Rewording for "make an intervention".
[bpt/guile.git] / libguile / numbers.c
1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
2 *
3 * Portions Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories
4 * and Bellcore. See scm_divide.
5 *
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23 \f
24 /* General assumptions:
25 * All objects satisfying SCM_BIGP() are too large to fit in a fixnum.
26 * If an object satisfies integer?, it's either an inum, a bignum, or a real.
27 * If floor (r) == r, r is an int, and mpz_set_d will DTRT.
28 * XXX What about infinities? They are equal to their own floor! -mhw
29 * All objects satisfying SCM_FRACTIONP are never an integer.
30 */
31
32 /* TODO:
33
34 - see if special casing bignums and reals in integer-exponent when
35 possible (to use mpz_pow and mpf_pow_ui) is faster.
36
37 - look in to better short-circuiting of common cases in
38 integer-expt and elsewhere.
39
40 - see if direct mpz operations can help in ash and elsewhere.
41
42 */
43
44 #ifdef HAVE_CONFIG_H
45 # include <config.h>
46 #endif
47
48 #include <math.h>
49 #include <string.h>
50 #include <unicase.h>
51 #include <unictype.h>
52
53 #if HAVE_COMPLEX_H
54 #include <complex.h>
55 #endif
56
57 #include "libguile/_scm.h"
58 #include "libguile/feature.h"
59 #include "libguile/ports.h"
60 #include "libguile/root.h"
61 #include "libguile/smob.h"
62 #include "libguile/strings.h"
63 #include "libguile/bdw-gc.h"
64
65 #include "libguile/validate.h"
66 #include "libguile/numbers.h"
67 #include "libguile/deprecation.h"
68
69 #include "libguile/eq.h"
70
71 /* values per glibc, if not already defined */
72 #ifndef M_LOG10E
73 #define M_LOG10E 0.43429448190325182765
74 #endif
75 #ifndef M_PI
76 #define M_PI 3.14159265358979323846
77 #endif
78
79 typedef scm_t_signed_bits scm_t_inum;
80 #define scm_from_inum(x) (scm_from_signed_integer (x))
81
82 /* Tests to see if a C double is neither infinite nor a NaN.
83 TODO: if it's available, use C99's isfinite(x) instead */
84 #define DOUBLE_IS_FINITE(x) (!isinf(x) && !isnan(x))
85
86 /* On some platforms, isinf(x) returns 0, 1 or -1, indicating the sign
87 of the infinity, but other platforms return a boolean only. */
88 #define DOUBLE_IS_POSITIVE_INFINITY(x) (isinf(x) && ((x) > 0))
89 #define DOUBLE_IS_NEGATIVE_INFINITY(x) (isinf(x) && ((x) < 0))
90
91 \f
92
93 /*
94 Wonder if this might be faster for some of our code? A switch on
95 the numtag would jump directly to the right case, and the
96 SCM_I_NUMTAG code might be faster than repeated SCM_FOOP tests...
97
98 #define SCM_I_NUMTAG_NOTNUM 0
99 #define SCM_I_NUMTAG_INUM 1
100 #define SCM_I_NUMTAG_BIG scm_tc16_big
101 #define SCM_I_NUMTAG_REAL scm_tc16_real
102 #define SCM_I_NUMTAG_COMPLEX scm_tc16_complex
103 #define SCM_I_NUMTAG(x) \
104 (SCM_I_INUMP(x) ? SCM_I_NUMTAG_INUM \
105 : (SCM_IMP(x) ? SCM_I_NUMTAG_NOTNUM \
106 : (((0xfcff & SCM_CELL_TYPE (x)) == scm_tc7_number) ? SCM_TYP16(x) \
107 : SCM_I_NUMTAG_NOTNUM)))
108 */
109 /* the macro above will not work as is with fractions */
110
111
112 static SCM flo0;
113 static SCM exactly_one_half;
114 static SCM flo_log10e;
115
116 #define SCM_SWAP(x, y) do { SCM __t = x; x = y; y = __t; } while (0)
117
118 /* FLOBUFLEN is the maximum number of characters neccessary for the
119 * printed or scm_string representation of an inexact number.
120 */
121 #define FLOBUFLEN (40+2*(sizeof(double)/sizeof(char)*SCM_CHAR_BIT*3+9)/10)
122
123
124 #if !defined (HAVE_ASINH)
125 static double asinh (double x) { return log (x + sqrt (x * x + 1)); }
126 #endif
127 #if !defined (HAVE_ACOSH)
128 static double acosh (double x) { return log (x + sqrt (x * x - 1)); }
129 #endif
130 #if !defined (HAVE_ATANH)
131 static double atanh (double x) { return 0.5 * log ((1 + x) / (1 - x)); }
132 #endif
133
134 /* mpz_cmp_d in gmp 4.1.3 doesn't recognise infinities, so xmpz_cmp_d uses
135 an explicit check. In some future gmp (don't know what version number),
136 mpz_cmp_d is supposed to do this itself. */
137 #if 1
138 #define xmpz_cmp_d(z, d) \
139 (isinf (d) ? (d < 0.0 ? 1 : -1) : mpz_cmp_d (z, d))
140 #else
141 #define xmpz_cmp_d(z, d) mpz_cmp_d (z, d)
142 #endif
143
144
145 #if defined (GUILE_I)
146 #if HAVE_COMPLEX_DOUBLE
147
148 /* For an SCM object Z which is a complex number (ie. satisfies
149 SCM_COMPLEXP), return its value as a C level "complex double". */
150 #define SCM_COMPLEX_VALUE(z) \
151 (SCM_COMPLEX_REAL (z) + GUILE_I * SCM_COMPLEX_IMAG (z))
152
153 static inline SCM scm_from_complex_double (complex double z) SCM_UNUSED;
154
155 /* Convert a C "complex double" to an SCM value. */
156 static inline SCM
157 scm_from_complex_double (complex double z)
158 {
159 return scm_c_make_rectangular (creal (z), cimag (z));
160 }
161
162 #endif /* HAVE_COMPLEX_DOUBLE */
163 #endif /* GUILE_I */
164
165 \f
166
167 static mpz_t z_negative_one;
168
169 \f
170 /* Clear the `mpz_t' embedded in bignum PTR. */
171 static void
172 finalize_bignum (GC_PTR ptr, GC_PTR data)
173 {
174 SCM bignum;
175
176 bignum = PTR2SCM (ptr);
177 mpz_clear (SCM_I_BIG_MPZ (bignum));
178 }
179
180 /* Return a new uninitialized bignum. */
181 static inline SCM
182 make_bignum (void)
183 {
184 scm_t_bits *p;
185 GC_finalization_proc prev_finalizer;
186 GC_PTR prev_finalizer_data;
187
188 /* Allocate one word for the type tag and enough room for an `mpz_t'. */
189 p = scm_gc_malloc_pointerless (sizeof (scm_t_bits) + sizeof (mpz_t),
190 "bignum");
191 p[0] = scm_tc16_big;
192
193 GC_REGISTER_FINALIZER_NO_ORDER (p, finalize_bignum, NULL,
194 &prev_finalizer,
195 &prev_finalizer_data);
196
197 return SCM_PACK (p);
198 }
199
200
201 SCM
202 scm_i_mkbig ()
203 {
204 /* Return a newly created bignum. */
205 SCM z = make_bignum ();
206 mpz_init (SCM_I_BIG_MPZ (z));
207 return z;
208 }
209
210 static SCM
211 scm_i_inum2big (scm_t_inum x)
212 {
213 /* Return a newly created bignum initialized to X. */
214 SCM z = make_bignum ();
215 #if SIZEOF_VOID_P == SIZEOF_LONG
216 mpz_init_set_si (SCM_I_BIG_MPZ (z), x);
217 #else
218 /* Note that in this case, you'll also have to check all mpz_*_ui and
219 mpz_*_si invocations in Guile. */
220 #error creation of mpz not implemented for this inum size
221 #endif
222 return z;
223 }
224
225 SCM
226 scm_i_long2big (long x)
227 {
228 /* Return a newly created bignum initialized to X. */
229 SCM z = make_bignum ();
230 mpz_init_set_si (SCM_I_BIG_MPZ (z), x);
231 return z;
232 }
233
234 SCM
235 scm_i_ulong2big (unsigned long x)
236 {
237 /* Return a newly created bignum initialized to X. */
238 SCM z = make_bignum ();
239 mpz_init_set_ui (SCM_I_BIG_MPZ (z), x);
240 return z;
241 }
242
243 SCM
244 scm_i_clonebig (SCM src_big, int same_sign_p)
245 {
246 /* Copy src_big's value, negate it if same_sign_p is false, and return. */
247 SCM z = make_bignum ();
248 mpz_init_set (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (src_big));
249 if (!same_sign_p)
250 mpz_neg (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (z));
251 return z;
252 }
253
254 int
255 scm_i_bigcmp (SCM x, SCM y)
256 {
257 /* Return neg if x < y, pos if x > y, and 0 if x == y */
258 /* presume we already know x and y are bignums */
259 int result = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
260 scm_remember_upto_here_2 (x, y);
261 return result;
262 }
263
264 SCM
265 scm_i_dbl2big (double d)
266 {
267 /* results are only defined if d is an integer */
268 SCM z = make_bignum ();
269 mpz_init_set_d (SCM_I_BIG_MPZ (z), d);
270 return z;
271 }
272
273 /* Convert a integer in double representation to a SCM number. */
274
275 SCM
276 scm_i_dbl2num (double u)
277 {
278 /* SCM_MOST_POSITIVE_FIXNUM+1 and SCM_MOST_NEGATIVE_FIXNUM are both
279 powers of 2, so there's no rounding when making "double" values
280 from them. If plain SCM_MOST_POSITIVE_FIXNUM was used it could
281 get rounded on a 64-bit machine, hence the "+1".
282
283 The use of floor() to force to an integer value ensures we get a
284 "numerically closest" value without depending on how a
285 double->long cast or how mpz_set_d will round. For reference,
286 double->long probably follows the hardware rounding mode,
287 mpz_set_d truncates towards zero. */
288
289 /* XXX - what happens when SCM_MOST_POSITIVE_FIXNUM etc is not
290 representable as a double? */
291
292 if (u < (double) (SCM_MOST_POSITIVE_FIXNUM+1)
293 && u >= (double) SCM_MOST_NEGATIVE_FIXNUM)
294 return SCM_I_MAKINUM ((scm_t_inum) u);
295 else
296 return scm_i_dbl2big (u);
297 }
298
299 /* scm_i_big2dbl() rounds to the closest representable double, in accordance
300 with R5RS exact->inexact.
301
302 The approach is to use mpz_get_d to pick out the high DBL_MANT_DIG bits
303 (ie. truncate towards zero), then adjust to get the closest double by
304 examining the next lower bit and adding 1 (to the absolute value) if
305 necessary.
306
307 Bignums exactly half way between representable doubles are rounded to the
308 next higher absolute value (ie. away from zero). This seems like an
309 adequate interpretation of R5RS "numerically closest", and it's easier
310 and faster than a full "nearest-even" style.
311
312 The bit test must be done on the absolute value of the mpz_t, which means
313 we need to use mpz_getlimbn. mpz_tstbit is not right, it treats
314 negatives as twos complement.
315
316 In current gmp 4.1.3, mpz_get_d rounding is unspecified. It ends up
317 following the hardware rounding mode, but applied to the absolute value
318 of the mpz_t operand. This is not what we want so we put the high
319 DBL_MANT_DIG bits into a temporary. In some future gmp, don't know when,
320 mpz_get_d is supposed to always truncate towards zero.
321
322 ENHANCE-ME: The temporary init+clear to force the rounding in gmp 4.1.3
323 is a slowdown. It'd be faster to pick out the relevant high bits with
324 mpz_getlimbn if we could be bothered coding that, and if the new
325 truncating gmp doesn't come out. */
326
327 double
328 scm_i_big2dbl (SCM b)
329 {
330 double result;
331 size_t bits;
332
333 bits = mpz_sizeinbase (SCM_I_BIG_MPZ (b), 2);
334
335 #if 1
336 {
337 /* Current GMP, eg. 4.1.3, force truncation towards zero */
338 mpz_t tmp;
339 if (bits > DBL_MANT_DIG)
340 {
341 size_t shift = bits - DBL_MANT_DIG;
342 mpz_init2 (tmp, DBL_MANT_DIG);
343 mpz_tdiv_q_2exp (tmp, SCM_I_BIG_MPZ (b), shift);
344 result = ldexp (mpz_get_d (tmp), shift);
345 mpz_clear (tmp);
346 }
347 else
348 {
349 result = mpz_get_d (SCM_I_BIG_MPZ (b));
350 }
351 }
352 #else
353 /* Future GMP */
354 result = mpz_get_d (SCM_I_BIG_MPZ (b));
355 #endif
356
357 if (bits > DBL_MANT_DIG)
358 {
359 unsigned long pos = bits - DBL_MANT_DIG - 1;
360 /* test bit number "pos" in absolute value */
361 if (mpz_getlimbn (SCM_I_BIG_MPZ (b), pos / GMP_NUMB_BITS)
362 & ((mp_limb_t) 1 << (pos % GMP_NUMB_BITS)))
363 {
364 result += ldexp ((double) mpz_sgn (SCM_I_BIG_MPZ (b)), pos + 1);
365 }
366 }
367
368 scm_remember_upto_here_1 (b);
369 return result;
370 }
371
372 SCM
373 scm_i_normbig (SCM b)
374 {
375 /* convert a big back to a fixnum if it'll fit */
376 /* presume b is a bignum */
377 if (mpz_fits_slong_p (SCM_I_BIG_MPZ (b)))
378 {
379 scm_t_inum val = mpz_get_si (SCM_I_BIG_MPZ (b));
380 if (SCM_FIXABLE (val))
381 b = SCM_I_MAKINUM (val);
382 }
383 return b;
384 }
385
386 static SCM_C_INLINE_KEYWORD SCM
387 scm_i_mpz2num (mpz_t b)
388 {
389 /* convert a mpz number to a SCM number. */
390 if (mpz_fits_slong_p (b))
391 {
392 scm_t_inum val = mpz_get_si (b);
393 if (SCM_FIXABLE (val))
394 return SCM_I_MAKINUM (val);
395 }
396
397 {
398 SCM z = make_bignum ();
399 mpz_init_set (SCM_I_BIG_MPZ (z), b);
400 return z;
401 }
402 }
403
404 /* this is needed when we want scm_divide to make a float, not a ratio, even if passed two ints */
405 static SCM scm_divide2real (SCM x, SCM y);
406
407 static SCM
408 scm_i_make_ratio (SCM numerator, SCM denominator)
409 #define FUNC_NAME "make-ratio"
410 {
411 /* First make sure the arguments are proper.
412 */
413 if (SCM_I_INUMP (denominator))
414 {
415 if (scm_is_eq (denominator, SCM_INUM0))
416 scm_num_overflow ("make-ratio");
417 if (scm_is_eq (denominator, SCM_INUM1))
418 return numerator;
419 }
420 else
421 {
422 if (!(SCM_BIGP(denominator)))
423 SCM_WRONG_TYPE_ARG (2, denominator);
424 }
425 if (!SCM_I_INUMP (numerator) && !SCM_BIGP (numerator))
426 SCM_WRONG_TYPE_ARG (1, numerator);
427
428 /* Then flip signs so that the denominator is positive.
429 */
430 if (scm_is_true (scm_negative_p (denominator)))
431 {
432 numerator = scm_difference (numerator, SCM_UNDEFINED);
433 denominator = scm_difference (denominator, SCM_UNDEFINED);
434 }
435
436 /* Now consider for each of the four fixnum/bignum combinations
437 whether the rational number is really an integer.
438 */
439 if (SCM_I_INUMP (numerator))
440 {
441 scm_t_inum x = SCM_I_INUM (numerator);
442 if (scm_is_eq (numerator, SCM_INUM0))
443 return SCM_INUM0;
444 if (SCM_I_INUMP (denominator))
445 {
446 scm_t_inum y;
447 y = SCM_I_INUM (denominator);
448 if (x == y)
449 return SCM_INUM1;
450 if ((x % y) == 0)
451 return SCM_I_MAKINUM (x / y);
452 }
453 else
454 {
455 /* When x == SCM_MOST_NEGATIVE_FIXNUM we could have the negative
456 of that value for the denominator, as a bignum. Apart from
457 that case, abs(bignum) > abs(inum) so inum/bignum is not an
458 integer. */
459 if (x == SCM_MOST_NEGATIVE_FIXNUM
460 && mpz_cmp_ui (SCM_I_BIG_MPZ (denominator),
461 - SCM_MOST_NEGATIVE_FIXNUM) == 0)
462 return SCM_I_MAKINUM(-1);
463 }
464 }
465 else if (SCM_BIGP (numerator))
466 {
467 if (SCM_I_INUMP (denominator))
468 {
469 scm_t_inum yy = SCM_I_INUM (denominator);
470 if (mpz_divisible_ui_p (SCM_I_BIG_MPZ (numerator), yy))
471 return scm_divide (numerator, denominator);
472 }
473 else
474 {
475 if (scm_is_eq (numerator, denominator))
476 return SCM_INUM1;
477 if (mpz_divisible_p (SCM_I_BIG_MPZ (numerator),
478 SCM_I_BIG_MPZ (denominator)))
479 return scm_divide(numerator, denominator);
480 }
481 }
482
483 /* No, it's a proper fraction.
484 */
485 {
486 SCM divisor = scm_gcd (numerator, denominator);
487 if (!(scm_is_eq (divisor, SCM_INUM1)))
488 {
489 numerator = scm_divide (numerator, divisor);
490 denominator = scm_divide (denominator, divisor);
491 }
492
493 return scm_double_cell (scm_tc16_fraction,
494 SCM_UNPACK (numerator),
495 SCM_UNPACK (denominator), 0);
496 }
497 }
498 #undef FUNC_NAME
499
500 double
501 scm_i_fraction2double (SCM z)
502 {
503 return scm_to_double (scm_divide2real (SCM_FRACTION_NUMERATOR (z),
504 SCM_FRACTION_DENOMINATOR (z)));
505 }
506
507 static int
508 double_is_non_negative_zero (double x)
509 {
510 static double zero = 0.0;
511
512 return !memcmp (&x, &zero, sizeof(double));
513 }
514
515 SCM_PRIMITIVE_GENERIC (scm_exact_p, "exact?", 1, 0, 0,
516 (SCM x),
517 "Return @code{#t} if @var{x} is an exact number, @code{#f}\n"
518 "otherwise.")
519 #define FUNC_NAME s_scm_exact_p
520 {
521 if (SCM_INEXACTP (x))
522 return SCM_BOOL_F;
523 else if (SCM_NUMBERP (x))
524 return SCM_BOOL_T;
525 else
526 SCM_WTA_DISPATCH_1 (g_scm_exact_p, x, 1, s_scm_exact_p);
527 }
528 #undef FUNC_NAME
529
530
531 SCM_PRIMITIVE_GENERIC (scm_inexact_p, "inexact?", 1, 0, 0,
532 (SCM x),
533 "Return @code{#t} if @var{x} is an inexact number, @code{#f}\n"
534 "else.")
535 #define FUNC_NAME s_scm_inexact_p
536 {
537 if (SCM_INEXACTP (x))
538 return SCM_BOOL_T;
539 else if (SCM_NUMBERP (x))
540 return SCM_BOOL_F;
541 else
542 SCM_WTA_DISPATCH_1 (g_scm_inexact_p, x, 1, s_scm_inexact_p);
543 }
544 #undef FUNC_NAME
545
546
547 SCM_PRIMITIVE_GENERIC (scm_odd_p, "odd?", 1, 0, 0,
548 (SCM n),
549 "Return @code{#t} if @var{n} is an odd number, @code{#f}\n"
550 "otherwise.")
551 #define FUNC_NAME s_scm_odd_p
552 {
553 if (SCM_I_INUMP (n))
554 {
555 scm_t_inum val = SCM_I_INUM (n);
556 return scm_from_bool ((val & 1L) != 0);
557 }
558 else if (SCM_BIGP (n))
559 {
560 int odd_p = mpz_odd_p (SCM_I_BIG_MPZ (n));
561 scm_remember_upto_here_1 (n);
562 return scm_from_bool (odd_p);
563 }
564 else if (SCM_REALP (n))
565 {
566 double val = SCM_REAL_VALUE (n);
567 if (DOUBLE_IS_FINITE (val))
568 {
569 double rem = fabs (fmod (val, 2.0));
570 if (rem == 1.0)
571 return SCM_BOOL_T;
572 else if (rem == 0.0)
573 return SCM_BOOL_F;
574 }
575 }
576 SCM_WTA_DISPATCH_1 (g_scm_odd_p, n, 1, s_scm_odd_p);
577 }
578 #undef FUNC_NAME
579
580
581 SCM_PRIMITIVE_GENERIC (scm_even_p, "even?", 1, 0, 0,
582 (SCM n),
583 "Return @code{#t} if @var{n} is an even number, @code{#f}\n"
584 "otherwise.")
585 #define FUNC_NAME s_scm_even_p
586 {
587 if (SCM_I_INUMP (n))
588 {
589 scm_t_inum val = SCM_I_INUM (n);
590 return scm_from_bool ((val & 1L) == 0);
591 }
592 else if (SCM_BIGP (n))
593 {
594 int even_p = mpz_even_p (SCM_I_BIG_MPZ (n));
595 scm_remember_upto_here_1 (n);
596 return scm_from_bool (even_p);
597 }
598 else if (SCM_REALP (n))
599 {
600 double val = SCM_REAL_VALUE (n);
601 if (DOUBLE_IS_FINITE (val))
602 {
603 double rem = fabs (fmod (val, 2.0));
604 if (rem == 1.0)
605 return SCM_BOOL_F;
606 else if (rem == 0.0)
607 return SCM_BOOL_T;
608 }
609 }
610 SCM_WTA_DISPATCH_1 (g_scm_even_p, n, 1, s_scm_even_p);
611 }
612 #undef FUNC_NAME
613
614 SCM_PRIMITIVE_GENERIC (scm_finite_p, "finite?", 1, 0, 0,
615 (SCM x),
616 "Return @code{#t} if the real number @var{x} is neither\n"
617 "infinite nor a NaN, @code{#f} otherwise.")
618 #define FUNC_NAME s_scm_finite_p
619 {
620 if (SCM_REALP (x))
621 return scm_from_bool (DOUBLE_IS_FINITE (SCM_REAL_VALUE (x)));
622 else if (scm_is_real (x))
623 return SCM_BOOL_T;
624 else
625 SCM_WTA_DISPATCH_1 (g_scm_finite_p, x, 1, s_scm_finite_p);
626 }
627 #undef FUNC_NAME
628
629 SCM_PRIMITIVE_GENERIC (scm_inf_p, "inf?", 1, 0, 0,
630 (SCM x),
631 "Return @code{#t} if the real number @var{x} is @samp{+inf.0} or\n"
632 "@samp{-inf.0}. Otherwise return @code{#f}.")
633 #define FUNC_NAME s_scm_inf_p
634 {
635 if (SCM_REALP (x))
636 return scm_from_bool (isinf (SCM_REAL_VALUE (x)));
637 else if (scm_is_real (x))
638 return SCM_BOOL_F;
639 else
640 SCM_WTA_DISPATCH_1 (g_scm_inf_p, x, 1, s_scm_inf_p);
641 }
642 #undef FUNC_NAME
643
644 SCM_PRIMITIVE_GENERIC (scm_nan_p, "nan?", 1, 0, 0,
645 (SCM x),
646 "Return @code{#t} if the real number @var{x} is a NaN,\n"
647 "or @code{#f} otherwise.")
648 #define FUNC_NAME s_scm_nan_p
649 {
650 if (SCM_REALP (x))
651 return scm_from_bool (isnan (SCM_REAL_VALUE (x)));
652 else if (scm_is_real (x))
653 return SCM_BOOL_F;
654 else
655 SCM_WTA_DISPATCH_1 (g_scm_nan_p, x, 1, s_scm_nan_p);
656 }
657 #undef FUNC_NAME
658
659 /* Guile's idea of infinity. */
660 static double guile_Inf;
661
662 /* Guile's idea of not a number. */
663 static double guile_NaN;
664
665 static void
666 guile_ieee_init (void)
667 {
668 /* Some version of gcc on some old version of Linux used to crash when
669 trying to make Inf and NaN. */
670
671 #ifdef INFINITY
672 /* C99 INFINITY, when available.
673 FIXME: The standard allows for INFINITY to be something that overflows
674 at compile time. We ought to have a configure test to check for that
675 before trying to use it. (But in practice we believe this is not a
676 problem on any system guile is likely to target.) */
677 guile_Inf = INFINITY;
678 #elif defined HAVE_DINFINITY
679 /* OSF */
680 extern unsigned int DINFINITY[2];
681 guile_Inf = (*((double *) (DINFINITY)));
682 #else
683 double tmp = 1e+10;
684 guile_Inf = tmp;
685 for (;;)
686 {
687 guile_Inf *= 1e+10;
688 if (guile_Inf == tmp)
689 break;
690 tmp = guile_Inf;
691 }
692 #endif
693
694 #ifdef NAN
695 /* C99 NAN, when available */
696 guile_NaN = NAN;
697 #elif defined HAVE_DQNAN
698 {
699 /* OSF */
700 extern unsigned int DQNAN[2];
701 guile_NaN = (*((double *)(DQNAN)));
702 }
703 #else
704 guile_NaN = guile_Inf / guile_Inf;
705 #endif
706 }
707
708 SCM_DEFINE (scm_inf, "inf", 0, 0, 0,
709 (void),
710 "Return Inf.")
711 #define FUNC_NAME s_scm_inf
712 {
713 static int initialized = 0;
714 if (! initialized)
715 {
716 guile_ieee_init ();
717 initialized = 1;
718 }
719 return scm_from_double (guile_Inf);
720 }
721 #undef FUNC_NAME
722
723 SCM_DEFINE (scm_nan, "nan", 0, 0, 0,
724 (void),
725 "Return NaN.")
726 #define FUNC_NAME s_scm_nan
727 {
728 static int initialized = 0;
729 if (!initialized)
730 {
731 guile_ieee_init ();
732 initialized = 1;
733 }
734 return scm_from_double (guile_NaN);
735 }
736 #undef FUNC_NAME
737
738
739 SCM_PRIMITIVE_GENERIC (scm_abs, "abs", 1, 0, 0,
740 (SCM x),
741 "Return the absolute value of @var{x}.")
742 #define FUNC_NAME s_scm_abs
743 {
744 if (SCM_I_INUMP (x))
745 {
746 scm_t_inum xx = SCM_I_INUM (x);
747 if (xx >= 0)
748 return x;
749 else if (SCM_POSFIXABLE (-xx))
750 return SCM_I_MAKINUM (-xx);
751 else
752 return scm_i_inum2big (-xx);
753 }
754 else if (SCM_LIKELY (SCM_REALP (x)))
755 {
756 double xx = SCM_REAL_VALUE (x);
757 /* If x is a NaN then xx<0 is false so we return x unchanged */
758 if (xx < 0.0)
759 return scm_from_double (-xx);
760 /* Handle signed zeroes properly */
761 else if (SCM_UNLIKELY (xx == 0.0))
762 return flo0;
763 else
764 return x;
765 }
766 else if (SCM_BIGP (x))
767 {
768 const int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
769 if (sgn < 0)
770 return scm_i_clonebig (x, 0);
771 else
772 return x;
773 }
774 else if (SCM_FRACTIONP (x))
775 {
776 if (scm_is_false (scm_negative_p (SCM_FRACTION_NUMERATOR (x))))
777 return x;
778 return scm_i_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x), SCM_UNDEFINED),
779 SCM_FRACTION_DENOMINATOR (x));
780 }
781 else
782 SCM_WTA_DISPATCH_1 (g_scm_abs, x, 1, s_scm_abs);
783 }
784 #undef FUNC_NAME
785
786
787 SCM_PRIMITIVE_GENERIC (scm_quotient, "quotient", 2, 0, 0,
788 (SCM x, SCM y),
789 "Return the quotient of the numbers @var{x} and @var{y}.")
790 #define FUNC_NAME s_scm_quotient
791 {
792 if (SCM_LIKELY (SCM_I_INUMP (x)) || SCM_LIKELY (SCM_BIGP (x)))
793 {
794 if (SCM_LIKELY (SCM_I_INUMP (y)) || SCM_LIKELY (SCM_BIGP (y)))
795 return scm_truncate_quotient (x, y);
796 else
797 SCM_WTA_DISPATCH_2 (g_scm_quotient, x, y, SCM_ARG2, s_scm_quotient);
798 }
799 else
800 SCM_WTA_DISPATCH_2 (g_scm_quotient, x, y, SCM_ARG1, s_scm_quotient);
801 }
802 #undef FUNC_NAME
803
804 SCM_PRIMITIVE_GENERIC (scm_remainder, "remainder", 2, 0, 0,
805 (SCM x, SCM y),
806 "Return the remainder of the numbers @var{x} and @var{y}.\n"
807 "@lisp\n"
808 "(remainder 13 4) @result{} 1\n"
809 "(remainder -13 4) @result{} -1\n"
810 "@end lisp")
811 #define FUNC_NAME s_scm_remainder
812 {
813 if (SCM_LIKELY (SCM_I_INUMP (x)) || SCM_LIKELY (SCM_BIGP (x)))
814 {
815 if (SCM_LIKELY (SCM_I_INUMP (y)) || SCM_LIKELY (SCM_BIGP (y)))
816 return scm_truncate_remainder (x, y);
817 else
818 SCM_WTA_DISPATCH_2 (g_scm_remainder, x, y, SCM_ARG2, s_scm_remainder);
819 }
820 else
821 SCM_WTA_DISPATCH_2 (g_scm_remainder, x, y, SCM_ARG1, s_scm_remainder);
822 }
823 #undef FUNC_NAME
824
825
826 SCM_PRIMITIVE_GENERIC (scm_modulo, "modulo", 2, 0, 0,
827 (SCM x, SCM y),
828 "Return the modulo of the numbers @var{x} and @var{y}.\n"
829 "@lisp\n"
830 "(modulo 13 4) @result{} 1\n"
831 "(modulo -13 4) @result{} 3\n"
832 "@end lisp")
833 #define FUNC_NAME s_scm_modulo
834 {
835 if (SCM_LIKELY (SCM_I_INUMP (x)) || SCM_LIKELY (SCM_BIGP (x)))
836 {
837 if (SCM_LIKELY (SCM_I_INUMP (y)) || SCM_LIKELY (SCM_BIGP (y)))
838 return scm_floor_remainder (x, y);
839 else
840 SCM_WTA_DISPATCH_2 (g_scm_modulo, x, y, SCM_ARG2, s_scm_modulo);
841 }
842 else
843 SCM_WTA_DISPATCH_2 (g_scm_modulo, x, y, SCM_ARG1, s_scm_modulo);
844 }
845 #undef FUNC_NAME
846
847 /* two_valued_wta_dispatch_2 is a version of SCM_WTA_DISPATCH_2 for
848 two-valued functions. It is called from primitive generics that take
849 two arguments and return two values, when the core procedure is
850 unable to handle the given argument types. If there are GOOPS
851 methods for this primitive generic, it dispatches to GOOPS and, if
852 successful, expects two values to be returned, which are placed in
853 *rp1 and *rp2. If there are no GOOPS methods, it throws a
854 wrong-type-arg exception.
855
856 FIXME: This obviously belongs somewhere else, but until we decide on
857 the right API, it is here as a static function, because it is needed
858 by the *_divide functions below.
859 */
860 static void
861 two_valued_wta_dispatch_2 (SCM gf, SCM a1, SCM a2, int pos,
862 const char *subr, SCM *rp1, SCM *rp2)
863 {
864 if (SCM_UNPACK (gf))
865 scm_i_extract_values_2 (scm_call_generic_2 (gf, a1, a2), rp1, rp2);
866 else
867 scm_wrong_type_arg (subr, pos, (pos == SCM_ARG1) ? a1 : a2);
868 }
869
870 SCM_DEFINE (scm_euclidean_quotient, "euclidean-quotient", 2, 0, 0,
871 (SCM x, SCM y),
872 "Return the integer @var{q} such that\n"
873 "@math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
874 "where @math{0 <= @var{r} < abs(@var{y})}.\n"
875 "@lisp\n"
876 "(euclidean-quotient 123 10) @result{} 12\n"
877 "(euclidean-quotient 123 -10) @result{} -12\n"
878 "(euclidean-quotient -123 10) @result{} -13\n"
879 "(euclidean-quotient -123 -10) @result{} 13\n"
880 "(euclidean-quotient -123.2 -63.5) @result{} 2.0\n"
881 "(euclidean-quotient 16/3 -10/7) @result{} -3\n"
882 "@end lisp")
883 #define FUNC_NAME s_scm_euclidean_quotient
884 {
885 if (scm_is_false (scm_negative_p (y)))
886 return scm_floor_quotient (x, y);
887 else
888 return scm_ceiling_quotient (x, y);
889 }
890 #undef FUNC_NAME
891
892 SCM_DEFINE (scm_euclidean_remainder, "euclidean-remainder", 2, 0, 0,
893 (SCM x, SCM y),
894 "Return the real number @var{r} such that\n"
895 "@math{0 <= @var{r} < abs(@var{y})} and\n"
896 "@math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
897 "for some integer @var{q}.\n"
898 "@lisp\n"
899 "(euclidean-remainder 123 10) @result{} 3\n"
900 "(euclidean-remainder 123 -10) @result{} 3\n"
901 "(euclidean-remainder -123 10) @result{} 7\n"
902 "(euclidean-remainder -123 -10) @result{} 7\n"
903 "(euclidean-remainder -123.2 -63.5) @result{} 3.8\n"
904 "(euclidean-remainder 16/3 -10/7) @result{} 22/21\n"
905 "@end lisp")
906 #define FUNC_NAME s_scm_euclidean_remainder
907 {
908 if (scm_is_false (scm_negative_p (y)))
909 return scm_floor_remainder (x, y);
910 else
911 return scm_ceiling_remainder (x, y);
912 }
913 #undef FUNC_NAME
914
915 SCM_DEFINE (scm_i_euclidean_divide, "euclidean/", 2, 0, 0,
916 (SCM x, SCM y),
917 "Return the integer @var{q} and the real number @var{r}\n"
918 "such that @math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
919 "and @math{0 <= @var{r} < abs(@var{y})}.\n"
920 "@lisp\n"
921 "(euclidean/ 123 10) @result{} 12 and 3\n"
922 "(euclidean/ 123 -10) @result{} -12 and 3\n"
923 "(euclidean/ -123 10) @result{} -13 and 7\n"
924 "(euclidean/ -123 -10) @result{} 13 and 7\n"
925 "(euclidean/ -123.2 -63.5) @result{} 2.0 and 3.8\n"
926 "(euclidean/ 16/3 -10/7) @result{} -3 and 22/21\n"
927 "@end lisp")
928 #define FUNC_NAME s_scm_i_euclidean_divide
929 {
930 if (scm_is_false (scm_negative_p (y)))
931 return scm_i_floor_divide (x, y);
932 else
933 return scm_i_ceiling_divide (x, y);
934 }
935 #undef FUNC_NAME
936
937 void
938 scm_euclidean_divide (SCM x, SCM y, SCM *qp, SCM *rp)
939 {
940 if (scm_is_false (scm_negative_p (y)))
941 return scm_floor_divide (x, y, qp, rp);
942 else
943 return scm_ceiling_divide (x, y, qp, rp);
944 }
945
946 static SCM scm_i_inexact_floor_quotient (double x, double y);
947 static SCM scm_i_exact_rational_floor_quotient (SCM x, SCM y);
948
949 SCM_PRIMITIVE_GENERIC (scm_floor_quotient, "floor-quotient", 2, 0, 0,
950 (SCM x, SCM y),
951 "Return the floor of @math{@var{x} / @var{y}}.\n"
952 "@lisp\n"
953 "(floor-quotient 123 10) @result{} 12\n"
954 "(floor-quotient 123 -10) @result{} -13\n"
955 "(floor-quotient -123 10) @result{} -13\n"
956 "(floor-quotient -123 -10) @result{} 12\n"
957 "(floor-quotient -123.2 -63.5) @result{} 1.0\n"
958 "(floor-quotient 16/3 -10/7) @result{} -4\n"
959 "@end lisp")
960 #define FUNC_NAME s_scm_floor_quotient
961 {
962 if (SCM_LIKELY (SCM_I_INUMP (x)))
963 {
964 scm_t_inum xx = SCM_I_INUM (x);
965 if (SCM_LIKELY (SCM_I_INUMP (y)))
966 {
967 scm_t_inum yy = SCM_I_INUM (y);
968 scm_t_inum xx1 = xx;
969 scm_t_inum qq;
970 if (SCM_LIKELY (yy > 0))
971 {
972 if (SCM_UNLIKELY (xx < 0))
973 xx1 = xx - yy + 1;
974 }
975 else if (SCM_UNLIKELY (yy == 0))
976 scm_num_overflow (s_scm_floor_quotient);
977 else if (xx > 0)
978 xx1 = xx - yy - 1;
979 qq = xx1 / yy;
980 if (SCM_LIKELY (SCM_FIXABLE (qq)))
981 return SCM_I_MAKINUM (qq);
982 else
983 return scm_i_inum2big (qq);
984 }
985 else if (SCM_BIGP (y))
986 {
987 int sign = mpz_sgn (SCM_I_BIG_MPZ (y));
988 scm_remember_upto_here_1 (y);
989 if (sign > 0)
990 return SCM_I_MAKINUM ((xx < 0) ? -1 : 0);
991 else
992 return SCM_I_MAKINUM ((xx > 0) ? -1 : 0);
993 }
994 else if (SCM_REALP (y))
995 return scm_i_inexact_floor_quotient (xx, SCM_REAL_VALUE (y));
996 else if (SCM_FRACTIONP (y))
997 return scm_i_exact_rational_floor_quotient (x, y);
998 else
999 SCM_WTA_DISPATCH_2 (g_scm_floor_quotient, x, y, SCM_ARG2,
1000 s_scm_floor_quotient);
1001 }
1002 else if (SCM_BIGP (x))
1003 {
1004 if (SCM_LIKELY (SCM_I_INUMP (y)))
1005 {
1006 scm_t_inum yy = SCM_I_INUM (y);
1007 if (SCM_UNLIKELY (yy == 0))
1008 scm_num_overflow (s_scm_floor_quotient);
1009 else if (SCM_UNLIKELY (yy == 1))
1010 return x;
1011 else
1012 {
1013 SCM q = scm_i_mkbig ();
1014 if (yy > 0)
1015 mpz_fdiv_q_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (x), yy);
1016 else
1017 {
1018 mpz_cdiv_q_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (x), -yy);
1019 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
1020 }
1021 scm_remember_upto_here_1 (x);
1022 return scm_i_normbig (q);
1023 }
1024 }
1025 else if (SCM_BIGP (y))
1026 {
1027 SCM q = scm_i_mkbig ();
1028 mpz_fdiv_q (SCM_I_BIG_MPZ (q),
1029 SCM_I_BIG_MPZ (x),
1030 SCM_I_BIG_MPZ (y));
1031 scm_remember_upto_here_2 (x, y);
1032 return scm_i_normbig (q);
1033 }
1034 else if (SCM_REALP (y))
1035 return scm_i_inexact_floor_quotient
1036 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
1037 else if (SCM_FRACTIONP (y))
1038 return scm_i_exact_rational_floor_quotient (x, y);
1039 else
1040 SCM_WTA_DISPATCH_2 (g_scm_floor_quotient, x, y, SCM_ARG2,
1041 s_scm_floor_quotient);
1042 }
1043 else if (SCM_REALP (x))
1044 {
1045 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
1046 SCM_BIGP (y) || SCM_FRACTIONP (y))
1047 return scm_i_inexact_floor_quotient
1048 (SCM_REAL_VALUE (x), scm_to_double (y));
1049 else
1050 SCM_WTA_DISPATCH_2 (g_scm_floor_quotient, x, y, SCM_ARG2,
1051 s_scm_floor_quotient);
1052 }
1053 else if (SCM_FRACTIONP (x))
1054 {
1055 if (SCM_REALP (y))
1056 return scm_i_inexact_floor_quotient
1057 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
1058 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
1059 return scm_i_exact_rational_floor_quotient (x, y);
1060 else
1061 SCM_WTA_DISPATCH_2 (g_scm_floor_quotient, x, y, SCM_ARG2,
1062 s_scm_floor_quotient);
1063 }
1064 else
1065 SCM_WTA_DISPATCH_2 (g_scm_floor_quotient, x, y, SCM_ARG1,
1066 s_scm_floor_quotient);
1067 }
1068 #undef FUNC_NAME
1069
1070 static SCM
1071 scm_i_inexact_floor_quotient (double x, double y)
1072 {
1073 if (SCM_UNLIKELY (y == 0))
1074 scm_num_overflow (s_scm_floor_quotient); /* or return a NaN? */
1075 else
1076 return scm_from_double (floor (x / y));
1077 }
1078
1079 static SCM
1080 scm_i_exact_rational_floor_quotient (SCM x, SCM y)
1081 {
1082 return scm_floor_quotient
1083 (scm_product (scm_numerator (x), scm_denominator (y)),
1084 scm_product (scm_numerator (y), scm_denominator (x)));
1085 }
1086
1087 static SCM scm_i_inexact_floor_remainder (double x, double y);
1088 static SCM scm_i_exact_rational_floor_remainder (SCM x, SCM y);
1089
1090 SCM_PRIMITIVE_GENERIC (scm_floor_remainder, "floor-remainder", 2, 0, 0,
1091 (SCM x, SCM y),
1092 "Return the real number @var{r} such that\n"
1093 "@math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
1094 "where @math{@var{q} = floor(@var{x} / @var{y})}.\n"
1095 "@lisp\n"
1096 "(floor-remainder 123 10) @result{} 3\n"
1097 "(floor-remainder 123 -10) @result{} -7\n"
1098 "(floor-remainder -123 10) @result{} 7\n"
1099 "(floor-remainder -123 -10) @result{} -3\n"
1100 "(floor-remainder -123.2 -63.5) @result{} -59.7\n"
1101 "(floor-remainder 16/3 -10/7) @result{} -8/21\n"
1102 "@end lisp")
1103 #define FUNC_NAME s_scm_floor_remainder
1104 {
1105 if (SCM_LIKELY (SCM_I_INUMP (x)))
1106 {
1107 scm_t_inum xx = SCM_I_INUM (x);
1108 if (SCM_LIKELY (SCM_I_INUMP (y)))
1109 {
1110 scm_t_inum yy = SCM_I_INUM (y);
1111 if (SCM_UNLIKELY (yy == 0))
1112 scm_num_overflow (s_scm_floor_remainder);
1113 else
1114 {
1115 scm_t_inum rr = xx % yy;
1116 int needs_adjustment;
1117
1118 if (SCM_LIKELY (yy > 0))
1119 needs_adjustment = (rr < 0);
1120 else
1121 needs_adjustment = (rr > 0);
1122
1123 if (needs_adjustment)
1124 rr += yy;
1125 return SCM_I_MAKINUM (rr);
1126 }
1127 }
1128 else if (SCM_BIGP (y))
1129 {
1130 int sign = mpz_sgn (SCM_I_BIG_MPZ (y));
1131 scm_remember_upto_here_1 (y);
1132 if (sign > 0)
1133 {
1134 if (xx < 0)
1135 {
1136 SCM r = scm_i_mkbig ();
1137 mpz_sub_ui (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y), -xx);
1138 scm_remember_upto_here_1 (y);
1139 return scm_i_normbig (r);
1140 }
1141 else
1142 return x;
1143 }
1144 else if (xx <= 0)
1145 return x;
1146 else
1147 {
1148 SCM r = scm_i_mkbig ();
1149 mpz_add_ui (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y), xx);
1150 scm_remember_upto_here_1 (y);
1151 return scm_i_normbig (r);
1152 }
1153 }
1154 else if (SCM_REALP (y))
1155 return scm_i_inexact_floor_remainder (xx, SCM_REAL_VALUE (y));
1156 else if (SCM_FRACTIONP (y))
1157 return scm_i_exact_rational_floor_remainder (x, y);
1158 else
1159 SCM_WTA_DISPATCH_2 (g_scm_floor_remainder, x, y, SCM_ARG2,
1160 s_scm_floor_remainder);
1161 }
1162 else if (SCM_BIGP (x))
1163 {
1164 if (SCM_LIKELY (SCM_I_INUMP (y)))
1165 {
1166 scm_t_inum yy = SCM_I_INUM (y);
1167 if (SCM_UNLIKELY (yy == 0))
1168 scm_num_overflow (s_scm_floor_remainder);
1169 else
1170 {
1171 scm_t_inum rr;
1172 if (yy > 0)
1173 rr = mpz_fdiv_ui (SCM_I_BIG_MPZ (x), yy);
1174 else
1175 rr = -mpz_cdiv_ui (SCM_I_BIG_MPZ (x), -yy);
1176 scm_remember_upto_here_1 (x);
1177 return SCM_I_MAKINUM (rr);
1178 }
1179 }
1180 else if (SCM_BIGP (y))
1181 {
1182 SCM r = scm_i_mkbig ();
1183 mpz_fdiv_r (SCM_I_BIG_MPZ (r),
1184 SCM_I_BIG_MPZ (x),
1185 SCM_I_BIG_MPZ (y));
1186 scm_remember_upto_here_2 (x, y);
1187 return scm_i_normbig (r);
1188 }
1189 else if (SCM_REALP (y))
1190 return scm_i_inexact_floor_remainder
1191 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
1192 else if (SCM_FRACTIONP (y))
1193 return scm_i_exact_rational_floor_remainder (x, y);
1194 else
1195 SCM_WTA_DISPATCH_2 (g_scm_floor_remainder, x, y, SCM_ARG2,
1196 s_scm_floor_remainder);
1197 }
1198 else if (SCM_REALP (x))
1199 {
1200 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
1201 SCM_BIGP (y) || SCM_FRACTIONP (y))
1202 return scm_i_inexact_floor_remainder
1203 (SCM_REAL_VALUE (x), scm_to_double (y));
1204 else
1205 SCM_WTA_DISPATCH_2 (g_scm_floor_remainder, x, y, SCM_ARG2,
1206 s_scm_floor_remainder);
1207 }
1208 else if (SCM_FRACTIONP (x))
1209 {
1210 if (SCM_REALP (y))
1211 return scm_i_inexact_floor_remainder
1212 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
1213 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
1214 return scm_i_exact_rational_floor_remainder (x, y);
1215 else
1216 SCM_WTA_DISPATCH_2 (g_scm_floor_remainder, x, y, SCM_ARG2,
1217 s_scm_floor_remainder);
1218 }
1219 else
1220 SCM_WTA_DISPATCH_2 (g_scm_floor_remainder, x, y, SCM_ARG1,
1221 s_scm_floor_remainder);
1222 }
1223 #undef FUNC_NAME
1224
1225 static SCM
1226 scm_i_inexact_floor_remainder (double x, double y)
1227 {
1228 /* Although it would be more efficient to use fmod here, we can't
1229 because it would in some cases produce results inconsistent with
1230 scm_i_inexact_floor_quotient, such that x != q * y + r (not even
1231 close). In particular, when x is very close to a multiple of y,
1232 then r might be either 0.0 or y, but those two cases must
1233 correspond to different choices of q. If r = 0.0 then q must be
1234 x/y, and if r = y then q must be x/y-1. If quotient chooses one
1235 and remainder chooses the other, it would be bad. */
1236 if (SCM_UNLIKELY (y == 0))
1237 scm_num_overflow (s_scm_floor_remainder); /* or return a NaN? */
1238 else
1239 return scm_from_double (x - y * floor (x / y));
1240 }
1241
1242 static SCM
1243 scm_i_exact_rational_floor_remainder (SCM x, SCM y)
1244 {
1245 SCM xd = scm_denominator (x);
1246 SCM yd = scm_denominator (y);
1247 SCM r1 = scm_floor_remainder (scm_product (scm_numerator (x), yd),
1248 scm_product (scm_numerator (y), xd));
1249 return scm_divide (r1, scm_product (xd, yd));
1250 }
1251
1252
1253 static void scm_i_inexact_floor_divide (double x, double y,
1254 SCM *qp, SCM *rp);
1255 static void scm_i_exact_rational_floor_divide (SCM x, SCM y,
1256 SCM *qp, SCM *rp);
1257
1258 SCM_PRIMITIVE_GENERIC (scm_i_floor_divide, "floor/", 2, 0, 0,
1259 (SCM x, SCM y),
1260 "Return the integer @var{q} and the real number @var{r}\n"
1261 "such that @math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
1262 "and @math{@var{q} = floor(@var{x} / @var{y})}.\n"
1263 "@lisp\n"
1264 "(floor/ 123 10) @result{} 12 and 3\n"
1265 "(floor/ 123 -10) @result{} -13 and -7\n"
1266 "(floor/ -123 10) @result{} -13 and 7\n"
1267 "(floor/ -123 -10) @result{} 12 and -3\n"
1268 "(floor/ -123.2 -63.5) @result{} 1.0 and -59.7\n"
1269 "(floor/ 16/3 -10/7) @result{} -4 and -8/21\n"
1270 "@end lisp")
1271 #define FUNC_NAME s_scm_i_floor_divide
1272 {
1273 SCM q, r;
1274
1275 scm_floor_divide(x, y, &q, &r);
1276 return scm_values (scm_list_2 (q, r));
1277 }
1278 #undef FUNC_NAME
1279
1280 #define s_scm_floor_divide s_scm_i_floor_divide
1281 #define g_scm_floor_divide g_scm_i_floor_divide
1282
1283 void
1284 scm_floor_divide (SCM x, SCM y, SCM *qp, SCM *rp)
1285 {
1286 if (SCM_LIKELY (SCM_I_INUMP (x)))
1287 {
1288 scm_t_inum xx = SCM_I_INUM (x);
1289 if (SCM_LIKELY (SCM_I_INUMP (y)))
1290 {
1291 scm_t_inum yy = SCM_I_INUM (y);
1292 if (SCM_UNLIKELY (yy == 0))
1293 scm_num_overflow (s_scm_floor_divide);
1294 else
1295 {
1296 scm_t_inum qq = xx / yy;
1297 scm_t_inum rr = xx % yy;
1298 int needs_adjustment;
1299
1300 if (SCM_LIKELY (yy > 0))
1301 needs_adjustment = (rr < 0);
1302 else
1303 needs_adjustment = (rr > 0);
1304
1305 if (needs_adjustment)
1306 {
1307 rr += yy;
1308 qq--;
1309 }
1310
1311 if (SCM_LIKELY (SCM_FIXABLE (qq)))
1312 *qp = SCM_I_MAKINUM (qq);
1313 else
1314 *qp = scm_i_inum2big (qq);
1315 *rp = SCM_I_MAKINUM (rr);
1316 }
1317 return;
1318 }
1319 else if (SCM_BIGP (y))
1320 {
1321 int sign = mpz_sgn (SCM_I_BIG_MPZ (y));
1322 scm_remember_upto_here_1 (y);
1323 if (sign > 0)
1324 {
1325 if (xx < 0)
1326 {
1327 SCM r = scm_i_mkbig ();
1328 mpz_sub_ui (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y), -xx);
1329 scm_remember_upto_here_1 (y);
1330 *qp = SCM_I_MAKINUM (-1);
1331 *rp = scm_i_normbig (r);
1332 }
1333 else
1334 {
1335 *qp = SCM_INUM0;
1336 *rp = x;
1337 }
1338 }
1339 else if (xx <= 0)
1340 {
1341 *qp = SCM_INUM0;
1342 *rp = x;
1343 }
1344 else
1345 {
1346 SCM r = scm_i_mkbig ();
1347 mpz_add_ui (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y), xx);
1348 scm_remember_upto_here_1 (y);
1349 *qp = SCM_I_MAKINUM (-1);
1350 *rp = scm_i_normbig (r);
1351 }
1352 return;
1353 }
1354 else if (SCM_REALP (y))
1355 return scm_i_inexact_floor_divide (xx, SCM_REAL_VALUE (y), qp, rp);
1356 else if (SCM_FRACTIONP (y))
1357 return scm_i_exact_rational_floor_divide (x, y, qp, rp);
1358 else
1359 return two_valued_wta_dispatch_2 (g_scm_floor_divide, x, y, SCM_ARG2,
1360 s_scm_floor_divide, qp, rp);
1361 }
1362 else if (SCM_BIGP (x))
1363 {
1364 if (SCM_LIKELY (SCM_I_INUMP (y)))
1365 {
1366 scm_t_inum yy = SCM_I_INUM (y);
1367 if (SCM_UNLIKELY (yy == 0))
1368 scm_num_overflow (s_scm_floor_divide);
1369 else
1370 {
1371 SCM q = scm_i_mkbig ();
1372 SCM r = scm_i_mkbig ();
1373 if (yy > 0)
1374 mpz_fdiv_qr_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
1375 SCM_I_BIG_MPZ (x), yy);
1376 else
1377 {
1378 mpz_cdiv_qr_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
1379 SCM_I_BIG_MPZ (x), -yy);
1380 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
1381 }
1382 scm_remember_upto_here_1 (x);
1383 *qp = scm_i_normbig (q);
1384 *rp = scm_i_normbig (r);
1385 }
1386 return;
1387 }
1388 else if (SCM_BIGP (y))
1389 {
1390 SCM q = scm_i_mkbig ();
1391 SCM r = scm_i_mkbig ();
1392 mpz_fdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
1393 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
1394 scm_remember_upto_here_2 (x, y);
1395 *qp = scm_i_normbig (q);
1396 *rp = scm_i_normbig (r);
1397 return;
1398 }
1399 else if (SCM_REALP (y))
1400 return scm_i_inexact_floor_divide
1401 (scm_i_big2dbl (x), SCM_REAL_VALUE (y), qp, rp);
1402 else if (SCM_FRACTIONP (y))
1403 return scm_i_exact_rational_floor_divide (x, y, qp, rp);
1404 else
1405 return two_valued_wta_dispatch_2 (g_scm_floor_divide, x, y, SCM_ARG2,
1406 s_scm_floor_divide, qp, rp);
1407 }
1408 else if (SCM_REALP (x))
1409 {
1410 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
1411 SCM_BIGP (y) || SCM_FRACTIONP (y))
1412 return scm_i_inexact_floor_divide
1413 (SCM_REAL_VALUE (x), scm_to_double (y), qp, rp);
1414 else
1415 return two_valued_wta_dispatch_2 (g_scm_floor_divide, x, y, SCM_ARG2,
1416 s_scm_floor_divide, qp, rp);
1417 }
1418 else if (SCM_FRACTIONP (x))
1419 {
1420 if (SCM_REALP (y))
1421 return scm_i_inexact_floor_divide
1422 (scm_i_fraction2double (x), SCM_REAL_VALUE (y), qp, rp);
1423 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
1424 return scm_i_exact_rational_floor_divide (x, y, qp, rp);
1425 else
1426 return two_valued_wta_dispatch_2 (g_scm_floor_divide, x, y, SCM_ARG2,
1427 s_scm_floor_divide, qp, rp);
1428 }
1429 else
1430 return two_valued_wta_dispatch_2 (g_scm_floor_divide, x, y, SCM_ARG1,
1431 s_scm_floor_divide, qp, rp);
1432 }
1433
1434 static void
1435 scm_i_inexact_floor_divide (double x, double y, SCM *qp, SCM *rp)
1436 {
1437 if (SCM_UNLIKELY (y == 0))
1438 scm_num_overflow (s_scm_floor_divide); /* or return a NaN? */
1439 else
1440 {
1441 double q = floor (x / y);
1442 double r = x - q * y;
1443 *qp = scm_from_double (q);
1444 *rp = scm_from_double (r);
1445 }
1446 }
1447
1448 static void
1449 scm_i_exact_rational_floor_divide (SCM x, SCM y, SCM *qp, SCM *rp)
1450 {
1451 SCM r1;
1452 SCM xd = scm_denominator (x);
1453 SCM yd = scm_denominator (y);
1454
1455 scm_floor_divide (scm_product (scm_numerator (x), yd),
1456 scm_product (scm_numerator (y), xd),
1457 qp, &r1);
1458 *rp = scm_divide (r1, scm_product (xd, yd));
1459 }
1460
1461 static SCM scm_i_inexact_ceiling_quotient (double x, double y);
1462 static SCM scm_i_exact_rational_ceiling_quotient (SCM x, SCM y);
1463
1464 SCM_PRIMITIVE_GENERIC (scm_ceiling_quotient, "ceiling-quotient", 2, 0, 0,
1465 (SCM x, SCM y),
1466 "Return the ceiling of @math{@var{x} / @var{y}}.\n"
1467 "@lisp\n"
1468 "(ceiling-quotient 123 10) @result{} 13\n"
1469 "(ceiling-quotient 123 -10) @result{} -12\n"
1470 "(ceiling-quotient -123 10) @result{} -12\n"
1471 "(ceiling-quotient -123 -10) @result{} 13\n"
1472 "(ceiling-quotient -123.2 -63.5) @result{} 2.0\n"
1473 "(ceiling-quotient 16/3 -10/7) @result{} -3\n"
1474 "@end lisp")
1475 #define FUNC_NAME s_scm_ceiling_quotient
1476 {
1477 if (SCM_LIKELY (SCM_I_INUMP (x)))
1478 {
1479 scm_t_inum xx = SCM_I_INUM (x);
1480 if (SCM_LIKELY (SCM_I_INUMP (y)))
1481 {
1482 scm_t_inum yy = SCM_I_INUM (y);
1483 if (SCM_UNLIKELY (yy == 0))
1484 scm_num_overflow (s_scm_ceiling_quotient);
1485 else
1486 {
1487 scm_t_inum xx1 = xx;
1488 scm_t_inum qq;
1489 if (SCM_LIKELY (yy > 0))
1490 {
1491 if (SCM_LIKELY (xx >= 0))
1492 xx1 = xx + yy - 1;
1493 }
1494 else if (SCM_UNLIKELY (yy == 0))
1495 scm_num_overflow (s_scm_ceiling_quotient);
1496 else if (xx < 0)
1497 xx1 = xx + yy + 1;
1498 qq = xx1 / yy;
1499 if (SCM_LIKELY (SCM_FIXABLE (qq)))
1500 return SCM_I_MAKINUM (qq);
1501 else
1502 return scm_i_inum2big (qq);
1503 }
1504 }
1505 else if (SCM_BIGP (y))
1506 {
1507 int sign = mpz_sgn (SCM_I_BIG_MPZ (y));
1508 scm_remember_upto_here_1 (y);
1509 if (SCM_LIKELY (sign > 0))
1510 {
1511 if (SCM_LIKELY (xx > 0))
1512 return SCM_INUM1;
1513 else if (SCM_UNLIKELY (xx == SCM_MOST_NEGATIVE_FIXNUM)
1514 && SCM_UNLIKELY (mpz_cmp_ui (SCM_I_BIG_MPZ (y),
1515 - SCM_MOST_NEGATIVE_FIXNUM) == 0))
1516 {
1517 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
1518 scm_remember_upto_here_1 (y);
1519 return SCM_I_MAKINUM (-1);
1520 }
1521 else
1522 return SCM_INUM0;
1523 }
1524 else if (xx >= 0)
1525 return SCM_INUM0;
1526 else
1527 return SCM_INUM1;
1528 }
1529 else if (SCM_REALP (y))
1530 return scm_i_inexact_ceiling_quotient (xx, SCM_REAL_VALUE (y));
1531 else if (SCM_FRACTIONP (y))
1532 return scm_i_exact_rational_ceiling_quotient (x, y);
1533 else
1534 SCM_WTA_DISPATCH_2 (g_scm_ceiling_quotient, x, y, SCM_ARG2,
1535 s_scm_ceiling_quotient);
1536 }
1537 else if (SCM_BIGP (x))
1538 {
1539 if (SCM_LIKELY (SCM_I_INUMP (y)))
1540 {
1541 scm_t_inum yy = SCM_I_INUM (y);
1542 if (SCM_UNLIKELY (yy == 0))
1543 scm_num_overflow (s_scm_ceiling_quotient);
1544 else if (SCM_UNLIKELY (yy == 1))
1545 return x;
1546 else
1547 {
1548 SCM q = scm_i_mkbig ();
1549 if (yy > 0)
1550 mpz_cdiv_q_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (x), yy);
1551 else
1552 {
1553 mpz_fdiv_q_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (x), -yy);
1554 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
1555 }
1556 scm_remember_upto_here_1 (x);
1557 return scm_i_normbig (q);
1558 }
1559 }
1560 else if (SCM_BIGP (y))
1561 {
1562 SCM q = scm_i_mkbig ();
1563 mpz_cdiv_q (SCM_I_BIG_MPZ (q),
1564 SCM_I_BIG_MPZ (x),
1565 SCM_I_BIG_MPZ (y));
1566 scm_remember_upto_here_2 (x, y);
1567 return scm_i_normbig (q);
1568 }
1569 else if (SCM_REALP (y))
1570 return scm_i_inexact_ceiling_quotient
1571 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
1572 else if (SCM_FRACTIONP (y))
1573 return scm_i_exact_rational_ceiling_quotient (x, y);
1574 else
1575 SCM_WTA_DISPATCH_2 (g_scm_ceiling_quotient, x, y, SCM_ARG2,
1576 s_scm_ceiling_quotient);
1577 }
1578 else if (SCM_REALP (x))
1579 {
1580 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
1581 SCM_BIGP (y) || SCM_FRACTIONP (y))
1582 return scm_i_inexact_ceiling_quotient
1583 (SCM_REAL_VALUE (x), scm_to_double (y));
1584 else
1585 SCM_WTA_DISPATCH_2 (g_scm_ceiling_quotient, x, y, SCM_ARG2,
1586 s_scm_ceiling_quotient);
1587 }
1588 else if (SCM_FRACTIONP (x))
1589 {
1590 if (SCM_REALP (y))
1591 return scm_i_inexact_ceiling_quotient
1592 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
1593 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
1594 return scm_i_exact_rational_ceiling_quotient (x, y);
1595 else
1596 SCM_WTA_DISPATCH_2 (g_scm_ceiling_quotient, x, y, SCM_ARG2,
1597 s_scm_ceiling_quotient);
1598 }
1599 else
1600 SCM_WTA_DISPATCH_2 (g_scm_ceiling_quotient, x, y, SCM_ARG1,
1601 s_scm_ceiling_quotient);
1602 }
1603 #undef FUNC_NAME
1604
1605 static SCM
1606 scm_i_inexact_ceiling_quotient (double x, double y)
1607 {
1608 if (SCM_UNLIKELY (y == 0))
1609 scm_num_overflow (s_scm_ceiling_quotient); /* or return a NaN? */
1610 else
1611 return scm_from_double (ceil (x / y));
1612 }
1613
1614 static SCM
1615 scm_i_exact_rational_ceiling_quotient (SCM x, SCM y)
1616 {
1617 return scm_ceiling_quotient
1618 (scm_product (scm_numerator (x), scm_denominator (y)),
1619 scm_product (scm_numerator (y), scm_denominator (x)));
1620 }
1621
1622 static SCM scm_i_inexact_ceiling_remainder (double x, double y);
1623 static SCM scm_i_exact_rational_ceiling_remainder (SCM x, SCM y);
1624
1625 SCM_PRIMITIVE_GENERIC (scm_ceiling_remainder, "ceiling-remainder", 2, 0, 0,
1626 (SCM x, SCM y),
1627 "Return the real number @var{r} such that\n"
1628 "@math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
1629 "where @math{@var{q} = ceiling(@var{x} / @var{y})}.\n"
1630 "@lisp\n"
1631 "(ceiling-remainder 123 10) @result{} -7\n"
1632 "(ceiling-remainder 123 -10) @result{} 3\n"
1633 "(ceiling-remainder -123 10) @result{} -3\n"
1634 "(ceiling-remainder -123 -10) @result{} 7\n"
1635 "(ceiling-remainder -123.2 -63.5) @result{} 3.8\n"
1636 "(ceiling-remainder 16/3 -10/7) @result{} 22/21\n"
1637 "@end lisp")
1638 #define FUNC_NAME s_scm_ceiling_remainder
1639 {
1640 if (SCM_LIKELY (SCM_I_INUMP (x)))
1641 {
1642 scm_t_inum xx = SCM_I_INUM (x);
1643 if (SCM_LIKELY (SCM_I_INUMP (y)))
1644 {
1645 scm_t_inum yy = SCM_I_INUM (y);
1646 if (SCM_UNLIKELY (yy == 0))
1647 scm_num_overflow (s_scm_ceiling_remainder);
1648 else
1649 {
1650 scm_t_inum rr = xx % yy;
1651 int needs_adjustment;
1652
1653 if (SCM_LIKELY (yy > 0))
1654 needs_adjustment = (rr > 0);
1655 else
1656 needs_adjustment = (rr < 0);
1657
1658 if (needs_adjustment)
1659 rr -= yy;
1660 return SCM_I_MAKINUM (rr);
1661 }
1662 }
1663 else if (SCM_BIGP (y))
1664 {
1665 int sign = mpz_sgn (SCM_I_BIG_MPZ (y));
1666 scm_remember_upto_here_1 (y);
1667 if (SCM_LIKELY (sign > 0))
1668 {
1669 if (SCM_LIKELY (xx > 0))
1670 {
1671 SCM r = scm_i_mkbig ();
1672 mpz_sub_ui (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y), xx);
1673 scm_remember_upto_here_1 (y);
1674 mpz_neg (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (r));
1675 return scm_i_normbig (r);
1676 }
1677 else if (SCM_UNLIKELY (xx == SCM_MOST_NEGATIVE_FIXNUM)
1678 && SCM_UNLIKELY (mpz_cmp_ui (SCM_I_BIG_MPZ (y),
1679 - SCM_MOST_NEGATIVE_FIXNUM) == 0))
1680 {
1681 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
1682 scm_remember_upto_here_1 (y);
1683 return SCM_INUM0;
1684 }
1685 else
1686 return x;
1687 }
1688 else if (xx >= 0)
1689 return x;
1690 else
1691 {
1692 SCM r = scm_i_mkbig ();
1693 mpz_add_ui (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y), -xx);
1694 scm_remember_upto_here_1 (y);
1695 mpz_neg (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (r));
1696 return scm_i_normbig (r);
1697 }
1698 }
1699 else if (SCM_REALP (y))
1700 return scm_i_inexact_ceiling_remainder (xx, SCM_REAL_VALUE (y));
1701 else if (SCM_FRACTIONP (y))
1702 return scm_i_exact_rational_ceiling_remainder (x, y);
1703 else
1704 SCM_WTA_DISPATCH_2 (g_scm_ceiling_remainder, x, y, SCM_ARG2,
1705 s_scm_ceiling_remainder);
1706 }
1707 else if (SCM_BIGP (x))
1708 {
1709 if (SCM_LIKELY (SCM_I_INUMP (y)))
1710 {
1711 scm_t_inum yy = SCM_I_INUM (y);
1712 if (SCM_UNLIKELY (yy == 0))
1713 scm_num_overflow (s_scm_ceiling_remainder);
1714 else
1715 {
1716 scm_t_inum rr;
1717 if (yy > 0)
1718 rr = -mpz_cdiv_ui (SCM_I_BIG_MPZ (x), yy);
1719 else
1720 rr = mpz_fdiv_ui (SCM_I_BIG_MPZ (x), -yy);
1721 scm_remember_upto_here_1 (x);
1722 return SCM_I_MAKINUM (rr);
1723 }
1724 }
1725 else if (SCM_BIGP (y))
1726 {
1727 SCM r = scm_i_mkbig ();
1728 mpz_cdiv_r (SCM_I_BIG_MPZ (r),
1729 SCM_I_BIG_MPZ (x),
1730 SCM_I_BIG_MPZ (y));
1731 scm_remember_upto_here_2 (x, y);
1732 return scm_i_normbig (r);
1733 }
1734 else if (SCM_REALP (y))
1735 return scm_i_inexact_ceiling_remainder
1736 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
1737 else if (SCM_FRACTIONP (y))
1738 return scm_i_exact_rational_ceiling_remainder (x, y);
1739 else
1740 SCM_WTA_DISPATCH_2 (g_scm_ceiling_remainder, x, y, SCM_ARG2,
1741 s_scm_ceiling_remainder);
1742 }
1743 else if (SCM_REALP (x))
1744 {
1745 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
1746 SCM_BIGP (y) || SCM_FRACTIONP (y))
1747 return scm_i_inexact_ceiling_remainder
1748 (SCM_REAL_VALUE (x), scm_to_double (y));
1749 else
1750 SCM_WTA_DISPATCH_2 (g_scm_ceiling_remainder, x, y, SCM_ARG2,
1751 s_scm_ceiling_remainder);
1752 }
1753 else if (SCM_FRACTIONP (x))
1754 {
1755 if (SCM_REALP (y))
1756 return scm_i_inexact_ceiling_remainder
1757 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
1758 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
1759 return scm_i_exact_rational_ceiling_remainder (x, y);
1760 else
1761 SCM_WTA_DISPATCH_2 (g_scm_ceiling_remainder, x, y, SCM_ARG2,
1762 s_scm_ceiling_remainder);
1763 }
1764 else
1765 SCM_WTA_DISPATCH_2 (g_scm_ceiling_remainder, x, y, SCM_ARG1,
1766 s_scm_ceiling_remainder);
1767 }
1768 #undef FUNC_NAME
1769
1770 static SCM
1771 scm_i_inexact_ceiling_remainder (double x, double y)
1772 {
1773 /* Although it would be more efficient to use fmod here, we can't
1774 because it would in some cases produce results inconsistent with
1775 scm_i_inexact_ceiling_quotient, such that x != q * y + r (not even
1776 close). In particular, when x is very close to a multiple of y,
1777 then r might be either 0.0 or -y, but those two cases must
1778 correspond to different choices of q. If r = 0.0 then q must be
1779 x/y, and if r = -y then q must be x/y+1. If quotient chooses one
1780 and remainder chooses the other, it would be bad. */
1781 if (SCM_UNLIKELY (y == 0))
1782 scm_num_overflow (s_scm_ceiling_remainder); /* or return a NaN? */
1783 else
1784 return scm_from_double (x - y * ceil (x / y));
1785 }
1786
1787 static SCM
1788 scm_i_exact_rational_ceiling_remainder (SCM x, SCM y)
1789 {
1790 SCM xd = scm_denominator (x);
1791 SCM yd = scm_denominator (y);
1792 SCM r1 = scm_ceiling_remainder (scm_product (scm_numerator (x), yd),
1793 scm_product (scm_numerator (y), xd));
1794 return scm_divide (r1, scm_product (xd, yd));
1795 }
1796
1797 static void scm_i_inexact_ceiling_divide (double x, double y,
1798 SCM *qp, SCM *rp);
1799 static void scm_i_exact_rational_ceiling_divide (SCM x, SCM y,
1800 SCM *qp, SCM *rp);
1801
1802 SCM_PRIMITIVE_GENERIC (scm_i_ceiling_divide, "ceiling/", 2, 0, 0,
1803 (SCM x, SCM y),
1804 "Return the integer @var{q} and the real number @var{r}\n"
1805 "such that @math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
1806 "and @math{@var{q} = ceiling(@var{x} / @var{y})}.\n"
1807 "@lisp\n"
1808 "(ceiling/ 123 10) @result{} 13 and -7\n"
1809 "(ceiling/ 123 -10) @result{} -12 and 3\n"
1810 "(ceiling/ -123 10) @result{} -12 and -3\n"
1811 "(ceiling/ -123 -10) @result{} 13 and 7\n"
1812 "(ceiling/ -123.2 -63.5) @result{} 2.0 and 3.8\n"
1813 "(ceiling/ 16/3 -10/7) @result{} -3 and 22/21\n"
1814 "@end lisp")
1815 #define FUNC_NAME s_scm_i_ceiling_divide
1816 {
1817 SCM q, r;
1818
1819 scm_ceiling_divide(x, y, &q, &r);
1820 return scm_values (scm_list_2 (q, r));
1821 }
1822 #undef FUNC_NAME
1823
1824 #define s_scm_ceiling_divide s_scm_i_ceiling_divide
1825 #define g_scm_ceiling_divide g_scm_i_ceiling_divide
1826
1827 void
1828 scm_ceiling_divide (SCM x, SCM y, SCM *qp, SCM *rp)
1829 {
1830 if (SCM_LIKELY (SCM_I_INUMP (x)))
1831 {
1832 scm_t_inum xx = SCM_I_INUM (x);
1833 if (SCM_LIKELY (SCM_I_INUMP (y)))
1834 {
1835 scm_t_inum yy = SCM_I_INUM (y);
1836 if (SCM_UNLIKELY (yy == 0))
1837 scm_num_overflow (s_scm_ceiling_divide);
1838 else
1839 {
1840 scm_t_inum qq = xx / yy;
1841 scm_t_inum rr = xx % yy;
1842 int needs_adjustment;
1843
1844 if (SCM_LIKELY (yy > 0))
1845 needs_adjustment = (rr > 0);
1846 else
1847 needs_adjustment = (rr < 0);
1848
1849 if (needs_adjustment)
1850 {
1851 rr -= yy;
1852 qq++;
1853 }
1854 if (SCM_LIKELY (SCM_FIXABLE (qq)))
1855 *qp = SCM_I_MAKINUM (qq);
1856 else
1857 *qp = scm_i_inum2big (qq);
1858 *rp = SCM_I_MAKINUM (rr);
1859 }
1860 return;
1861 }
1862 else if (SCM_BIGP (y))
1863 {
1864 int sign = mpz_sgn (SCM_I_BIG_MPZ (y));
1865 scm_remember_upto_here_1 (y);
1866 if (SCM_LIKELY (sign > 0))
1867 {
1868 if (SCM_LIKELY (xx > 0))
1869 {
1870 SCM r = scm_i_mkbig ();
1871 mpz_sub_ui (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y), xx);
1872 scm_remember_upto_here_1 (y);
1873 mpz_neg (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (r));
1874 *qp = SCM_INUM1;
1875 *rp = scm_i_normbig (r);
1876 }
1877 else if (SCM_UNLIKELY (xx == SCM_MOST_NEGATIVE_FIXNUM)
1878 && SCM_UNLIKELY (mpz_cmp_ui (SCM_I_BIG_MPZ (y),
1879 - SCM_MOST_NEGATIVE_FIXNUM) == 0))
1880 {
1881 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
1882 scm_remember_upto_here_1 (y);
1883 *qp = SCM_I_MAKINUM (-1);
1884 *rp = SCM_INUM0;
1885 }
1886 else
1887 {
1888 *qp = SCM_INUM0;
1889 *rp = x;
1890 }
1891 }
1892 else if (xx >= 0)
1893 {
1894 *qp = SCM_INUM0;
1895 *rp = x;
1896 }
1897 else
1898 {
1899 SCM r = scm_i_mkbig ();
1900 mpz_add_ui (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y), -xx);
1901 scm_remember_upto_here_1 (y);
1902 mpz_neg (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (r));
1903 *qp = SCM_INUM1;
1904 *rp = scm_i_normbig (r);
1905 }
1906 return;
1907 }
1908 else if (SCM_REALP (y))
1909 return scm_i_inexact_ceiling_divide (xx, SCM_REAL_VALUE (y), qp, rp);
1910 else if (SCM_FRACTIONP (y))
1911 return scm_i_exact_rational_ceiling_divide (x, y, qp, rp);
1912 else
1913 return two_valued_wta_dispatch_2 (g_scm_ceiling_divide, x, y, SCM_ARG2,
1914 s_scm_ceiling_divide, qp, rp);
1915 }
1916 else if (SCM_BIGP (x))
1917 {
1918 if (SCM_LIKELY (SCM_I_INUMP (y)))
1919 {
1920 scm_t_inum yy = SCM_I_INUM (y);
1921 if (SCM_UNLIKELY (yy == 0))
1922 scm_num_overflow (s_scm_ceiling_divide);
1923 else
1924 {
1925 SCM q = scm_i_mkbig ();
1926 SCM r = scm_i_mkbig ();
1927 if (yy > 0)
1928 mpz_cdiv_qr_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
1929 SCM_I_BIG_MPZ (x), yy);
1930 else
1931 {
1932 mpz_fdiv_qr_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
1933 SCM_I_BIG_MPZ (x), -yy);
1934 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
1935 }
1936 scm_remember_upto_here_1 (x);
1937 *qp = scm_i_normbig (q);
1938 *rp = scm_i_normbig (r);
1939 }
1940 return;
1941 }
1942 else if (SCM_BIGP (y))
1943 {
1944 SCM q = scm_i_mkbig ();
1945 SCM r = scm_i_mkbig ();
1946 mpz_cdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
1947 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
1948 scm_remember_upto_here_2 (x, y);
1949 *qp = scm_i_normbig (q);
1950 *rp = scm_i_normbig (r);
1951 return;
1952 }
1953 else if (SCM_REALP (y))
1954 return scm_i_inexact_ceiling_divide
1955 (scm_i_big2dbl (x), SCM_REAL_VALUE (y), qp, rp);
1956 else if (SCM_FRACTIONP (y))
1957 return scm_i_exact_rational_ceiling_divide (x, y, qp, rp);
1958 else
1959 return two_valued_wta_dispatch_2 (g_scm_ceiling_divide, x, y, SCM_ARG2,
1960 s_scm_ceiling_divide, qp, rp);
1961 }
1962 else if (SCM_REALP (x))
1963 {
1964 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
1965 SCM_BIGP (y) || SCM_FRACTIONP (y))
1966 return scm_i_inexact_ceiling_divide
1967 (SCM_REAL_VALUE (x), scm_to_double (y), qp, rp);
1968 else
1969 return two_valued_wta_dispatch_2 (g_scm_ceiling_divide, x, y, SCM_ARG2,
1970 s_scm_ceiling_divide, qp, rp);
1971 }
1972 else if (SCM_FRACTIONP (x))
1973 {
1974 if (SCM_REALP (y))
1975 return scm_i_inexact_ceiling_divide
1976 (scm_i_fraction2double (x), SCM_REAL_VALUE (y), qp, rp);
1977 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
1978 return scm_i_exact_rational_ceiling_divide (x, y, qp, rp);
1979 else
1980 return two_valued_wta_dispatch_2 (g_scm_ceiling_divide, x, y, SCM_ARG2,
1981 s_scm_ceiling_divide, qp, rp);
1982 }
1983 else
1984 return two_valued_wta_dispatch_2 (g_scm_ceiling_divide, x, y, SCM_ARG1,
1985 s_scm_ceiling_divide, qp, rp);
1986 }
1987
1988 static void
1989 scm_i_inexact_ceiling_divide (double x, double y, SCM *qp, SCM *rp)
1990 {
1991 if (SCM_UNLIKELY (y == 0))
1992 scm_num_overflow (s_scm_ceiling_divide); /* or return a NaN? */
1993 else
1994 {
1995 double q = ceil (x / y);
1996 double r = x - q * y;
1997 *qp = scm_from_double (q);
1998 *rp = scm_from_double (r);
1999 }
2000 }
2001
2002 static void
2003 scm_i_exact_rational_ceiling_divide (SCM x, SCM y, SCM *qp, SCM *rp)
2004 {
2005 SCM r1;
2006 SCM xd = scm_denominator (x);
2007 SCM yd = scm_denominator (y);
2008
2009 scm_ceiling_divide (scm_product (scm_numerator (x), yd),
2010 scm_product (scm_numerator (y), xd),
2011 qp, &r1);
2012 *rp = scm_divide (r1, scm_product (xd, yd));
2013 }
2014
2015 static SCM scm_i_inexact_truncate_quotient (double x, double y);
2016 static SCM scm_i_exact_rational_truncate_quotient (SCM x, SCM y);
2017
2018 SCM_PRIMITIVE_GENERIC (scm_truncate_quotient, "truncate-quotient", 2, 0, 0,
2019 (SCM x, SCM y),
2020 "Return @math{@var{x} / @var{y}} rounded toward zero.\n"
2021 "@lisp\n"
2022 "(truncate-quotient 123 10) @result{} 12\n"
2023 "(truncate-quotient 123 -10) @result{} -12\n"
2024 "(truncate-quotient -123 10) @result{} -12\n"
2025 "(truncate-quotient -123 -10) @result{} 12\n"
2026 "(truncate-quotient -123.2 -63.5) @result{} 1.0\n"
2027 "(truncate-quotient 16/3 -10/7) @result{} -3\n"
2028 "@end lisp")
2029 #define FUNC_NAME s_scm_truncate_quotient
2030 {
2031 if (SCM_LIKELY (SCM_I_INUMP (x)))
2032 {
2033 scm_t_inum xx = SCM_I_INUM (x);
2034 if (SCM_LIKELY (SCM_I_INUMP (y)))
2035 {
2036 scm_t_inum yy = SCM_I_INUM (y);
2037 if (SCM_UNLIKELY (yy == 0))
2038 scm_num_overflow (s_scm_truncate_quotient);
2039 else
2040 {
2041 scm_t_inum qq = xx / yy;
2042 if (SCM_LIKELY (SCM_FIXABLE (qq)))
2043 return SCM_I_MAKINUM (qq);
2044 else
2045 return scm_i_inum2big (qq);
2046 }
2047 }
2048 else if (SCM_BIGP (y))
2049 {
2050 if (SCM_UNLIKELY (xx == SCM_MOST_NEGATIVE_FIXNUM)
2051 && SCM_UNLIKELY (mpz_cmp_ui (SCM_I_BIG_MPZ (y),
2052 - SCM_MOST_NEGATIVE_FIXNUM) == 0))
2053 {
2054 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
2055 scm_remember_upto_here_1 (y);
2056 return SCM_I_MAKINUM (-1);
2057 }
2058 else
2059 return SCM_INUM0;
2060 }
2061 else if (SCM_REALP (y))
2062 return scm_i_inexact_truncate_quotient (xx, SCM_REAL_VALUE (y));
2063 else if (SCM_FRACTIONP (y))
2064 return scm_i_exact_rational_truncate_quotient (x, y);
2065 else
2066 SCM_WTA_DISPATCH_2 (g_scm_truncate_quotient, x, y, SCM_ARG2,
2067 s_scm_truncate_quotient);
2068 }
2069 else if (SCM_BIGP (x))
2070 {
2071 if (SCM_LIKELY (SCM_I_INUMP (y)))
2072 {
2073 scm_t_inum yy = SCM_I_INUM (y);
2074 if (SCM_UNLIKELY (yy == 0))
2075 scm_num_overflow (s_scm_truncate_quotient);
2076 else if (SCM_UNLIKELY (yy == 1))
2077 return x;
2078 else
2079 {
2080 SCM q = scm_i_mkbig ();
2081 if (yy > 0)
2082 mpz_tdiv_q_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (x), yy);
2083 else
2084 {
2085 mpz_tdiv_q_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (x), -yy);
2086 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
2087 }
2088 scm_remember_upto_here_1 (x);
2089 return scm_i_normbig (q);
2090 }
2091 }
2092 else if (SCM_BIGP (y))
2093 {
2094 SCM q = scm_i_mkbig ();
2095 mpz_tdiv_q (SCM_I_BIG_MPZ (q),
2096 SCM_I_BIG_MPZ (x),
2097 SCM_I_BIG_MPZ (y));
2098 scm_remember_upto_here_2 (x, y);
2099 return scm_i_normbig (q);
2100 }
2101 else if (SCM_REALP (y))
2102 return scm_i_inexact_truncate_quotient
2103 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
2104 else if (SCM_FRACTIONP (y))
2105 return scm_i_exact_rational_truncate_quotient (x, y);
2106 else
2107 SCM_WTA_DISPATCH_2 (g_scm_truncate_quotient, x, y, SCM_ARG2,
2108 s_scm_truncate_quotient);
2109 }
2110 else if (SCM_REALP (x))
2111 {
2112 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
2113 SCM_BIGP (y) || SCM_FRACTIONP (y))
2114 return scm_i_inexact_truncate_quotient
2115 (SCM_REAL_VALUE (x), scm_to_double (y));
2116 else
2117 SCM_WTA_DISPATCH_2 (g_scm_truncate_quotient, x, y, SCM_ARG2,
2118 s_scm_truncate_quotient);
2119 }
2120 else if (SCM_FRACTIONP (x))
2121 {
2122 if (SCM_REALP (y))
2123 return scm_i_inexact_truncate_quotient
2124 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
2125 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
2126 return scm_i_exact_rational_truncate_quotient (x, y);
2127 else
2128 SCM_WTA_DISPATCH_2 (g_scm_truncate_quotient, x, y, SCM_ARG2,
2129 s_scm_truncate_quotient);
2130 }
2131 else
2132 SCM_WTA_DISPATCH_2 (g_scm_truncate_quotient, x, y, SCM_ARG1,
2133 s_scm_truncate_quotient);
2134 }
2135 #undef FUNC_NAME
2136
2137 static SCM
2138 scm_i_inexact_truncate_quotient (double x, double y)
2139 {
2140 if (SCM_UNLIKELY (y == 0))
2141 scm_num_overflow (s_scm_truncate_quotient); /* or return a NaN? */
2142 else
2143 return scm_from_double (trunc (x / y));
2144 }
2145
2146 static SCM
2147 scm_i_exact_rational_truncate_quotient (SCM x, SCM y)
2148 {
2149 return scm_truncate_quotient
2150 (scm_product (scm_numerator (x), scm_denominator (y)),
2151 scm_product (scm_numerator (y), scm_denominator (x)));
2152 }
2153
2154 static SCM scm_i_inexact_truncate_remainder (double x, double y);
2155 static SCM scm_i_exact_rational_truncate_remainder (SCM x, SCM y);
2156
2157 SCM_PRIMITIVE_GENERIC (scm_truncate_remainder, "truncate-remainder", 2, 0, 0,
2158 (SCM x, SCM y),
2159 "Return the real number @var{r} such that\n"
2160 "@math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
2161 "where @math{@var{q} = truncate(@var{x} / @var{y})}.\n"
2162 "@lisp\n"
2163 "(truncate-remainder 123 10) @result{} 3\n"
2164 "(truncate-remainder 123 -10) @result{} 3\n"
2165 "(truncate-remainder -123 10) @result{} -3\n"
2166 "(truncate-remainder -123 -10) @result{} -3\n"
2167 "(truncate-remainder -123.2 -63.5) @result{} -59.7\n"
2168 "(truncate-remainder 16/3 -10/7) @result{} 22/21\n"
2169 "@end lisp")
2170 #define FUNC_NAME s_scm_truncate_remainder
2171 {
2172 if (SCM_LIKELY (SCM_I_INUMP (x)))
2173 {
2174 scm_t_inum xx = SCM_I_INUM (x);
2175 if (SCM_LIKELY (SCM_I_INUMP (y)))
2176 {
2177 scm_t_inum yy = SCM_I_INUM (y);
2178 if (SCM_UNLIKELY (yy == 0))
2179 scm_num_overflow (s_scm_truncate_remainder);
2180 else
2181 return SCM_I_MAKINUM (xx % yy);
2182 }
2183 else if (SCM_BIGP (y))
2184 {
2185 if (SCM_UNLIKELY (xx == SCM_MOST_NEGATIVE_FIXNUM)
2186 && SCM_UNLIKELY (mpz_cmp_ui (SCM_I_BIG_MPZ (y),
2187 - SCM_MOST_NEGATIVE_FIXNUM) == 0))
2188 {
2189 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
2190 scm_remember_upto_here_1 (y);
2191 return SCM_INUM0;
2192 }
2193 else
2194 return x;
2195 }
2196 else if (SCM_REALP (y))
2197 return scm_i_inexact_truncate_remainder (xx, SCM_REAL_VALUE (y));
2198 else if (SCM_FRACTIONP (y))
2199 return scm_i_exact_rational_truncate_remainder (x, y);
2200 else
2201 SCM_WTA_DISPATCH_2 (g_scm_truncate_remainder, x, y, SCM_ARG2,
2202 s_scm_truncate_remainder);
2203 }
2204 else if (SCM_BIGP (x))
2205 {
2206 if (SCM_LIKELY (SCM_I_INUMP (y)))
2207 {
2208 scm_t_inum yy = SCM_I_INUM (y);
2209 if (SCM_UNLIKELY (yy == 0))
2210 scm_num_overflow (s_scm_truncate_remainder);
2211 else
2212 {
2213 scm_t_inum rr = (mpz_tdiv_ui (SCM_I_BIG_MPZ (x),
2214 (yy > 0) ? yy : -yy)
2215 * mpz_sgn (SCM_I_BIG_MPZ (x)));
2216 scm_remember_upto_here_1 (x);
2217 return SCM_I_MAKINUM (rr);
2218 }
2219 }
2220 else if (SCM_BIGP (y))
2221 {
2222 SCM r = scm_i_mkbig ();
2223 mpz_tdiv_r (SCM_I_BIG_MPZ (r),
2224 SCM_I_BIG_MPZ (x),
2225 SCM_I_BIG_MPZ (y));
2226 scm_remember_upto_here_2 (x, y);
2227 return scm_i_normbig (r);
2228 }
2229 else if (SCM_REALP (y))
2230 return scm_i_inexact_truncate_remainder
2231 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
2232 else if (SCM_FRACTIONP (y))
2233 return scm_i_exact_rational_truncate_remainder (x, y);
2234 else
2235 SCM_WTA_DISPATCH_2 (g_scm_truncate_remainder, x, y, SCM_ARG2,
2236 s_scm_truncate_remainder);
2237 }
2238 else if (SCM_REALP (x))
2239 {
2240 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
2241 SCM_BIGP (y) || SCM_FRACTIONP (y))
2242 return scm_i_inexact_truncate_remainder
2243 (SCM_REAL_VALUE (x), scm_to_double (y));
2244 else
2245 SCM_WTA_DISPATCH_2 (g_scm_truncate_remainder, x, y, SCM_ARG2,
2246 s_scm_truncate_remainder);
2247 }
2248 else if (SCM_FRACTIONP (x))
2249 {
2250 if (SCM_REALP (y))
2251 return scm_i_inexact_truncate_remainder
2252 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
2253 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
2254 return scm_i_exact_rational_truncate_remainder (x, y);
2255 else
2256 SCM_WTA_DISPATCH_2 (g_scm_truncate_remainder, x, y, SCM_ARG2,
2257 s_scm_truncate_remainder);
2258 }
2259 else
2260 SCM_WTA_DISPATCH_2 (g_scm_truncate_remainder, x, y, SCM_ARG1,
2261 s_scm_truncate_remainder);
2262 }
2263 #undef FUNC_NAME
2264
2265 static SCM
2266 scm_i_inexact_truncate_remainder (double x, double y)
2267 {
2268 /* Although it would be more efficient to use fmod here, we can't
2269 because it would in some cases produce results inconsistent with
2270 scm_i_inexact_truncate_quotient, such that x != q * y + r (not even
2271 close). In particular, when x is very close to a multiple of y,
2272 then r might be either 0.0 or sgn(x)*|y|, but those two cases must
2273 correspond to different choices of q. If quotient chooses one and
2274 remainder chooses the other, it would be bad. */
2275 if (SCM_UNLIKELY (y == 0))
2276 scm_num_overflow (s_scm_truncate_remainder); /* or return a NaN? */
2277 else
2278 return scm_from_double (x - y * trunc (x / y));
2279 }
2280
2281 static SCM
2282 scm_i_exact_rational_truncate_remainder (SCM x, SCM y)
2283 {
2284 SCM xd = scm_denominator (x);
2285 SCM yd = scm_denominator (y);
2286 SCM r1 = scm_truncate_remainder (scm_product (scm_numerator (x), yd),
2287 scm_product (scm_numerator (y), xd));
2288 return scm_divide (r1, scm_product (xd, yd));
2289 }
2290
2291
2292 static void scm_i_inexact_truncate_divide (double x, double y,
2293 SCM *qp, SCM *rp);
2294 static void scm_i_exact_rational_truncate_divide (SCM x, SCM y,
2295 SCM *qp, SCM *rp);
2296
2297 SCM_PRIMITIVE_GENERIC (scm_i_truncate_divide, "truncate/", 2, 0, 0,
2298 (SCM x, SCM y),
2299 "Return the integer @var{q} and the real number @var{r}\n"
2300 "such that @math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
2301 "and @math{@var{q} = truncate(@var{x} / @var{y})}.\n"
2302 "@lisp\n"
2303 "(truncate/ 123 10) @result{} 12 and 3\n"
2304 "(truncate/ 123 -10) @result{} -12 and 3\n"
2305 "(truncate/ -123 10) @result{} -12 and -3\n"
2306 "(truncate/ -123 -10) @result{} 12 and -3\n"
2307 "(truncate/ -123.2 -63.5) @result{} 1.0 and -59.7\n"
2308 "(truncate/ 16/3 -10/7) @result{} -3 and 22/21\n"
2309 "@end lisp")
2310 #define FUNC_NAME s_scm_i_truncate_divide
2311 {
2312 SCM q, r;
2313
2314 scm_truncate_divide(x, y, &q, &r);
2315 return scm_values (scm_list_2 (q, r));
2316 }
2317 #undef FUNC_NAME
2318
2319 #define s_scm_truncate_divide s_scm_i_truncate_divide
2320 #define g_scm_truncate_divide g_scm_i_truncate_divide
2321
2322 void
2323 scm_truncate_divide (SCM x, SCM y, SCM *qp, SCM *rp)
2324 {
2325 if (SCM_LIKELY (SCM_I_INUMP (x)))
2326 {
2327 scm_t_inum xx = SCM_I_INUM (x);
2328 if (SCM_LIKELY (SCM_I_INUMP (y)))
2329 {
2330 scm_t_inum yy = SCM_I_INUM (y);
2331 if (SCM_UNLIKELY (yy == 0))
2332 scm_num_overflow (s_scm_truncate_divide);
2333 else
2334 {
2335 scm_t_inum qq = xx / yy;
2336 scm_t_inum rr = xx % yy;
2337 if (SCM_LIKELY (SCM_FIXABLE (qq)))
2338 *qp = SCM_I_MAKINUM (qq);
2339 else
2340 *qp = scm_i_inum2big (qq);
2341 *rp = SCM_I_MAKINUM (rr);
2342 }
2343 return;
2344 }
2345 else if (SCM_BIGP (y))
2346 {
2347 if (SCM_UNLIKELY (xx == SCM_MOST_NEGATIVE_FIXNUM)
2348 && SCM_UNLIKELY (mpz_cmp_ui (SCM_I_BIG_MPZ (y),
2349 - SCM_MOST_NEGATIVE_FIXNUM) == 0))
2350 {
2351 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
2352 scm_remember_upto_here_1 (y);
2353 *qp = SCM_I_MAKINUM (-1);
2354 *rp = SCM_INUM0;
2355 }
2356 else
2357 {
2358 *qp = SCM_INUM0;
2359 *rp = x;
2360 }
2361 return;
2362 }
2363 else if (SCM_REALP (y))
2364 return scm_i_inexact_truncate_divide (xx, SCM_REAL_VALUE (y), qp, rp);
2365 else if (SCM_FRACTIONP (y))
2366 return scm_i_exact_rational_truncate_divide (x, y, qp, rp);
2367 else
2368 return two_valued_wta_dispatch_2
2369 (g_scm_truncate_divide, x, y, SCM_ARG2,
2370 s_scm_truncate_divide, qp, rp);
2371 }
2372 else if (SCM_BIGP (x))
2373 {
2374 if (SCM_LIKELY (SCM_I_INUMP (y)))
2375 {
2376 scm_t_inum yy = SCM_I_INUM (y);
2377 if (SCM_UNLIKELY (yy == 0))
2378 scm_num_overflow (s_scm_truncate_divide);
2379 else
2380 {
2381 SCM q = scm_i_mkbig ();
2382 scm_t_inum rr;
2383 if (yy > 0)
2384 rr = mpz_tdiv_q_ui (SCM_I_BIG_MPZ (q),
2385 SCM_I_BIG_MPZ (x), yy);
2386 else
2387 {
2388 rr = mpz_tdiv_q_ui (SCM_I_BIG_MPZ (q),
2389 SCM_I_BIG_MPZ (x), -yy);
2390 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
2391 }
2392 rr *= mpz_sgn (SCM_I_BIG_MPZ (x));
2393 scm_remember_upto_here_1 (x);
2394 *qp = scm_i_normbig (q);
2395 *rp = SCM_I_MAKINUM (rr);
2396 }
2397 return;
2398 }
2399 else if (SCM_BIGP (y))
2400 {
2401 SCM q = scm_i_mkbig ();
2402 SCM r = scm_i_mkbig ();
2403 mpz_tdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
2404 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2405 scm_remember_upto_here_2 (x, y);
2406 *qp = scm_i_normbig (q);
2407 *rp = scm_i_normbig (r);
2408 }
2409 else if (SCM_REALP (y))
2410 return scm_i_inexact_truncate_divide
2411 (scm_i_big2dbl (x), SCM_REAL_VALUE (y), qp, rp);
2412 else if (SCM_FRACTIONP (y))
2413 return scm_i_exact_rational_truncate_divide (x, y, qp, rp);
2414 else
2415 return two_valued_wta_dispatch_2
2416 (g_scm_truncate_divide, x, y, SCM_ARG2,
2417 s_scm_truncate_divide, qp, rp);
2418 }
2419 else if (SCM_REALP (x))
2420 {
2421 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
2422 SCM_BIGP (y) || SCM_FRACTIONP (y))
2423 return scm_i_inexact_truncate_divide
2424 (SCM_REAL_VALUE (x), scm_to_double (y), qp, rp);
2425 else
2426 return two_valued_wta_dispatch_2
2427 (g_scm_truncate_divide, x, y, SCM_ARG2,
2428 s_scm_truncate_divide, qp, rp);
2429 }
2430 else if (SCM_FRACTIONP (x))
2431 {
2432 if (SCM_REALP (y))
2433 return scm_i_inexact_truncate_divide
2434 (scm_i_fraction2double (x), SCM_REAL_VALUE (y), qp, rp);
2435 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
2436 return scm_i_exact_rational_truncate_divide (x, y, qp, rp);
2437 else
2438 return two_valued_wta_dispatch_2
2439 (g_scm_truncate_divide, x, y, SCM_ARG2,
2440 s_scm_truncate_divide, qp, rp);
2441 }
2442 else
2443 return two_valued_wta_dispatch_2 (g_scm_truncate_divide, x, y, SCM_ARG1,
2444 s_scm_truncate_divide, qp, rp);
2445 }
2446
2447 static void
2448 scm_i_inexact_truncate_divide (double x, double y, SCM *qp, SCM *rp)
2449 {
2450 if (SCM_UNLIKELY (y == 0))
2451 scm_num_overflow (s_scm_truncate_divide); /* or return a NaN? */
2452 else
2453 {
2454 double q = trunc (x / y);
2455 double r = x - q * y;
2456 *qp = scm_from_double (q);
2457 *rp = scm_from_double (r);
2458 }
2459 }
2460
2461 static void
2462 scm_i_exact_rational_truncate_divide (SCM x, SCM y, SCM *qp, SCM *rp)
2463 {
2464 SCM r1;
2465 SCM xd = scm_denominator (x);
2466 SCM yd = scm_denominator (y);
2467
2468 scm_truncate_divide (scm_product (scm_numerator (x), yd),
2469 scm_product (scm_numerator (y), xd),
2470 qp, &r1);
2471 *rp = scm_divide (r1, scm_product (xd, yd));
2472 }
2473
2474 static SCM scm_i_inexact_centered_quotient (double x, double y);
2475 static SCM scm_i_bigint_centered_quotient (SCM x, SCM y);
2476 static SCM scm_i_exact_rational_centered_quotient (SCM x, SCM y);
2477
2478 SCM_PRIMITIVE_GENERIC (scm_centered_quotient, "centered-quotient", 2, 0, 0,
2479 (SCM x, SCM y),
2480 "Return the integer @var{q} such that\n"
2481 "@math{@var{x} = @var{q}*@var{y} + @var{r}} where\n"
2482 "@math{-abs(@var{y}/2) <= @var{r} < abs(@var{y}/2)}.\n"
2483 "@lisp\n"
2484 "(centered-quotient 123 10) @result{} 12\n"
2485 "(centered-quotient 123 -10) @result{} -12\n"
2486 "(centered-quotient -123 10) @result{} -12\n"
2487 "(centered-quotient -123 -10) @result{} 12\n"
2488 "(centered-quotient -123.2 -63.5) @result{} 2.0\n"
2489 "(centered-quotient 16/3 -10/7) @result{} -4\n"
2490 "@end lisp")
2491 #define FUNC_NAME s_scm_centered_quotient
2492 {
2493 if (SCM_LIKELY (SCM_I_INUMP (x)))
2494 {
2495 scm_t_inum xx = SCM_I_INUM (x);
2496 if (SCM_LIKELY (SCM_I_INUMP (y)))
2497 {
2498 scm_t_inum yy = SCM_I_INUM (y);
2499 if (SCM_UNLIKELY (yy == 0))
2500 scm_num_overflow (s_scm_centered_quotient);
2501 else
2502 {
2503 scm_t_inum qq = xx / yy;
2504 scm_t_inum rr = xx % yy;
2505 if (SCM_LIKELY (xx > 0))
2506 {
2507 if (SCM_LIKELY (yy > 0))
2508 {
2509 if (rr >= (yy + 1) / 2)
2510 qq++;
2511 }
2512 else
2513 {
2514 if (rr >= (1 - yy) / 2)
2515 qq--;
2516 }
2517 }
2518 else
2519 {
2520 if (SCM_LIKELY (yy > 0))
2521 {
2522 if (rr < -yy / 2)
2523 qq--;
2524 }
2525 else
2526 {
2527 if (rr < yy / 2)
2528 qq++;
2529 }
2530 }
2531 if (SCM_LIKELY (SCM_FIXABLE (qq)))
2532 return SCM_I_MAKINUM (qq);
2533 else
2534 return scm_i_inum2big (qq);
2535 }
2536 }
2537 else if (SCM_BIGP (y))
2538 {
2539 /* Pass a denormalized bignum version of x (even though it
2540 can fit in a fixnum) to scm_i_bigint_centered_quotient */
2541 return scm_i_bigint_centered_quotient (scm_i_long2big (xx), y);
2542 }
2543 else if (SCM_REALP (y))
2544 return scm_i_inexact_centered_quotient (xx, SCM_REAL_VALUE (y));
2545 else if (SCM_FRACTIONP (y))
2546 return scm_i_exact_rational_centered_quotient (x, y);
2547 else
2548 SCM_WTA_DISPATCH_2 (g_scm_centered_quotient, x, y, SCM_ARG2,
2549 s_scm_centered_quotient);
2550 }
2551 else if (SCM_BIGP (x))
2552 {
2553 if (SCM_LIKELY (SCM_I_INUMP (y)))
2554 {
2555 scm_t_inum yy = SCM_I_INUM (y);
2556 if (SCM_UNLIKELY (yy == 0))
2557 scm_num_overflow (s_scm_centered_quotient);
2558 else if (SCM_UNLIKELY (yy == 1))
2559 return x;
2560 else
2561 {
2562 SCM q = scm_i_mkbig ();
2563 scm_t_inum rr;
2564 /* Arrange for rr to initially be non-positive,
2565 because that simplifies the test to see
2566 if it is within the needed bounds. */
2567 if (yy > 0)
2568 {
2569 rr = - mpz_cdiv_q_ui (SCM_I_BIG_MPZ (q),
2570 SCM_I_BIG_MPZ (x), yy);
2571 scm_remember_upto_here_1 (x);
2572 if (rr < -yy / 2)
2573 mpz_sub_ui (SCM_I_BIG_MPZ (q),
2574 SCM_I_BIG_MPZ (q), 1);
2575 }
2576 else
2577 {
2578 rr = - mpz_cdiv_q_ui (SCM_I_BIG_MPZ (q),
2579 SCM_I_BIG_MPZ (x), -yy);
2580 scm_remember_upto_here_1 (x);
2581 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
2582 if (rr < yy / 2)
2583 mpz_add_ui (SCM_I_BIG_MPZ (q),
2584 SCM_I_BIG_MPZ (q), 1);
2585 }
2586 return scm_i_normbig (q);
2587 }
2588 }
2589 else if (SCM_BIGP (y))
2590 return scm_i_bigint_centered_quotient (x, y);
2591 else if (SCM_REALP (y))
2592 return scm_i_inexact_centered_quotient
2593 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
2594 else if (SCM_FRACTIONP (y))
2595 return scm_i_exact_rational_centered_quotient (x, y);
2596 else
2597 SCM_WTA_DISPATCH_2 (g_scm_centered_quotient, x, y, SCM_ARG2,
2598 s_scm_centered_quotient);
2599 }
2600 else if (SCM_REALP (x))
2601 {
2602 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
2603 SCM_BIGP (y) || SCM_FRACTIONP (y))
2604 return scm_i_inexact_centered_quotient
2605 (SCM_REAL_VALUE (x), scm_to_double (y));
2606 else
2607 SCM_WTA_DISPATCH_2 (g_scm_centered_quotient, x, y, SCM_ARG2,
2608 s_scm_centered_quotient);
2609 }
2610 else if (SCM_FRACTIONP (x))
2611 {
2612 if (SCM_REALP (y))
2613 return scm_i_inexact_centered_quotient
2614 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
2615 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
2616 return scm_i_exact_rational_centered_quotient (x, y);
2617 else
2618 SCM_WTA_DISPATCH_2 (g_scm_centered_quotient, x, y, SCM_ARG2,
2619 s_scm_centered_quotient);
2620 }
2621 else
2622 SCM_WTA_DISPATCH_2 (g_scm_centered_quotient, x, y, SCM_ARG1,
2623 s_scm_centered_quotient);
2624 }
2625 #undef FUNC_NAME
2626
2627 static SCM
2628 scm_i_inexact_centered_quotient (double x, double y)
2629 {
2630 if (SCM_LIKELY (y > 0))
2631 return scm_from_double (floor (x/y + 0.5));
2632 else if (SCM_LIKELY (y < 0))
2633 return scm_from_double (ceil (x/y - 0.5));
2634 else if (y == 0)
2635 scm_num_overflow (s_scm_centered_quotient); /* or return a NaN? */
2636 else
2637 return scm_nan ();
2638 }
2639
2640 /* Assumes that both x and y are bigints, though
2641 x might be able to fit into a fixnum. */
2642 static SCM
2643 scm_i_bigint_centered_quotient (SCM x, SCM y)
2644 {
2645 SCM q, r, min_r;
2646
2647 /* Note that x might be small enough to fit into a
2648 fixnum, so we must not let it escape into the wild */
2649 q = scm_i_mkbig ();
2650 r = scm_i_mkbig ();
2651
2652 /* min_r will eventually become -abs(y)/2 */
2653 min_r = scm_i_mkbig ();
2654 mpz_tdiv_q_2exp (SCM_I_BIG_MPZ (min_r),
2655 SCM_I_BIG_MPZ (y), 1);
2656
2657 /* Arrange for rr to initially be non-positive,
2658 because that simplifies the test to see
2659 if it is within the needed bounds. */
2660 if (mpz_sgn (SCM_I_BIG_MPZ (y)) > 0)
2661 {
2662 mpz_cdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
2663 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2664 scm_remember_upto_here_2 (x, y);
2665 mpz_neg (SCM_I_BIG_MPZ (min_r), SCM_I_BIG_MPZ (min_r));
2666 if (mpz_cmp (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (min_r)) < 0)
2667 mpz_sub_ui (SCM_I_BIG_MPZ (q),
2668 SCM_I_BIG_MPZ (q), 1);
2669 }
2670 else
2671 {
2672 mpz_fdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
2673 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2674 scm_remember_upto_here_2 (x, y);
2675 if (mpz_cmp (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (min_r)) < 0)
2676 mpz_add_ui (SCM_I_BIG_MPZ (q),
2677 SCM_I_BIG_MPZ (q), 1);
2678 }
2679 scm_remember_upto_here_2 (r, min_r);
2680 return scm_i_normbig (q);
2681 }
2682
2683 static SCM
2684 scm_i_exact_rational_centered_quotient (SCM x, SCM y)
2685 {
2686 return scm_centered_quotient
2687 (scm_product (scm_numerator (x), scm_denominator (y)),
2688 scm_product (scm_numerator (y), scm_denominator (x)));
2689 }
2690
2691 static SCM scm_i_inexact_centered_remainder (double x, double y);
2692 static SCM scm_i_bigint_centered_remainder (SCM x, SCM y);
2693 static SCM scm_i_exact_rational_centered_remainder (SCM x, SCM y);
2694
2695 SCM_PRIMITIVE_GENERIC (scm_centered_remainder, "centered-remainder", 2, 0, 0,
2696 (SCM x, SCM y),
2697 "Return the real number @var{r} such that\n"
2698 "@math{-abs(@var{y}/2) <= @var{r} < abs(@var{y}/2)}\n"
2699 "and @math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
2700 "for some integer @var{q}.\n"
2701 "@lisp\n"
2702 "(centered-remainder 123 10) @result{} 3\n"
2703 "(centered-remainder 123 -10) @result{} 3\n"
2704 "(centered-remainder -123 10) @result{} -3\n"
2705 "(centered-remainder -123 -10) @result{} -3\n"
2706 "(centered-remainder -123.2 -63.5) @result{} 3.8\n"
2707 "(centered-remainder 16/3 -10/7) @result{} -8/21\n"
2708 "@end lisp")
2709 #define FUNC_NAME s_scm_centered_remainder
2710 {
2711 if (SCM_LIKELY (SCM_I_INUMP (x)))
2712 {
2713 scm_t_inum xx = SCM_I_INUM (x);
2714 if (SCM_LIKELY (SCM_I_INUMP (y)))
2715 {
2716 scm_t_inum yy = SCM_I_INUM (y);
2717 if (SCM_UNLIKELY (yy == 0))
2718 scm_num_overflow (s_scm_centered_remainder);
2719 else
2720 {
2721 scm_t_inum rr = xx % yy;
2722 if (SCM_LIKELY (xx > 0))
2723 {
2724 if (SCM_LIKELY (yy > 0))
2725 {
2726 if (rr >= (yy + 1) / 2)
2727 rr -= yy;
2728 }
2729 else
2730 {
2731 if (rr >= (1 - yy) / 2)
2732 rr += yy;
2733 }
2734 }
2735 else
2736 {
2737 if (SCM_LIKELY (yy > 0))
2738 {
2739 if (rr < -yy / 2)
2740 rr += yy;
2741 }
2742 else
2743 {
2744 if (rr < yy / 2)
2745 rr -= yy;
2746 }
2747 }
2748 return SCM_I_MAKINUM (rr);
2749 }
2750 }
2751 else if (SCM_BIGP (y))
2752 {
2753 /* Pass a denormalized bignum version of x (even though it
2754 can fit in a fixnum) to scm_i_bigint_centered_remainder */
2755 return scm_i_bigint_centered_remainder (scm_i_long2big (xx), y);
2756 }
2757 else if (SCM_REALP (y))
2758 return scm_i_inexact_centered_remainder (xx, SCM_REAL_VALUE (y));
2759 else if (SCM_FRACTIONP (y))
2760 return scm_i_exact_rational_centered_remainder (x, y);
2761 else
2762 SCM_WTA_DISPATCH_2 (g_scm_centered_remainder, x, y, SCM_ARG2,
2763 s_scm_centered_remainder);
2764 }
2765 else if (SCM_BIGP (x))
2766 {
2767 if (SCM_LIKELY (SCM_I_INUMP (y)))
2768 {
2769 scm_t_inum yy = SCM_I_INUM (y);
2770 if (SCM_UNLIKELY (yy == 0))
2771 scm_num_overflow (s_scm_centered_remainder);
2772 else
2773 {
2774 scm_t_inum rr;
2775 /* Arrange for rr to initially be non-positive,
2776 because that simplifies the test to see
2777 if it is within the needed bounds. */
2778 if (yy > 0)
2779 {
2780 rr = - mpz_cdiv_ui (SCM_I_BIG_MPZ (x), yy);
2781 scm_remember_upto_here_1 (x);
2782 if (rr < -yy / 2)
2783 rr += yy;
2784 }
2785 else
2786 {
2787 rr = - mpz_cdiv_ui (SCM_I_BIG_MPZ (x), -yy);
2788 scm_remember_upto_here_1 (x);
2789 if (rr < yy / 2)
2790 rr -= yy;
2791 }
2792 return SCM_I_MAKINUM (rr);
2793 }
2794 }
2795 else if (SCM_BIGP (y))
2796 return scm_i_bigint_centered_remainder (x, y);
2797 else if (SCM_REALP (y))
2798 return scm_i_inexact_centered_remainder
2799 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
2800 else if (SCM_FRACTIONP (y))
2801 return scm_i_exact_rational_centered_remainder (x, y);
2802 else
2803 SCM_WTA_DISPATCH_2 (g_scm_centered_remainder, x, y, SCM_ARG2,
2804 s_scm_centered_remainder);
2805 }
2806 else if (SCM_REALP (x))
2807 {
2808 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
2809 SCM_BIGP (y) || SCM_FRACTIONP (y))
2810 return scm_i_inexact_centered_remainder
2811 (SCM_REAL_VALUE (x), scm_to_double (y));
2812 else
2813 SCM_WTA_DISPATCH_2 (g_scm_centered_remainder, x, y, SCM_ARG2,
2814 s_scm_centered_remainder);
2815 }
2816 else if (SCM_FRACTIONP (x))
2817 {
2818 if (SCM_REALP (y))
2819 return scm_i_inexact_centered_remainder
2820 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
2821 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
2822 return scm_i_exact_rational_centered_remainder (x, y);
2823 else
2824 SCM_WTA_DISPATCH_2 (g_scm_centered_remainder, x, y, SCM_ARG2,
2825 s_scm_centered_remainder);
2826 }
2827 else
2828 SCM_WTA_DISPATCH_2 (g_scm_centered_remainder, x, y, SCM_ARG1,
2829 s_scm_centered_remainder);
2830 }
2831 #undef FUNC_NAME
2832
2833 static SCM
2834 scm_i_inexact_centered_remainder (double x, double y)
2835 {
2836 double q;
2837
2838 /* Although it would be more efficient to use fmod here, we can't
2839 because it would in some cases produce results inconsistent with
2840 scm_i_inexact_centered_quotient, such that x != r + q * y (not even
2841 close). In particular, when x-y/2 is very close to a multiple of
2842 y, then r might be either -abs(y/2) or abs(y/2)-epsilon, but those
2843 two cases must correspond to different choices of q. If quotient
2844 chooses one and remainder chooses the other, it would be bad. */
2845 if (SCM_LIKELY (y > 0))
2846 q = floor (x/y + 0.5);
2847 else if (SCM_LIKELY (y < 0))
2848 q = ceil (x/y - 0.5);
2849 else if (y == 0)
2850 scm_num_overflow (s_scm_centered_remainder); /* or return a NaN? */
2851 else
2852 return scm_nan ();
2853 return scm_from_double (x - q * y);
2854 }
2855
2856 /* Assumes that both x and y are bigints, though
2857 x might be able to fit into a fixnum. */
2858 static SCM
2859 scm_i_bigint_centered_remainder (SCM x, SCM y)
2860 {
2861 SCM r, min_r;
2862
2863 /* Note that x might be small enough to fit into a
2864 fixnum, so we must not let it escape into the wild */
2865 r = scm_i_mkbig ();
2866
2867 /* min_r will eventually become -abs(y)/2 */
2868 min_r = scm_i_mkbig ();
2869 mpz_tdiv_q_2exp (SCM_I_BIG_MPZ (min_r),
2870 SCM_I_BIG_MPZ (y), 1);
2871
2872 /* Arrange for rr to initially be non-positive,
2873 because that simplifies the test to see
2874 if it is within the needed bounds. */
2875 if (mpz_sgn (SCM_I_BIG_MPZ (y)) > 0)
2876 {
2877 mpz_cdiv_r (SCM_I_BIG_MPZ (r),
2878 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2879 mpz_neg (SCM_I_BIG_MPZ (min_r), SCM_I_BIG_MPZ (min_r));
2880 if (mpz_cmp (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (min_r)) < 0)
2881 mpz_add (SCM_I_BIG_MPZ (r),
2882 SCM_I_BIG_MPZ (r),
2883 SCM_I_BIG_MPZ (y));
2884 }
2885 else
2886 {
2887 mpz_fdiv_r (SCM_I_BIG_MPZ (r),
2888 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2889 if (mpz_cmp (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (min_r)) < 0)
2890 mpz_sub (SCM_I_BIG_MPZ (r),
2891 SCM_I_BIG_MPZ (r),
2892 SCM_I_BIG_MPZ (y));
2893 }
2894 scm_remember_upto_here_2 (x, y);
2895 return scm_i_normbig (r);
2896 }
2897
2898 static SCM
2899 scm_i_exact_rational_centered_remainder (SCM x, SCM y)
2900 {
2901 SCM xd = scm_denominator (x);
2902 SCM yd = scm_denominator (y);
2903 SCM r1 = scm_centered_remainder (scm_product (scm_numerator (x), yd),
2904 scm_product (scm_numerator (y), xd));
2905 return scm_divide (r1, scm_product (xd, yd));
2906 }
2907
2908
2909 static void scm_i_inexact_centered_divide (double x, double y,
2910 SCM *qp, SCM *rp);
2911 static void scm_i_bigint_centered_divide (SCM x, SCM y, SCM *qp, SCM *rp);
2912 static void scm_i_exact_rational_centered_divide (SCM x, SCM y,
2913 SCM *qp, SCM *rp);
2914
2915 SCM_PRIMITIVE_GENERIC (scm_i_centered_divide, "centered/", 2, 0, 0,
2916 (SCM x, SCM y),
2917 "Return the integer @var{q} and the real number @var{r}\n"
2918 "such that @math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
2919 "and @math{-abs(@var{y}/2) <= @var{r} < abs(@var{y}/2)}.\n"
2920 "@lisp\n"
2921 "(centered/ 123 10) @result{} 12 and 3\n"
2922 "(centered/ 123 -10) @result{} -12 and 3\n"
2923 "(centered/ -123 10) @result{} -12 and -3\n"
2924 "(centered/ -123 -10) @result{} 12 and -3\n"
2925 "(centered/ -123.2 -63.5) @result{} 2.0 and 3.8\n"
2926 "(centered/ 16/3 -10/7) @result{} -4 and -8/21\n"
2927 "@end lisp")
2928 #define FUNC_NAME s_scm_i_centered_divide
2929 {
2930 SCM q, r;
2931
2932 scm_centered_divide(x, y, &q, &r);
2933 return scm_values (scm_list_2 (q, r));
2934 }
2935 #undef FUNC_NAME
2936
2937 #define s_scm_centered_divide s_scm_i_centered_divide
2938 #define g_scm_centered_divide g_scm_i_centered_divide
2939
2940 void
2941 scm_centered_divide (SCM x, SCM y, SCM *qp, SCM *rp)
2942 {
2943 if (SCM_LIKELY (SCM_I_INUMP (x)))
2944 {
2945 scm_t_inum xx = SCM_I_INUM (x);
2946 if (SCM_LIKELY (SCM_I_INUMP (y)))
2947 {
2948 scm_t_inum yy = SCM_I_INUM (y);
2949 if (SCM_UNLIKELY (yy == 0))
2950 scm_num_overflow (s_scm_centered_divide);
2951 else
2952 {
2953 scm_t_inum qq = xx / yy;
2954 scm_t_inum rr = xx % yy;
2955 if (SCM_LIKELY (xx > 0))
2956 {
2957 if (SCM_LIKELY (yy > 0))
2958 {
2959 if (rr >= (yy + 1) / 2)
2960 { qq++; rr -= yy; }
2961 }
2962 else
2963 {
2964 if (rr >= (1 - yy) / 2)
2965 { qq--; rr += yy; }
2966 }
2967 }
2968 else
2969 {
2970 if (SCM_LIKELY (yy > 0))
2971 {
2972 if (rr < -yy / 2)
2973 { qq--; rr += yy; }
2974 }
2975 else
2976 {
2977 if (rr < yy / 2)
2978 { qq++; rr -= yy; }
2979 }
2980 }
2981 if (SCM_LIKELY (SCM_FIXABLE (qq)))
2982 *qp = SCM_I_MAKINUM (qq);
2983 else
2984 *qp = scm_i_inum2big (qq);
2985 *rp = SCM_I_MAKINUM (rr);
2986 }
2987 return;
2988 }
2989 else if (SCM_BIGP (y))
2990 {
2991 /* Pass a denormalized bignum version of x (even though it
2992 can fit in a fixnum) to scm_i_bigint_centered_divide */
2993 return scm_i_bigint_centered_divide (scm_i_long2big (xx), y, qp, rp);
2994 }
2995 else if (SCM_REALP (y))
2996 return scm_i_inexact_centered_divide (xx, SCM_REAL_VALUE (y), qp, rp);
2997 else if (SCM_FRACTIONP (y))
2998 return scm_i_exact_rational_centered_divide (x, y, qp, rp);
2999 else
3000 return two_valued_wta_dispatch_2
3001 (g_scm_centered_divide, x, y, SCM_ARG2,
3002 s_scm_centered_divide, qp, rp);
3003 }
3004 else if (SCM_BIGP (x))
3005 {
3006 if (SCM_LIKELY (SCM_I_INUMP (y)))
3007 {
3008 scm_t_inum yy = SCM_I_INUM (y);
3009 if (SCM_UNLIKELY (yy == 0))
3010 scm_num_overflow (s_scm_centered_divide);
3011 else
3012 {
3013 SCM q = scm_i_mkbig ();
3014 scm_t_inum rr;
3015 /* Arrange for rr to initially be non-positive,
3016 because that simplifies the test to see
3017 if it is within the needed bounds. */
3018 if (yy > 0)
3019 {
3020 rr = - mpz_cdiv_q_ui (SCM_I_BIG_MPZ (q),
3021 SCM_I_BIG_MPZ (x), yy);
3022 scm_remember_upto_here_1 (x);
3023 if (rr < -yy / 2)
3024 {
3025 mpz_sub_ui (SCM_I_BIG_MPZ (q),
3026 SCM_I_BIG_MPZ (q), 1);
3027 rr += yy;
3028 }
3029 }
3030 else
3031 {
3032 rr = - mpz_cdiv_q_ui (SCM_I_BIG_MPZ (q),
3033 SCM_I_BIG_MPZ (x), -yy);
3034 scm_remember_upto_here_1 (x);
3035 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
3036 if (rr < yy / 2)
3037 {
3038 mpz_add_ui (SCM_I_BIG_MPZ (q),
3039 SCM_I_BIG_MPZ (q), 1);
3040 rr -= yy;
3041 }
3042 }
3043 *qp = scm_i_normbig (q);
3044 *rp = SCM_I_MAKINUM (rr);
3045 }
3046 return;
3047 }
3048 else if (SCM_BIGP (y))
3049 return scm_i_bigint_centered_divide (x, y, qp, rp);
3050 else if (SCM_REALP (y))
3051 return scm_i_inexact_centered_divide
3052 (scm_i_big2dbl (x), SCM_REAL_VALUE (y), qp, rp);
3053 else if (SCM_FRACTIONP (y))
3054 return scm_i_exact_rational_centered_divide (x, y, qp, rp);
3055 else
3056 return two_valued_wta_dispatch_2
3057 (g_scm_centered_divide, x, y, SCM_ARG2,
3058 s_scm_centered_divide, qp, rp);
3059 }
3060 else if (SCM_REALP (x))
3061 {
3062 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
3063 SCM_BIGP (y) || SCM_FRACTIONP (y))
3064 return scm_i_inexact_centered_divide
3065 (SCM_REAL_VALUE (x), scm_to_double (y), qp, rp);
3066 else
3067 return two_valued_wta_dispatch_2
3068 (g_scm_centered_divide, x, y, SCM_ARG2,
3069 s_scm_centered_divide, qp, rp);
3070 }
3071 else if (SCM_FRACTIONP (x))
3072 {
3073 if (SCM_REALP (y))
3074 return scm_i_inexact_centered_divide
3075 (scm_i_fraction2double (x), SCM_REAL_VALUE (y), qp, rp);
3076 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
3077 return scm_i_exact_rational_centered_divide (x, y, qp, rp);
3078 else
3079 return two_valued_wta_dispatch_2
3080 (g_scm_centered_divide, x, y, SCM_ARG2,
3081 s_scm_centered_divide, qp, rp);
3082 }
3083 else
3084 return two_valued_wta_dispatch_2 (g_scm_centered_divide, x, y, SCM_ARG1,
3085 s_scm_centered_divide, qp, rp);
3086 }
3087
3088 static void
3089 scm_i_inexact_centered_divide (double x, double y, SCM *qp, SCM *rp)
3090 {
3091 double q, r;
3092
3093 if (SCM_LIKELY (y > 0))
3094 q = floor (x/y + 0.5);
3095 else if (SCM_LIKELY (y < 0))
3096 q = ceil (x/y - 0.5);
3097 else if (y == 0)
3098 scm_num_overflow (s_scm_centered_divide); /* or return a NaN? */
3099 else
3100 q = guile_NaN;
3101 r = x - q * y;
3102 *qp = scm_from_double (q);
3103 *rp = scm_from_double (r);
3104 }
3105
3106 /* Assumes that both x and y are bigints, though
3107 x might be able to fit into a fixnum. */
3108 static void
3109 scm_i_bigint_centered_divide (SCM x, SCM y, SCM *qp, SCM *rp)
3110 {
3111 SCM q, r, min_r;
3112
3113 /* Note that x might be small enough to fit into a
3114 fixnum, so we must not let it escape into the wild */
3115 q = scm_i_mkbig ();
3116 r = scm_i_mkbig ();
3117
3118 /* min_r will eventually become -abs(y/2) */
3119 min_r = scm_i_mkbig ();
3120 mpz_tdiv_q_2exp (SCM_I_BIG_MPZ (min_r),
3121 SCM_I_BIG_MPZ (y), 1);
3122
3123 /* Arrange for rr to initially be non-positive,
3124 because that simplifies the test to see
3125 if it is within the needed bounds. */
3126 if (mpz_sgn (SCM_I_BIG_MPZ (y)) > 0)
3127 {
3128 mpz_cdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
3129 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3130 mpz_neg (SCM_I_BIG_MPZ (min_r), SCM_I_BIG_MPZ (min_r));
3131 if (mpz_cmp (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (min_r)) < 0)
3132 {
3133 mpz_sub_ui (SCM_I_BIG_MPZ (q),
3134 SCM_I_BIG_MPZ (q), 1);
3135 mpz_add (SCM_I_BIG_MPZ (r),
3136 SCM_I_BIG_MPZ (r),
3137 SCM_I_BIG_MPZ (y));
3138 }
3139 }
3140 else
3141 {
3142 mpz_fdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
3143 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3144 if (mpz_cmp (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (min_r)) < 0)
3145 {
3146 mpz_add_ui (SCM_I_BIG_MPZ (q),
3147 SCM_I_BIG_MPZ (q), 1);
3148 mpz_sub (SCM_I_BIG_MPZ (r),
3149 SCM_I_BIG_MPZ (r),
3150 SCM_I_BIG_MPZ (y));
3151 }
3152 }
3153 scm_remember_upto_here_2 (x, y);
3154 *qp = scm_i_normbig (q);
3155 *rp = scm_i_normbig (r);
3156 }
3157
3158 static void
3159 scm_i_exact_rational_centered_divide (SCM x, SCM y, SCM *qp, SCM *rp)
3160 {
3161 SCM r1;
3162 SCM xd = scm_denominator (x);
3163 SCM yd = scm_denominator (y);
3164
3165 scm_centered_divide (scm_product (scm_numerator (x), yd),
3166 scm_product (scm_numerator (y), xd),
3167 qp, &r1);
3168 *rp = scm_divide (r1, scm_product (xd, yd));
3169 }
3170
3171 static SCM scm_i_inexact_round_quotient (double x, double y);
3172 static SCM scm_i_bigint_round_quotient (SCM x, SCM y);
3173 static SCM scm_i_exact_rational_round_quotient (SCM x, SCM y);
3174
3175 SCM_PRIMITIVE_GENERIC (scm_round_quotient, "round-quotient", 2, 0, 0,
3176 (SCM x, SCM y),
3177 "Return @math{@var{x} / @var{y}} to the nearest integer,\n"
3178 "with ties going to the nearest even integer.\n"
3179 "@lisp\n"
3180 "(round-quotient 123 10) @result{} 12\n"
3181 "(round-quotient 123 -10) @result{} -12\n"
3182 "(round-quotient -123 10) @result{} -12\n"
3183 "(round-quotient -123 -10) @result{} 12\n"
3184 "(round-quotient 125 10) @result{} 12\n"
3185 "(round-quotient 127 10) @result{} 13\n"
3186 "(round-quotient 135 10) @result{} 14\n"
3187 "(round-quotient -123.2 -63.5) @result{} 2.0\n"
3188 "(round-quotient 16/3 -10/7) @result{} -4\n"
3189 "@end lisp")
3190 #define FUNC_NAME s_scm_round_quotient
3191 {
3192 if (SCM_LIKELY (SCM_I_INUMP (x)))
3193 {
3194 scm_t_inum xx = SCM_I_INUM (x);
3195 if (SCM_LIKELY (SCM_I_INUMP (y)))
3196 {
3197 scm_t_inum yy = SCM_I_INUM (y);
3198 if (SCM_UNLIKELY (yy == 0))
3199 scm_num_overflow (s_scm_round_quotient);
3200 else
3201 {
3202 scm_t_inum qq = xx / yy;
3203 scm_t_inum rr = xx % yy;
3204 scm_t_inum ay = yy;
3205 scm_t_inum r2 = 2 * rr;
3206
3207 if (SCM_LIKELY (yy < 0))
3208 {
3209 ay = -ay;
3210 r2 = -r2;
3211 }
3212
3213 if (qq & 1L)
3214 {
3215 if (r2 >= ay)
3216 qq++;
3217 else if (r2 <= -ay)
3218 qq--;
3219 }
3220 else
3221 {
3222 if (r2 > ay)
3223 qq++;
3224 else if (r2 < -ay)
3225 qq--;
3226 }
3227 if (SCM_LIKELY (SCM_FIXABLE (qq)))
3228 return SCM_I_MAKINUM (qq);
3229 else
3230 return scm_i_inum2big (qq);
3231 }
3232 }
3233 else if (SCM_BIGP (y))
3234 {
3235 /* Pass a denormalized bignum version of x (even though it
3236 can fit in a fixnum) to scm_i_bigint_round_quotient */
3237 return scm_i_bigint_round_quotient (scm_i_long2big (xx), y);
3238 }
3239 else if (SCM_REALP (y))
3240 return scm_i_inexact_round_quotient (xx, SCM_REAL_VALUE (y));
3241 else if (SCM_FRACTIONP (y))
3242 return scm_i_exact_rational_round_quotient (x, y);
3243 else
3244 SCM_WTA_DISPATCH_2 (g_scm_round_quotient, x, y, SCM_ARG2,
3245 s_scm_round_quotient);
3246 }
3247 else if (SCM_BIGP (x))
3248 {
3249 if (SCM_LIKELY (SCM_I_INUMP (y)))
3250 {
3251 scm_t_inum yy = SCM_I_INUM (y);
3252 if (SCM_UNLIKELY (yy == 0))
3253 scm_num_overflow (s_scm_round_quotient);
3254 else if (SCM_UNLIKELY (yy == 1))
3255 return x;
3256 else
3257 {
3258 SCM q = scm_i_mkbig ();
3259 scm_t_inum rr;
3260 int needs_adjustment;
3261
3262 if (yy > 0)
3263 {
3264 rr = mpz_fdiv_q_ui (SCM_I_BIG_MPZ (q),
3265 SCM_I_BIG_MPZ (x), yy);
3266 if (mpz_odd_p (SCM_I_BIG_MPZ (q)))
3267 needs_adjustment = (2*rr >= yy);
3268 else
3269 needs_adjustment = (2*rr > yy);
3270 }
3271 else
3272 {
3273 rr = - mpz_cdiv_q_ui (SCM_I_BIG_MPZ (q),
3274 SCM_I_BIG_MPZ (x), -yy);
3275 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
3276 if (mpz_odd_p (SCM_I_BIG_MPZ (q)))
3277 needs_adjustment = (2*rr <= yy);
3278 else
3279 needs_adjustment = (2*rr < yy);
3280 }
3281 scm_remember_upto_here_1 (x);
3282 if (needs_adjustment)
3283 mpz_add_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q), 1);
3284 return scm_i_normbig (q);
3285 }
3286 }
3287 else if (SCM_BIGP (y))
3288 return scm_i_bigint_round_quotient (x, y);
3289 else if (SCM_REALP (y))
3290 return scm_i_inexact_round_quotient
3291 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
3292 else if (SCM_FRACTIONP (y))
3293 return scm_i_exact_rational_round_quotient (x, y);
3294 else
3295 SCM_WTA_DISPATCH_2 (g_scm_round_quotient, x, y, SCM_ARG2,
3296 s_scm_round_quotient);
3297 }
3298 else if (SCM_REALP (x))
3299 {
3300 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
3301 SCM_BIGP (y) || SCM_FRACTIONP (y))
3302 return scm_i_inexact_round_quotient
3303 (SCM_REAL_VALUE (x), scm_to_double (y));
3304 else
3305 SCM_WTA_DISPATCH_2 (g_scm_round_quotient, x, y, SCM_ARG2,
3306 s_scm_round_quotient);
3307 }
3308 else if (SCM_FRACTIONP (x))
3309 {
3310 if (SCM_REALP (y))
3311 return scm_i_inexact_round_quotient
3312 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
3313 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
3314 return scm_i_exact_rational_round_quotient (x, y);
3315 else
3316 SCM_WTA_DISPATCH_2 (g_scm_round_quotient, x, y, SCM_ARG2,
3317 s_scm_round_quotient);
3318 }
3319 else
3320 SCM_WTA_DISPATCH_2 (g_scm_round_quotient, x, y, SCM_ARG1,
3321 s_scm_round_quotient);
3322 }
3323 #undef FUNC_NAME
3324
3325 static SCM
3326 scm_i_inexact_round_quotient (double x, double y)
3327 {
3328 if (SCM_UNLIKELY (y == 0))
3329 scm_num_overflow (s_scm_round_quotient); /* or return a NaN? */
3330 else
3331 return scm_from_double (scm_c_round (x / y));
3332 }
3333
3334 /* Assumes that both x and y are bigints, though
3335 x might be able to fit into a fixnum. */
3336 static SCM
3337 scm_i_bigint_round_quotient (SCM x, SCM y)
3338 {
3339 SCM q, r, r2;
3340 int cmp, needs_adjustment;
3341
3342 /* Note that x might be small enough to fit into a
3343 fixnum, so we must not let it escape into the wild */
3344 q = scm_i_mkbig ();
3345 r = scm_i_mkbig ();
3346 r2 = scm_i_mkbig ();
3347
3348 mpz_fdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
3349 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3350 mpz_mul_2exp (SCM_I_BIG_MPZ (r2), SCM_I_BIG_MPZ (r), 1); /* r2 = 2*r */
3351 scm_remember_upto_here_2 (x, r);
3352
3353 cmp = mpz_cmpabs (SCM_I_BIG_MPZ (r2), SCM_I_BIG_MPZ (y));
3354 if (mpz_odd_p (SCM_I_BIG_MPZ (q)))
3355 needs_adjustment = (cmp >= 0);
3356 else
3357 needs_adjustment = (cmp > 0);
3358 scm_remember_upto_here_2 (r2, y);
3359
3360 if (needs_adjustment)
3361 mpz_add_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q), 1);
3362
3363 return scm_i_normbig (q);
3364 }
3365
3366 static SCM
3367 scm_i_exact_rational_round_quotient (SCM x, SCM y)
3368 {
3369 return scm_round_quotient
3370 (scm_product (scm_numerator (x), scm_denominator (y)),
3371 scm_product (scm_numerator (y), scm_denominator (x)));
3372 }
3373
3374 static SCM scm_i_inexact_round_remainder (double x, double y);
3375 static SCM scm_i_bigint_round_remainder (SCM x, SCM y);
3376 static SCM scm_i_exact_rational_round_remainder (SCM x, SCM y);
3377
3378 SCM_PRIMITIVE_GENERIC (scm_round_remainder, "round-remainder", 2, 0, 0,
3379 (SCM x, SCM y),
3380 "Return the real number @var{r} such that\n"
3381 "@math{@var{x} = @var{q}*@var{y} + @var{r}}, where\n"
3382 "@var{q} is @math{@var{x} / @var{y}} rounded to the\n"
3383 "nearest integer, with ties going to the nearest\n"
3384 "even integer.\n"
3385 "@lisp\n"
3386 "(round-remainder 123 10) @result{} 3\n"
3387 "(round-remainder 123 -10) @result{} 3\n"
3388 "(round-remainder -123 10) @result{} -3\n"
3389 "(round-remainder -123 -10) @result{} -3\n"
3390 "(round-remainder 125 10) @result{} 5\n"
3391 "(round-remainder 127 10) @result{} -3\n"
3392 "(round-remainder 135 10) @result{} -5\n"
3393 "(round-remainder -123.2 -63.5) @result{} 3.8\n"
3394 "(round-remainder 16/3 -10/7) @result{} -8/21\n"
3395 "@end lisp")
3396 #define FUNC_NAME s_scm_round_remainder
3397 {
3398 if (SCM_LIKELY (SCM_I_INUMP (x)))
3399 {
3400 scm_t_inum xx = SCM_I_INUM (x);
3401 if (SCM_LIKELY (SCM_I_INUMP (y)))
3402 {
3403 scm_t_inum yy = SCM_I_INUM (y);
3404 if (SCM_UNLIKELY (yy == 0))
3405 scm_num_overflow (s_scm_round_remainder);
3406 else
3407 {
3408 scm_t_inum qq = xx / yy;
3409 scm_t_inum rr = xx % yy;
3410 scm_t_inum ay = yy;
3411 scm_t_inum r2 = 2 * rr;
3412
3413 if (SCM_LIKELY (yy < 0))
3414 {
3415 ay = -ay;
3416 r2 = -r2;
3417 }
3418
3419 if (qq & 1L)
3420 {
3421 if (r2 >= ay)
3422 rr -= yy;
3423 else if (r2 <= -ay)
3424 rr += yy;
3425 }
3426 else
3427 {
3428 if (r2 > ay)
3429 rr -= yy;
3430 else if (r2 < -ay)
3431 rr += yy;
3432 }
3433 return SCM_I_MAKINUM (rr);
3434 }
3435 }
3436 else if (SCM_BIGP (y))
3437 {
3438 /* Pass a denormalized bignum version of x (even though it
3439 can fit in a fixnum) to scm_i_bigint_round_remainder */
3440 return scm_i_bigint_round_remainder
3441 (scm_i_long2big (xx), y);
3442 }
3443 else if (SCM_REALP (y))
3444 return scm_i_inexact_round_remainder (xx, SCM_REAL_VALUE (y));
3445 else if (SCM_FRACTIONP (y))
3446 return scm_i_exact_rational_round_remainder (x, y);
3447 else
3448 SCM_WTA_DISPATCH_2 (g_scm_round_remainder, x, y, SCM_ARG2,
3449 s_scm_round_remainder);
3450 }
3451 else if (SCM_BIGP (x))
3452 {
3453 if (SCM_LIKELY (SCM_I_INUMP (y)))
3454 {
3455 scm_t_inum yy = SCM_I_INUM (y);
3456 if (SCM_UNLIKELY (yy == 0))
3457 scm_num_overflow (s_scm_round_remainder);
3458 else
3459 {
3460 SCM q = scm_i_mkbig ();
3461 scm_t_inum rr;
3462 int needs_adjustment;
3463
3464 if (yy > 0)
3465 {
3466 rr = mpz_fdiv_q_ui (SCM_I_BIG_MPZ (q),
3467 SCM_I_BIG_MPZ (x), yy);
3468 if (mpz_odd_p (SCM_I_BIG_MPZ (q)))
3469 needs_adjustment = (2*rr >= yy);
3470 else
3471 needs_adjustment = (2*rr > yy);
3472 }
3473 else
3474 {
3475 rr = - mpz_cdiv_q_ui (SCM_I_BIG_MPZ (q),
3476 SCM_I_BIG_MPZ (x), -yy);
3477 if (mpz_odd_p (SCM_I_BIG_MPZ (q)))
3478 needs_adjustment = (2*rr <= yy);
3479 else
3480 needs_adjustment = (2*rr < yy);
3481 }
3482 scm_remember_upto_here_2 (x, q);
3483 if (needs_adjustment)
3484 rr -= yy;
3485 return SCM_I_MAKINUM (rr);
3486 }
3487 }
3488 else if (SCM_BIGP (y))
3489 return scm_i_bigint_round_remainder (x, y);
3490 else if (SCM_REALP (y))
3491 return scm_i_inexact_round_remainder
3492 (scm_i_big2dbl (x), SCM_REAL_VALUE (y));
3493 else if (SCM_FRACTIONP (y))
3494 return scm_i_exact_rational_round_remainder (x, y);
3495 else
3496 SCM_WTA_DISPATCH_2 (g_scm_round_remainder, x, y, SCM_ARG2,
3497 s_scm_round_remainder);
3498 }
3499 else if (SCM_REALP (x))
3500 {
3501 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
3502 SCM_BIGP (y) || SCM_FRACTIONP (y))
3503 return scm_i_inexact_round_remainder
3504 (SCM_REAL_VALUE (x), scm_to_double (y));
3505 else
3506 SCM_WTA_DISPATCH_2 (g_scm_round_remainder, x, y, SCM_ARG2,
3507 s_scm_round_remainder);
3508 }
3509 else if (SCM_FRACTIONP (x))
3510 {
3511 if (SCM_REALP (y))
3512 return scm_i_inexact_round_remainder
3513 (scm_i_fraction2double (x), SCM_REAL_VALUE (y));
3514 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
3515 return scm_i_exact_rational_round_remainder (x, y);
3516 else
3517 SCM_WTA_DISPATCH_2 (g_scm_round_remainder, x, y, SCM_ARG2,
3518 s_scm_round_remainder);
3519 }
3520 else
3521 SCM_WTA_DISPATCH_2 (g_scm_round_remainder, x, y, SCM_ARG1,
3522 s_scm_round_remainder);
3523 }
3524 #undef FUNC_NAME
3525
3526 static SCM
3527 scm_i_inexact_round_remainder (double x, double y)
3528 {
3529 /* Although it would be more efficient to use fmod here, we can't
3530 because it would in some cases produce results inconsistent with
3531 scm_i_inexact_round_quotient, such that x != r + q * y (not even
3532 close). In particular, when x-y/2 is very close to a multiple of
3533 y, then r might be either -abs(y/2) or abs(y/2), but those two
3534 cases must correspond to different choices of q. If quotient
3535 chooses one and remainder chooses the other, it would be bad. */
3536
3537 if (SCM_UNLIKELY (y == 0))
3538 scm_num_overflow (s_scm_round_remainder); /* or return a NaN? */
3539 else
3540 {
3541 double q = scm_c_round (x / y);
3542 return scm_from_double (x - q * y);
3543 }
3544 }
3545
3546 /* Assumes that both x and y are bigints, though
3547 x might be able to fit into a fixnum. */
3548 static SCM
3549 scm_i_bigint_round_remainder (SCM x, SCM y)
3550 {
3551 SCM q, r, r2;
3552 int cmp, needs_adjustment;
3553
3554 /* Note that x might be small enough to fit into a
3555 fixnum, so we must not let it escape into the wild */
3556 q = scm_i_mkbig ();
3557 r = scm_i_mkbig ();
3558 r2 = scm_i_mkbig ();
3559
3560 mpz_fdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
3561 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3562 scm_remember_upto_here_1 (x);
3563 mpz_mul_2exp (SCM_I_BIG_MPZ (r2), SCM_I_BIG_MPZ (r), 1); /* r2 = 2*r */
3564
3565 cmp = mpz_cmpabs (SCM_I_BIG_MPZ (r2), SCM_I_BIG_MPZ (y));
3566 if (mpz_odd_p (SCM_I_BIG_MPZ (q)))
3567 needs_adjustment = (cmp >= 0);
3568 else
3569 needs_adjustment = (cmp > 0);
3570 scm_remember_upto_here_2 (q, r2);
3571
3572 if (needs_adjustment)
3573 mpz_sub (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y));
3574
3575 scm_remember_upto_here_1 (y);
3576 return scm_i_normbig (r);
3577 }
3578
3579 static SCM
3580 scm_i_exact_rational_round_remainder (SCM x, SCM y)
3581 {
3582 SCM xd = scm_denominator (x);
3583 SCM yd = scm_denominator (y);
3584 SCM r1 = scm_round_remainder (scm_product (scm_numerator (x), yd),
3585 scm_product (scm_numerator (y), xd));
3586 return scm_divide (r1, scm_product (xd, yd));
3587 }
3588
3589
3590 static void scm_i_inexact_round_divide (double x, double y, SCM *qp, SCM *rp);
3591 static void scm_i_bigint_round_divide (SCM x, SCM y, SCM *qp, SCM *rp);
3592 static void scm_i_exact_rational_round_divide (SCM x, SCM y, SCM *qp, SCM *rp);
3593
3594 SCM_PRIMITIVE_GENERIC (scm_i_round_divide, "round/", 2, 0, 0,
3595 (SCM x, SCM y),
3596 "Return the integer @var{q} and the real number @var{r}\n"
3597 "such that @math{@var{x} = @var{q}*@var{y} + @var{r}}\n"
3598 "and @var{q} is @math{@var{x} / @var{y}} rounded to the\n"
3599 "nearest integer, with ties going to the nearest even integer.\n"
3600 "@lisp\n"
3601 "(round/ 123 10) @result{} 12 and 3\n"
3602 "(round/ 123 -10) @result{} -12 and 3\n"
3603 "(round/ -123 10) @result{} -12 and -3\n"
3604 "(round/ -123 -10) @result{} 12 and -3\n"
3605 "(round/ 125 10) @result{} 12 and 5\n"
3606 "(round/ 127 10) @result{} 13 and -3\n"
3607 "(round/ 135 10) @result{} 14 and -5\n"
3608 "(round/ -123.2 -63.5) @result{} 2.0 and 3.8\n"
3609 "(round/ 16/3 -10/7) @result{} -4 and -8/21\n"
3610 "@end lisp")
3611 #define FUNC_NAME s_scm_i_round_divide
3612 {
3613 SCM q, r;
3614
3615 scm_round_divide(x, y, &q, &r);
3616 return scm_values (scm_list_2 (q, r));
3617 }
3618 #undef FUNC_NAME
3619
3620 #define s_scm_round_divide s_scm_i_round_divide
3621 #define g_scm_round_divide g_scm_i_round_divide
3622
3623 void
3624 scm_round_divide (SCM x, SCM y, SCM *qp, SCM *rp)
3625 {
3626 if (SCM_LIKELY (SCM_I_INUMP (x)))
3627 {
3628 scm_t_inum xx = SCM_I_INUM (x);
3629 if (SCM_LIKELY (SCM_I_INUMP (y)))
3630 {
3631 scm_t_inum yy = SCM_I_INUM (y);
3632 if (SCM_UNLIKELY (yy == 0))
3633 scm_num_overflow (s_scm_round_divide);
3634 else
3635 {
3636 scm_t_inum qq = xx / yy;
3637 scm_t_inum rr = xx % yy;
3638 scm_t_inum ay = yy;
3639 scm_t_inum r2 = 2 * rr;
3640
3641 if (SCM_LIKELY (yy < 0))
3642 {
3643 ay = -ay;
3644 r2 = -r2;
3645 }
3646
3647 if (qq & 1L)
3648 {
3649 if (r2 >= ay)
3650 { qq++; rr -= yy; }
3651 else if (r2 <= -ay)
3652 { qq--; rr += yy; }
3653 }
3654 else
3655 {
3656 if (r2 > ay)
3657 { qq++; rr -= yy; }
3658 else if (r2 < -ay)
3659 { qq--; rr += yy; }
3660 }
3661 if (SCM_LIKELY (SCM_FIXABLE (qq)))
3662 *qp = SCM_I_MAKINUM (qq);
3663 else
3664 *qp = scm_i_inum2big (qq);
3665 *rp = SCM_I_MAKINUM (rr);
3666 }
3667 return;
3668 }
3669 else if (SCM_BIGP (y))
3670 {
3671 /* Pass a denormalized bignum version of x (even though it
3672 can fit in a fixnum) to scm_i_bigint_round_divide */
3673 return scm_i_bigint_round_divide
3674 (scm_i_long2big (SCM_I_INUM (x)), y, qp, rp);
3675 }
3676 else if (SCM_REALP (y))
3677 return scm_i_inexact_round_divide (xx, SCM_REAL_VALUE (y), qp, rp);
3678 else if (SCM_FRACTIONP (y))
3679 return scm_i_exact_rational_round_divide (x, y, qp, rp);
3680 else
3681 return two_valued_wta_dispatch_2 (g_scm_round_divide, x, y, SCM_ARG2,
3682 s_scm_round_divide, qp, rp);
3683 }
3684 else if (SCM_BIGP (x))
3685 {
3686 if (SCM_LIKELY (SCM_I_INUMP (y)))
3687 {
3688 scm_t_inum yy = SCM_I_INUM (y);
3689 if (SCM_UNLIKELY (yy == 0))
3690 scm_num_overflow (s_scm_round_divide);
3691 else
3692 {
3693 SCM q = scm_i_mkbig ();
3694 scm_t_inum rr;
3695 int needs_adjustment;
3696
3697 if (yy > 0)
3698 {
3699 rr = mpz_fdiv_q_ui (SCM_I_BIG_MPZ (q),
3700 SCM_I_BIG_MPZ (x), yy);
3701 if (mpz_odd_p (SCM_I_BIG_MPZ (q)))
3702 needs_adjustment = (2*rr >= yy);
3703 else
3704 needs_adjustment = (2*rr > yy);
3705 }
3706 else
3707 {
3708 rr = - mpz_cdiv_q_ui (SCM_I_BIG_MPZ (q),
3709 SCM_I_BIG_MPZ (x), -yy);
3710 mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
3711 if (mpz_odd_p (SCM_I_BIG_MPZ (q)))
3712 needs_adjustment = (2*rr <= yy);
3713 else
3714 needs_adjustment = (2*rr < yy);
3715 }
3716 scm_remember_upto_here_1 (x);
3717 if (needs_adjustment)
3718 {
3719 mpz_add_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q), 1);
3720 rr -= yy;
3721 }
3722 *qp = scm_i_normbig (q);
3723 *rp = SCM_I_MAKINUM (rr);
3724 }
3725 return;
3726 }
3727 else if (SCM_BIGP (y))
3728 return scm_i_bigint_round_divide (x, y, qp, rp);
3729 else if (SCM_REALP (y))
3730 return scm_i_inexact_round_divide
3731 (scm_i_big2dbl (x), SCM_REAL_VALUE (y), qp, rp);
3732 else if (SCM_FRACTIONP (y))
3733 return scm_i_exact_rational_round_divide (x, y, qp, rp);
3734 else
3735 return two_valued_wta_dispatch_2 (g_scm_round_divide, x, y, SCM_ARG2,
3736 s_scm_round_divide, qp, rp);
3737 }
3738 else if (SCM_REALP (x))
3739 {
3740 if (SCM_REALP (y) || SCM_I_INUMP (y) ||
3741 SCM_BIGP (y) || SCM_FRACTIONP (y))
3742 return scm_i_inexact_round_divide
3743 (SCM_REAL_VALUE (x), scm_to_double (y), qp, rp);
3744 else
3745 return two_valued_wta_dispatch_2 (g_scm_round_divide, x, y, SCM_ARG2,
3746 s_scm_round_divide, qp, rp);
3747 }
3748 else if (SCM_FRACTIONP (x))
3749 {
3750 if (SCM_REALP (y))
3751 return scm_i_inexact_round_divide
3752 (scm_i_fraction2double (x), SCM_REAL_VALUE (y), qp, rp);
3753 else if (SCM_I_INUMP (y) || SCM_BIGP (y) || SCM_FRACTIONP (y))
3754 return scm_i_exact_rational_round_divide (x, y, qp, rp);
3755 else
3756 return two_valued_wta_dispatch_2 (g_scm_round_divide, x, y, SCM_ARG2,
3757 s_scm_round_divide, qp, rp);
3758 }
3759 else
3760 return two_valued_wta_dispatch_2 (g_scm_round_divide, x, y, SCM_ARG1,
3761 s_scm_round_divide, qp, rp);
3762 }
3763
3764 static void
3765 scm_i_inexact_round_divide (double x, double y, SCM *qp, SCM *rp)
3766 {
3767 if (SCM_UNLIKELY (y == 0))
3768 scm_num_overflow (s_scm_round_divide); /* or return a NaN? */
3769 else
3770 {
3771 double q = scm_c_round (x / y);
3772 double r = x - q * y;
3773 *qp = scm_from_double (q);
3774 *rp = scm_from_double (r);
3775 }
3776 }
3777
3778 /* Assumes that both x and y are bigints, though
3779 x might be able to fit into a fixnum. */
3780 static void
3781 scm_i_bigint_round_divide (SCM x, SCM y, SCM *qp, SCM *rp)
3782 {
3783 SCM q, r, r2;
3784 int cmp, needs_adjustment;
3785
3786 /* Note that x might be small enough to fit into a
3787 fixnum, so we must not let it escape into the wild */
3788 q = scm_i_mkbig ();
3789 r = scm_i_mkbig ();
3790 r2 = scm_i_mkbig ();
3791
3792 mpz_fdiv_qr (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
3793 SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3794 scm_remember_upto_here_1 (x);
3795 mpz_mul_2exp (SCM_I_BIG_MPZ (r2), SCM_I_BIG_MPZ (r), 1); /* r2 = 2*r */
3796
3797 cmp = mpz_cmpabs (SCM_I_BIG_MPZ (r2), SCM_I_BIG_MPZ (y));
3798 if (mpz_odd_p (SCM_I_BIG_MPZ (q)))
3799 needs_adjustment = (cmp >= 0);
3800 else
3801 needs_adjustment = (cmp > 0);
3802
3803 if (needs_adjustment)
3804 {
3805 mpz_add_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q), 1);
3806 mpz_sub (SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (y));
3807 }
3808
3809 scm_remember_upto_here_2 (r2, y);
3810 *qp = scm_i_normbig (q);
3811 *rp = scm_i_normbig (r);
3812 }
3813
3814 static void
3815 scm_i_exact_rational_round_divide (SCM x, SCM y, SCM *qp, SCM *rp)
3816 {
3817 SCM r1;
3818 SCM xd = scm_denominator (x);
3819 SCM yd = scm_denominator (y);
3820
3821 scm_round_divide (scm_product (scm_numerator (x), yd),
3822 scm_product (scm_numerator (y), xd),
3823 qp, &r1);
3824 *rp = scm_divide (r1, scm_product (xd, yd));
3825 }
3826
3827
3828 SCM_PRIMITIVE_GENERIC (scm_i_gcd, "gcd", 0, 2, 1,
3829 (SCM x, SCM y, SCM rest),
3830 "Return the greatest common divisor of all parameter values.\n"
3831 "If called without arguments, 0 is returned.")
3832 #define FUNC_NAME s_scm_i_gcd
3833 {
3834 while (!scm_is_null (rest))
3835 { x = scm_gcd (x, y);
3836 y = scm_car (rest);
3837 rest = scm_cdr (rest);
3838 }
3839 return scm_gcd (x, y);
3840 }
3841 #undef FUNC_NAME
3842
3843 #define s_gcd s_scm_i_gcd
3844 #define g_gcd g_scm_i_gcd
3845
3846 SCM
3847 scm_gcd (SCM x, SCM y)
3848 {
3849 if (SCM_UNBNDP (y))
3850 return SCM_UNBNDP (x) ? SCM_INUM0 : scm_abs (x);
3851
3852 if (SCM_I_INUMP (x))
3853 {
3854 if (SCM_I_INUMP (y))
3855 {
3856 scm_t_inum xx = SCM_I_INUM (x);
3857 scm_t_inum yy = SCM_I_INUM (y);
3858 scm_t_inum u = xx < 0 ? -xx : xx;
3859 scm_t_inum v = yy < 0 ? -yy : yy;
3860 scm_t_inum result;
3861 if (xx == 0)
3862 result = v;
3863 else if (yy == 0)
3864 result = u;
3865 else
3866 {
3867 scm_t_inum k = 1;
3868 scm_t_inum t;
3869 /* Determine a common factor 2^k */
3870 while (!(1 & (u | v)))
3871 {
3872 k <<= 1;
3873 u >>= 1;
3874 v >>= 1;
3875 }
3876 /* Now, any factor 2^n can be eliminated */
3877 if (u & 1)
3878 t = -v;
3879 else
3880 {
3881 t = u;
3882 b3:
3883 t = SCM_SRS (t, 1);
3884 }
3885 if (!(1 & t))
3886 goto b3;
3887 if (t > 0)
3888 u = t;
3889 else
3890 v = -t;
3891 t = u - v;
3892 if (t != 0)
3893 goto b3;
3894 result = u * k;
3895 }
3896 return (SCM_POSFIXABLE (result)
3897 ? SCM_I_MAKINUM (result)
3898 : scm_i_inum2big (result));
3899 }
3900 else if (SCM_BIGP (y))
3901 {
3902 SCM_SWAP (x, y);
3903 goto big_inum;
3904 }
3905 else
3906 SCM_WTA_DISPATCH_2 (g_gcd, x, y, SCM_ARG2, s_gcd);
3907 }
3908 else if (SCM_BIGP (x))
3909 {
3910 if (SCM_I_INUMP (y))
3911 {
3912 scm_t_bits result;
3913 scm_t_inum yy;
3914 big_inum:
3915 yy = SCM_I_INUM (y);
3916 if (yy == 0)
3917 return scm_abs (x);
3918 if (yy < 0)
3919 yy = -yy;
3920 result = mpz_gcd_ui (NULL, SCM_I_BIG_MPZ (x), yy);
3921 scm_remember_upto_here_1 (x);
3922 return (SCM_POSFIXABLE (result)
3923 ? SCM_I_MAKINUM (result)
3924 : scm_from_unsigned_integer (result));
3925 }
3926 else if (SCM_BIGP (y))
3927 {
3928 SCM result = scm_i_mkbig ();
3929 mpz_gcd (SCM_I_BIG_MPZ (result),
3930 SCM_I_BIG_MPZ (x),
3931 SCM_I_BIG_MPZ (y));
3932 scm_remember_upto_here_2 (x, y);
3933 return scm_i_normbig (result);
3934 }
3935 else
3936 SCM_WTA_DISPATCH_2 (g_gcd, x, y, SCM_ARG2, s_gcd);
3937 }
3938 else
3939 SCM_WTA_DISPATCH_2 (g_gcd, x, y, SCM_ARG1, s_gcd);
3940 }
3941
3942 SCM_PRIMITIVE_GENERIC (scm_i_lcm, "lcm", 0, 2, 1,
3943 (SCM x, SCM y, SCM rest),
3944 "Return the least common multiple of the arguments.\n"
3945 "If called without arguments, 1 is returned.")
3946 #define FUNC_NAME s_scm_i_lcm
3947 {
3948 while (!scm_is_null (rest))
3949 { x = scm_lcm (x, y);
3950 y = scm_car (rest);
3951 rest = scm_cdr (rest);
3952 }
3953 return scm_lcm (x, y);
3954 }
3955 #undef FUNC_NAME
3956
3957 #define s_lcm s_scm_i_lcm
3958 #define g_lcm g_scm_i_lcm
3959
3960 SCM
3961 scm_lcm (SCM n1, SCM n2)
3962 {
3963 if (SCM_UNBNDP (n2))
3964 {
3965 if (SCM_UNBNDP (n1))
3966 return SCM_I_MAKINUM (1L);
3967 n2 = SCM_I_MAKINUM (1L);
3968 }
3969
3970 SCM_GASSERT2 (SCM_I_INUMP (n1) || SCM_BIGP (n1),
3971 g_lcm, n1, n2, SCM_ARG1, s_lcm);
3972 SCM_GASSERT2 (SCM_I_INUMP (n2) || SCM_BIGP (n2),
3973 g_lcm, n1, n2, SCM_ARGn, s_lcm);
3974
3975 if (SCM_I_INUMP (n1))
3976 {
3977 if (SCM_I_INUMP (n2))
3978 {
3979 SCM d = scm_gcd (n1, n2);
3980 if (scm_is_eq (d, SCM_INUM0))
3981 return d;
3982 else
3983 return scm_abs (scm_product (n1, scm_quotient (n2, d)));
3984 }
3985 else
3986 {
3987 /* inum n1, big n2 */
3988 inumbig:
3989 {
3990 SCM result = scm_i_mkbig ();
3991 scm_t_inum nn1 = SCM_I_INUM (n1);
3992 if (nn1 == 0) return SCM_INUM0;
3993 if (nn1 < 0) nn1 = - nn1;
3994 mpz_lcm_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n2), nn1);
3995 scm_remember_upto_here_1 (n2);
3996 return result;
3997 }
3998 }
3999 }
4000 else
4001 {
4002 /* big n1 */
4003 if (SCM_I_INUMP (n2))
4004 {
4005 SCM_SWAP (n1, n2);
4006 goto inumbig;
4007 }
4008 else
4009 {
4010 SCM result = scm_i_mkbig ();
4011 mpz_lcm(SCM_I_BIG_MPZ (result),
4012 SCM_I_BIG_MPZ (n1),
4013 SCM_I_BIG_MPZ (n2));
4014 scm_remember_upto_here_2(n1, n2);
4015 /* shouldn't need to normalize b/c lcm of 2 bigs should be big */
4016 return result;
4017 }
4018 }
4019 }
4020
4021 /* Emulating 2's complement bignums with sign magnitude arithmetic:
4022
4023 Logand:
4024 X Y Result Method:
4025 (len)
4026 + + + x (map digit:logand X Y)
4027 + - + x (map digit:logand X (lognot (+ -1 Y)))
4028 - + + y (map digit:logand (lognot (+ -1 X)) Y)
4029 - - - (+ 1 (map digit:logior (+ -1 X) (+ -1 Y)))
4030
4031 Logior:
4032 X Y Result Method:
4033
4034 + + + (map digit:logior X Y)
4035 + - - y (+ 1 (map digit:logand (lognot X) (+ -1 Y)))
4036 - + - x (+ 1 (map digit:logand (+ -1 X) (lognot Y)))
4037 - - - x (+ 1 (map digit:logand (+ -1 X) (+ -1 Y)))
4038
4039 Logxor:
4040 X Y Result Method:
4041
4042 + + + (map digit:logxor X Y)
4043 + - - (+ 1 (map digit:logxor X (+ -1 Y)))
4044 - + - (+ 1 (map digit:logxor (+ -1 X) Y))
4045 - - + (map digit:logxor (+ -1 X) (+ -1 Y))
4046
4047 Logtest:
4048 X Y Result
4049
4050 + + (any digit:logand X Y)
4051 + - (any digit:logand X (lognot (+ -1 Y)))
4052 - + (any digit:logand (lognot (+ -1 X)) Y)
4053 - - #t
4054
4055 */
4056
4057 SCM_DEFINE (scm_i_logand, "logand", 0, 2, 1,
4058 (SCM x, SCM y, SCM rest),
4059 "Return the bitwise AND of the integer arguments.\n\n"
4060 "@lisp\n"
4061 "(logand) @result{} -1\n"
4062 "(logand 7) @result{} 7\n"
4063 "(logand #b111 #b011 #b001) @result{} 1\n"
4064 "@end lisp")
4065 #define FUNC_NAME s_scm_i_logand
4066 {
4067 while (!scm_is_null (rest))
4068 { x = scm_logand (x, y);
4069 y = scm_car (rest);
4070 rest = scm_cdr (rest);
4071 }
4072 return scm_logand (x, y);
4073 }
4074 #undef FUNC_NAME
4075
4076 #define s_scm_logand s_scm_i_logand
4077
4078 SCM scm_logand (SCM n1, SCM n2)
4079 #define FUNC_NAME s_scm_logand
4080 {
4081 scm_t_inum nn1;
4082
4083 if (SCM_UNBNDP (n2))
4084 {
4085 if (SCM_UNBNDP (n1))
4086 return SCM_I_MAKINUM (-1);
4087 else if (!SCM_NUMBERP (n1))
4088 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
4089 else if (SCM_NUMBERP (n1))
4090 return n1;
4091 else
4092 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
4093 }
4094
4095 if (SCM_I_INUMP (n1))
4096 {
4097 nn1 = SCM_I_INUM (n1);
4098 if (SCM_I_INUMP (n2))
4099 {
4100 scm_t_inum nn2 = SCM_I_INUM (n2);
4101 return SCM_I_MAKINUM (nn1 & nn2);
4102 }
4103 else if SCM_BIGP (n2)
4104 {
4105 intbig:
4106 if (n1 == 0)
4107 return SCM_INUM0;
4108 {
4109 SCM result_z = scm_i_mkbig ();
4110 mpz_t nn1_z;
4111 mpz_init_set_si (nn1_z, nn1);
4112 mpz_and (SCM_I_BIG_MPZ (result_z), nn1_z, SCM_I_BIG_MPZ (n2));
4113 scm_remember_upto_here_1 (n2);
4114 mpz_clear (nn1_z);
4115 return scm_i_normbig (result_z);
4116 }
4117 }
4118 else
4119 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
4120 }
4121 else if (SCM_BIGP (n1))
4122 {
4123 if (SCM_I_INUMP (n2))
4124 {
4125 SCM_SWAP (n1, n2);
4126 nn1 = SCM_I_INUM (n1);
4127 goto intbig;
4128 }
4129 else if (SCM_BIGP (n2))
4130 {
4131 SCM result_z = scm_i_mkbig ();
4132 mpz_and (SCM_I_BIG_MPZ (result_z),
4133 SCM_I_BIG_MPZ (n1),
4134 SCM_I_BIG_MPZ (n2));
4135 scm_remember_upto_here_2 (n1, n2);
4136 return scm_i_normbig (result_z);
4137 }
4138 else
4139 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
4140 }
4141 else
4142 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
4143 }
4144 #undef FUNC_NAME
4145
4146
4147 SCM_DEFINE (scm_i_logior, "logior", 0, 2, 1,
4148 (SCM x, SCM y, SCM rest),
4149 "Return the bitwise OR of the integer arguments.\n\n"
4150 "@lisp\n"
4151 "(logior) @result{} 0\n"
4152 "(logior 7) @result{} 7\n"
4153 "(logior #b000 #b001 #b011) @result{} 3\n"
4154 "@end lisp")
4155 #define FUNC_NAME s_scm_i_logior
4156 {
4157 while (!scm_is_null (rest))
4158 { x = scm_logior (x, y);
4159 y = scm_car (rest);
4160 rest = scm_cdr (rest);
4161 }
4162 return scm_logior (x, y);
4163 }
4164 #undef FUNC_NAME
4165
4166 #define s_scm_logior s_scm_i_logior
4167
4168 SCM scm_logior (SCM n1, SCM n2)
4169 #define FUNC_NAME s_scm_logior
4170 {
4171 scm_t_inum nn1;
4172
4173 if (SCM_UNBNDP (n2))
4174 {
4175 if (SCM_UNBNDP (n1))
4176 return SCM_INUM0;
4177 else if (SCM_NUMBERP (n1))
4178 return n1;
4179 else
4180 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
4181 }
4182
4183 if (SCM_I_INUMP (n1))
4184 {
4185 nn1 = SCM_I_INUM (n1);
4186 if (SCM_I_INUMP (n2))
4187 {
4188 long nn2 = SCM_I_INUM (n2);
4189 return SCM_I_MAKINUM (nn1 | nn2);
4190 }
4191 else if (SCM_BIGP (n2))
4192 {
4193 intbig:
4194 if (nn1 == 0)
4195 return n2;
4196 {
4197 SCM result_z = scm_i_mkbig ();
4198 mpz_t nn1_z;
4199 mpz_init_set_si (nn1_z, nn1);
4200 mpz_ior (SCM_I_BIG_MPZ (result_z), nn1_z, SCM_I_BIG_MPZ (n2));
4201 scm_remember_upto_here_1 (n2);
4202 mpz_clear (nn1_z);
4203 return scm_i_normbig (result_z);
4204 }
4205 }
4206 else
4207 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
4208 }
4209 else if (SCM_BIGP (n1))
4210 {
4211 if (SCM_I_INUMP (n2))
4212 {
4213 SCM_SWAP (n1, n2);
4214 nn1 = SCM_I_INUM (n1);
4215 goto intbig;
4216 }
4217 else if (SCM_BIGP (n2))
4218 {
4219 SCM result_z = scm_i_mkbig ();
4220 mpz_ior (SCM_I_BIG_MPZ (result_z),
4221 SCM_I_BIG_MPZ (n1),
4222 SCM_I_BIG_MPZ (n2));
4223 scm_remember_upto_here_2 (n1, n2);
4224 return scm_i_normbig (result_z);
4225 }
4226 else
4227 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
4228 }
4229 else
4230 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
4231 }
4232 #undef FUNC_NAME
4233
4234
4235 SCM_DEFINE (scm_i_logxor, "logxor", 0, 2, 1,
4236 (SCM x, SCM y, SCM rest),
4237 "Return the bitwise XOR of the integer arguments. A bit is\n"
4238 "set in the result if it is set in an odd number of arguments.\n"
4239 "@lisp\n"
4240 "(logxor) @result{} 0\n"
4241 "(logxor 7) @result{} 7\n"
4242 "(logxor #b000 #b001 #b011) @result{} 2\n"
4243 "(logxor #b000 #b001 #b011 #b011) @result{} 1\n"
4244 "@end lisp")
4245 #define FUNC_NAME s_scm_i_logxor
4246 {
4247 while (!scm_is_null (rest))
4248 { x = scm_logxor (x, y);
4249 y = scm_car (rest);
4250 rest = scm_cdr (rest);
4251 }
4252 return scm_logxor (x, y);
4253 }
4254 #undef FUNC_NAME
4255
4256 #define s_scm_logxor s_scm_i_logxor
4257
4258 SCM scm_logxor (SCM n1, SCM n2)
4259 #define FUNC_NAME s_scm_logxor
4260 {
4261 scm_t_inum nn1;
4262
4263 if (SCM_UNBNDP (n2))
4264 {
4265 if (SCM_UNBNDP (n1))
4266 return SCM_INUM0;
4267 else if (SCM_NUMBERP (n1))
4268 return n1;
4269 else
4270 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
4271 }
4272
4273 if (SCM_I_INUMP (n1))
4274 {
4275 nn1 = SCM_I_INUM (n1);
4276 if (SCM_I_INUMP (n2))
4277 {
4278 scm_t_inum nn2 = SCM_I_INUM (n2);
4279 return SCM_I_MAKINUM (nn1 ^ nn2);
4280 }
4281 else if (SCM_BIGP (n2))
4282 {
4283 intbig:
4284 {
4285 SCM result_z = scm_i_mkbig ();
4286 mpz_t nn1_z;
4287 mpz_init_set_si (nn1_z, nn1);
4288 mpz_xor (SCM_I_BIG_MPZ (result_z), nn1_z, SCM_I_BIG_MPZ (n2));
4289 scm_remember_upto_here_1 (n2);
4290 mpz_clear (nn1_z);
4291 return scm_i_normbig (result_z);
4292 }
4293 }
4294 else
4295 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
4296 }
4297 else if (SCM_BIGP (n1))
4298 {
4299 if (SCM_I_INUMP (n2))
4300 {
4301 SCM_SWAP (n1, n2);
4302 nn1 = SCM_I_INUM (n1);
4303 goto intbig;
4304 }
4305 else if (SCM_BIGP (n2))
4306 {
4307 SCM result_z = scm_i_mkbig ();
4308 mpz_xor (SCM_I_BIG_MPZ (result_z),
4309 SCM_I_BIG_MPZ (n1),
4310 SCM_I_BIG_MPZ (n2));
4311 scm_remember_upto_here_2 (n1, n2);
4312 return scm_i_normbig (result_z);
4313 }
4314 else
4315 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
4316 }
4317 else
4318 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
4319 }
4320 #undef FUNC_NAME
4321
4322
4323 SCM_DEFINE (scm_logtest, "logtest", 2, 0, 0,
4324 (SCM j, SCM k),
4325 "Test whether @var{j} and @var{k} have any 1 bits in common.\n"
4326 "This is equivalent to @code{(not (zero? (logand j k)))}, but\n"
4327 "without actually calculating the @code{logand}, just testing\n"
4328 "for non-zero.\n"
4329 "\n"
4330 "@lisp\n"
4331 "(logtest #b0100 #b1011) @result{} #f\n"
4332 "(logtest #b0100 #b0111) @result{} #t\n"
4333 "@end lisp")
4334 #define FUNC_NAME s_scm_logtest
4335 {
4336 scm_t_inum nj;
4337
4338 if (SCM_I_INUMP (j))
4339 {
4340 nj = SCM_I_INUM (j);
4341 if (SCM_I_INUMP (k))
4342 {
4343 scm_t_inum nk = SCM_I_INUM (k);
4344 return scm_from_bool (nj & nk);
4345 }
4346 else if (SCM_BIGP (k))
4347 {
4348 intbig:
4349 if (nj == 0)
4350 return SCM_BOOL_F;
4351 {
4352 SCM result;
4353 mpz_t nj_z;
4354 mpz_init_set_si (nj_z, nj);
4355 mpz_and (nj_z, nj_z, SCM_I_BIG_MPZ (k));
4356 scm_remember_upto_here_1 (k);
4357 result = scm_from_bool (mpz_sgn (nj_z) != 0);
4358 mpz_clear (nj_z);
4359 return result;
4360 }
4361 }
4362 else
4363 SCM_WRONG_TYPE_ARG (SCM_ARG2, k);
4364 }
4365 else if (SCM_BIGP (j))
4366 {
4367 if (SCM_I_INUMP (k))
4368 {
4369 SCM_SWAP (j, k);
4370 nj = SCM_I_INUM (j);
4371 goto intbig;
4372 }
4373 else if (SCM_BIGP (k))
4374 {
4375 SCM result;
4376 mpz_t result_z;
4377 mpz_init (result_z);
4378 mpz_and (result_z,
4379 SCM_I_BIG_MPZ (j),
4380 SCM_I_BIG_MPZ (k));
4381 scm_remember_upto_here_2 (j, k);
4382 result = scm_from_bool (mpz_sgn (result_z) != 0);
4383 mpz_clear (result_z);
4384 return result;
4385 }
4386 else
4387 SCM_WRONG_TYPE_ARG (SCM_ARG2, k);
4388 }
4389 else
4390 SCM_WRONG_TYPE_ARG (SCM_ARG1, j);
4391 }
4392 #undef FUNC_NAME
4393
4394
4395 SCM_DEFINE (scm_logbit_p, "logbit?", 2, 0, 0,
4396 (SCM index, SCM j),
4397 "Test whether bit number @var{index} in @var{j} is set.\n"
4398 "@var{index} starts from 0 for the least significant bit.\n"
4399 "\n"
4400 "@lisp\n"
4401 "(logbit? 0 #b1101) @result{} #t\n"
4402 "(logbit? 1 #b1101) @result{} #f\n"
4403 "(logbit? 2 #b1101) @result{} #t\n"
4404 "(logbit? 3 #b1101) @result{} #t\n"
4405 "(logbit? 4 #b1101) @result{} #f\n"
4406 "@end lisp")
4407 #define FUNC_NAME s_scm_logbit_p
4408 {
4409 unsigned long int iindex;
4410 iindex = scm_to_ulong (index);
4411
4412 if (SCM_I_INUMP (j))
4413 {
4414 /* bits above what's in an inum follow the sign bit */
4415 iindex = min (iindex, SCM_LONG_BIT - 1);
4416 return scm_from_bool ((1L << iindex) & SCM_I_INUM (j));
4417 }
4418 else if (SCM_BIGP (j))
4419 {
4420 int val = mpz_tstbit (SCM_I_BIG_MPZ (j), iindex);
4421 scm_remember_upto_here_1 (j);
4422 return scm_from_bool (val);
4423 }
4424 else
4425 SCM_WRONG_TYPE_ARG (SCM_ARG2, j);
4426 }
4427 #undef FUNC_NAME
4428
4429
4430 SCM_DEFINE (scm_lognot, "lognot", 1, 0, 0,
4431 (SCM n),
4432 "Return the integer which is the ones-complement of the integer\n"
4433 "argument.\n"
4434 "\n"
4435 "@lisp\n"
4436 "(number->string (lognot #b10000000) 2)\n"
4437 " @result{} \"-10000001\"\n"
4438 "(number->string (lognot #b0) 2)\n"
4439 " @result{} \"-1\"\n"
4440 "@end lisp")
4441 #define FUNC_NAME s_scm_lognot
4442 {
4443 if (SCM_I_INUMP (n)) {
4444 /* No overflow here, just need to toggle all the bits making up the inum.
4445 Enhancement: No need to strip the tag and add it back, could just xor
4446 a block of 1 bits, if that worked with the various debug versions of
4447 the SCM typedef. */
4448 return SCM_I_MAKINUM (~ SCM_I_INUM (n));
4449
4450 } else if (SCM_BIGP (n)) {
4451 SCM result = scm_i_mkbig ();
4452 mpz_com (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n));
4453 scm_remember_upto_here_1 (n);
4454 return result;
4455
4456 } else {
4457 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
4458 }
4459 }
4460 #undef FUNC_NAME
4461
4462 /* returns 0 if IN is not an integer. OUT must already be
4463 initialized. */
4464 static int
4465 coerce_to_big (SCM in, mpz_t out)
4466 {
4467 if (SCM_BIGP (in))
4468 mpz_set (out, SCM_I_BIG_MPZ (in));
4469 else if (SCM_I_INUMP (in))
4470 mpz_set_si (out, SCM_I_INUM (in));
4471 else
4472 return 0;
4473
4474 return 1;
4475 }
4476
4477 SCM_DEFINE (scm_modulo_expt, "modulo-expt", 3, 0, 0,
4478 (SCM n, SCM k, SCM m),
4479 "Return @var{n} raised to the integer exponent\n"
4480 "@var{k}, modulo @var{m}.\n"
4481 "\n"
4482 "@lisp\n"
4483 "(modulo-expt 2 3 5)\n"
4484 " @result{} 3\n"
4485 "@end lisp")
4486 #define FUNC_NAME s_scm_modulo_expt
4487 {
4488 mpz_t n_tmp;
4489 mpz_t k_tmp;
4490 mpz_t m_tmp;
4491
4492 /* There are two classes of error we might encounter --
4493 1) Math errors, which we'll report by calling scm_num_overflow,
4494 and
4495 2) wrong-type errors, which of course we'll report by calling
4496 SCM_WRONG_TYPE_ARG.
4497 We don't report those errors immediately, however; instead we do
4498 some cleanup first. These variables tell us which error (if
4499 any) we should report after cleaning up.
4500 */
4501 int report_overflow = 0;
4502
4503 int position_of_wrong_type = 0;
4504 SCM value_of_wrong_type = SCM_INUM0;
4505
4506 SCM result = SCM_UNDEFINED;
4507
4508 mpz_init (n_tmp);
4509 mpz_init (k_tmp);
4510 mpz_init (m_tmp);
4511
4512 if (scm_is_eq (m, SCM_INUM0))
4513 {
4514 report_overflow = 1;
4515 goto cleanup;
4516 }
4517
4518 if (!coerce_to_big (n, n_tmp))
4519 {
4520 value_of_wrong_type = n;
4521 position_of_wrong_type = 1;
4522 goto cleanup;
4523 }
4524
4525 if (!coerce_to_big (k, k_tmp))
4526 {
4527 value_of_wrong_type = k;
4528 position_of_wrong_type = 2;
4529 goto cleanup;
4530 }
4531
4532 if (!coerce_to_big (m, m_tmp))
4533 {
4534 value_of_wrong_type = m;
4535 position_of_wrong_type = 3;
4536 goto cleanup;
4537 }
4538
4539 /* if the exponent K is negative, and we simply call mpz_powm, we
4540 will get a divide-by-zero exception when an inverse 1/n mod m
4541 doesn't exist (or is not unique). Since exceptions are hard to
4542 handle, we'll attempt the inversion "by hand" -- that way, we get
4543 a simple failure code, which is easy to handle. */
4544
4545 if (-1 == mpz_sgn (k_tmp))
4546 {
4547 if (!mpz_invert (n_tmp, n_tmp, m_tmp))
4548 {
4549 report_overflow = 1;
4550 goto cleanup;
4551 }
4552 mpz_neg (k_tmp, k_tmp);
4553 }
4554
4555 result = scm_i_mkbig ();
4556 mpz_powm (SCM_I_BIG_MPZ (result),
4557 n_tmp,
4558 k_tmp,
4559 m_tmp);
4560
4561 if (mpz_sgn (m_tmp) < 0 && mpz_sgn (SCM_I_BIG_MPZ (result)) != 0)
4562 mpz_add (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result), m_tmp);
4563
4564 cleanup:
4565 mpz_clear (m_tmp);
4566 mpz_clear (k_tmp);
4567 mpz_clear (n_tmp);
4568
4569 if (report_overflow)
4570 scm_num_overflow (FUNC_NAME);
4571
4572 if (position_of_wrong_type)
4573 SCM_WRONG_TYPE_ARG (position_of_wrong_type,
4574 value_of_wrong_type);
4575
4576 return scm_i_normbig (result);
4577 }
4578 #undef FUNC_NAME
4579
4580 SCM_DEFINE (scm_integer_expt, "integer-expt", 2, 0, 0,
4581 (SCM n, SCM k),
4582 "Return @var{n} raised to the power @var{k}. @var{k} must be an\n"
4583 "exact integer, @var{n} can be any number.\n"
4584 "\n"
4585 "Negative @var{k} is supported, and results in\n"
4586 "@math{1/@var{n}^abs(@var{k})} in the usual way.\n"
4587 "@math{@var{n}^0} is 1, as usual, and that\n"
4588 "includes @math{0^0} is 1.\n"
4589 "\n"
4590 "@lisp\n"
4591 "(integer-expt 2 5) @result{} 32\n"
4592 "(integer-expt -3 3) @result{} -27\n"
4593 "(integer-expt 5 -3) @result{} 1/125\n"
4594 "(integer-expt 0 0) @result{} 1\n"
4595 "@end lisp")
4596 #define FUNC_NAME s_scm_integer_expt
4597 {
4598 scm_t_inum i2 = 0;
4599 SCM z_i2 = SCM_BOOL_F;
4600 int i2_is_big = 0;
4601 SCM acc = SCM_I_MAKINUM (1L);
4602
4603 /* Specifically refrain from checking the type of the first argument.
4604 This allows us to exponentiate any object that can be multiplied.
4605 If we must raise to a negative power, we must also be able to
4606 take its reciprocal. */
4607 if (!SCM_LIKELY (SCM_I_INUMP (k)) && !SCM_LIKELY (SCM_BIGP (k)))
4608 SCM_WRONG_TYPE_ARG (2, k);
4609
4610 if (SCM_UNLIKELY (scm_is_eq (k, SCM_INUM0)))
4611 return SCM_INUM1; /* n^(exact0) is exact 1, regardless of n */
4612 else if (SCM_UNLIKELY (scm_is_eq (n, SCM_I_MAKINUM (-1L))))
4613 return scm_is_false (scm_even_p (k)) ? n : SCM_INUM1;
4614 /* The next check is necessary only because R6RS specifies different
4615 behavior for 0^(-k) than for (/ 0). If n is not a scheme number,
4616 we simply skip this case and move on. */
4617 else if (SCM_NUMBERP (n) && scm_is_true (scm_zero_p (n)))
4618 {
4619 /* k cannot be 0 at this point, because we
4620 have already checked for that case above */
4621 if (scm_is_true (scm_positive_p (k)))
4622 return n;
4623 else /* return NaN for (0 ^ k) for negative k per R6RS */
4624 return scm_nan ();
4625 }
4626
4627 if (SCM_I_INUMP (k))
4628 i2 = SCM_I_INUM (k);
4629 else if (SCM_BIGP (k))
4630 {
4631 z_i2 = scm_i_clonebig (k, 1);
4632 scm_remember_upto_here_1 (k);
4633 i2_is_big = 1;
4634 }
4635 else
4636 SCM_WRONG_TYPE_ARG (2, k);
4637
4638 if (i2_is_big)
4639 {
4640 if (mpz_sgn(SCM_I_BIG_MPZ (z_i2)) == -1)
4641 {
4642 mpz_neg (SCM_I_BIG_MPZ (z_i2), SCM_I_BIG_MPZ (z_i2));
4643 n = scm_divide (n, SCM_UNDEFINED);
4644 }
4645 while (1)
4646 {
4647 if (mpz_sgn(SCM_I_BIG_MPZ (z_i2)) == 0)
4648 {
4649 return acc;
4650 }
4651 if (mpz_cmp_ui(SCM_I_BIG_MPZ (z_i2), 1) == 0)
4652 {
4653 return scm_product (acc, n);
4654 }
4655 if (mpz_tstbit(SCM_I_BIG_MPZ (z_i2), 0))
4656 acc = scm_product (acc, n);
4657 n = scm_product (n, n);
4658 mpz_fdiv_q_2exp (SCM_I_BIG_MPZ (z_i2), SCM_I_BIG_MPZ (z_i2), 1);
4659 }
4660 }
4661 else
4662 {
4663 if (i2 < 0)
4664 {
4665 i2 = -i2;
4666 n = scm_divide (n, SCM_UNDEFINED);
4667 }
4668 while (1)
4669 {
4670 if (0 == i2)
4671 return acc;
4672 if (1 == i2)
4673 return scm_product (acc, n);
4674 if (i2 & 1)
4675 acc = scm_product (acc, n);
4676 n = scm_product (n, n);
4677 i2 >>= 1;
4678 }
4679 }
4680 }
4681 #undef FUNC_NAME
4682
4683 SCM_DEFINE (scm_ash, "ash", 2, 0, 0,
4684 (SCM n, SCM cnt),
4685 "Return @var{n} shifted left by @var{cnt} bits, or shifted right\n"
4686 "if @var{cnt} is negative. This is an ``arithmetic'' shift.\n"
4687 "\n"
4688 "This is effectively a multiplication by 2^@var{cnt}, and when\n"
4689 "@var{cnt} is negative it's a division, rounded towards negative\n"
4690 "infinity. (Note that this is not the same rounding as\n"
4691 "@code{quotient} does.)\n"
4692 "\n"
4693 "With @var{n} viewed as an infinite precision twos complement,\n"
4694 "@code{ash} means a left shift introducing zero bits, or a right\n"
4695 "shift dropping bits.\n"
4696 "\n"
4697 "@lisp\n"
4698 "(number->string (ash #b1 3) 2) @result{} \"1000\"\n"
4699 "(number->string (ash #b1010 -1) 2) @result{} \"101\"\n"
4700 "\n"
4701 ";; -23 is bits ...11101001, -6 is bits ...111010\n"
4702 "(ash -23 -2) @result{} -6\n"
4703 "@end lisp")
4704 #define FUNC_NAME s_scm_ash
4705 {
4706 long bits_to_shift;
4707 bits_to_shift = scm_to_long (cnt);
4708
4709 if (SCM_I_INUMP (n))
4710 {
4711 scm_t_inum nn = SCM_I_INUM (n);
4712
4713 if (bits_to_shift > 0)
4714 {
4715 /* Left shift of bits_to_shift >= SCM_I_FIXNUM_BIT-1 will always
4716 overflow a non-zero fixnum. For smaller shifts we check the
4717 bits going into positions above SCM_I_FIXNUM_BIT-1. If they're
4718 all 0s for nn>=0, or all 1s for nn<0 then there's no overflow.
4719 Those bits are "nn >> (SCM_I_FIXNUM_BIT-1 -
4720 bits_to_shift)". */
4721
4722 if (nn == 0)
4723 return n;
4724
4725 if (bits_to_shift < SCM_I_FIXNUM_BIT-1
4726 && ((scm_t_bits)
4727 (SCM_SRS (nn, (SCM_I_FIXNUM_BIT-1 - bits_to_shift)) + 1)
4728 <= 1))
4729 {
4730 return SCM_I_MAKINUM (nn << bits_to_shift);
4731 }
4732 else
4733 {
4734 SCM result = scm_i_inum2big (nn);
4735 mpz_mul_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result),
4736 bits_to_shift);
4737 return result;
4738 }
4739 }
4740 else
4741 {
4742 bits_to_shift = -bits_to_shift;
4743 if (bits_to_shift >= SCM_LONG_BIT)
4744 return (nn >= 0 ? SCM_INUM0 : SCM_I_MAKINUM(-1));
4745 else
4746 return SCM_I_MAKINUM (SCM_SRS (nn, bits_to_shift));
4747 }
4748
4749 }
4750 else if (SCM_BIGP (n))
4751 {
4752 SCM result;
4753
4754 if (bits_to_shift == 0)
4755 return n;
4756
4757 result = scm_i_mkbig ();
4758 if (bits_to_shift >= 0)
4759 {
4760 mpz_mul_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n),
4761 bits_to_shift);
4762 return result;
4763 }
4764 else
4765 {
4766 /* GMP doesn't have an fdiv_q_2exp variant returning just a long, so
4767 we have to allocate a bignum even if the result is going to be a
4768 fixnum. */
4769 mpz_fdiv_q_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n),
4770 -bits_to_shift);
4771 return scm_i_normbig (result);
4772 }
4773
4774 }
4775 else
4776 {
4777 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
4778 }
4779 }
4780 #undef FUNC_NAME
4781
4782
4783 SCM_DEFINE (scm_bit_extract, "bit-extract", 3, 0, 0,
4784 (SCM n, SCM start, SCM end),
4785 "Return the integer composed of the @var{start} (inclusive)\n"
4786 "through @var{end} (exclusive) bits of @var{n}. The\n"
4787 "@var{start}th bit becomes the 0-th bit in the result.\n"
4788 "\n"
4789 "@lisp\n"
4790 "(number->string (bit-extract #b1101101010 0 4) 2)\n"
4791 " @result{} \"1010\"\n"
4792 "(number->string (bit-extract #b1101101010 4 9) 2)\n"
4793 " @result{} \"10110\"\n"
4794 "@end lisp")
4795 #define FUNC_NAME s_scm_bit_extract
4796 {
4797 unsigned long int istart, iend, bits;
4798 istart = scm_to_ulong (start);
4799 iend = scm_to_ulong (end);
4800 SCM_ASSERT_RANGE (3, end, (iend >= istart));
4801
4802 /* how many bits to keep */
4803 bits = iend - istart;
4804
4805 if (SCM_I_INUMP (n))
4806 {
4807 scm_t_inum in = SCM_I_INUM (n);
4808
4809 /* When istart>=SCM_I_FIXNUM_BIT we can just limit the shift to
4810 SCM_I_FIXNUM_BIT-1 to get either 0 or -1 per the sign of "in". */
4811 in = SCM_SRS (in, min (istart, SCM_I_FIXNUM_BIT-1));
4812
4813 if (in < 0 && bits >= SCM_I_FIXNUM_BIT)
4814 {
4815 /* Since we emulate two's complement encoded numbers, this
4816 * special case requires us to produce a result that has
4817 * more bits than can be stored in a fixnum.
4818 */
4819 SCM result = scm_i_inum2big (in);
4820 mpz_fdiv_r_2exp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result),
4821 bits);
4822 return result;
4823 }
4824
4825 /* mask down to requisite bits */
4826 bits = min (bits, SCM_I_FIXNUM_BIT);
4827 return SCM_I_MAKINUM (in & ((1L << bits) - 1));
4828 }
4829 else if (SCM_BIGP (n))
4830 {
4831 SCM result;
4832 if (bits == 1)
4833 {
4834 result = SCM_I_MAKINUM (mpz_tstbit (SCM_I_BIG_MPZ (n), istart));
4835 }
4836 else
4837 {
4838 /* ENHANCE-ME: It'd be nice not to allocate a new bignum when
4839 bits<SCM_I_FIXNUM_BIT. Would want some help from GMP to get
4840 such bits into a ulong. */
4841 result = scm_i_mkbig ();
4842 mpz_fdiv_q_2exp (SCM_I_BIG_MPZ(result), SCM_I_BIG_MPZ(n), istart);
4843 mpz_fdiv_r_2exp (SCM_I_BIG_MPZ(result), SCM_I_BIG_MPZ(result), bits);
4844 result = scm_i_normbig (result);
4845 }
4846 scm_remember_upto_here_1 (n);
4847 return result;
4848 }
4849 else
4850 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
4851 }
4852 #undef FUNC_NAME
4853
4854
4855 static const char scm_logtab[] = {
4856 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
4857 };
4858
4859 SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
4860 (SCM n),
4861 "Return the number of bits in integer @var{n}. If integer is\n"
4862 "positive, the 1-bits in its binary representation are counted.\n"
4863 "If negative, the 0-bits in its two's-complement binary\n"
4864 "representation are counted. If 0, 0 is returned.\n"
4865 "\n"
4866 "@lisp\n"
4867 "(logcount #b10101010)\n"
4868 " @result{} 4\n"
4869 "(logcount 0)\n"
4870 " @result{} 0\n"
4871 "(logcount -2)\n"
4872 " @result{} 1\n"
4873 "@end lisp")
4874 #define FUNC_NAME s_scm_logcount
4875 {
4876 if (SCM_I_INUMP (n))
4877 {
4878 unsigned long c = 0;
4879 scm_t_inum nn = SCM_I_INUM (n);
4880 if (nn < 0)
4881 nn = -1 - nn;
4882 while (nn)
4883 {
4884 c += scm_logtab[15 & nn];
4885 nn >>= 4;
4886 }
4887 return SCM_I_MAKINUM (c);
4888 }
4889 else if (SCM_BIGP (n))
4890 {
4891 unsigned long count;
4892 if (mpz_sgn (SCM_I_BIG_MPZ (n)) >= 0)
4893 count = mpz_popcount (SCM_I_BIG_MPZ (n));
4894 else
4895 count = mpz_hamdist (SCM_I_BIG_MPZ (n), z_negative_one);
4896 scm_remember_upto_here_1 (n);
4897 return SCM_I_MAKINUM (count);
4898 }
4899 else
4900 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
4901 }
4902 #undef FUNC_NAME
4903
4904
4905 static const char scm_ilentab[] = {
4906 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
4907 };
4908
4909
4910 SCM_DEFINE (scm_integer_length, "integer-length", 1, 0, 0,
4911 (SCM n),
4912 "Return the number of bits necessary to represent @var{n}.\n"
4913 "\n"
4914 "@lisp\n"
4915 "(integer-length #b10101010)\n"
4916 " @result{} 8\n"
4917 "(integer-length 0)\n"
4918 " @result{} 0\n"
4919 "(integer-length #b1111)\n"
4920 " @result{} 4\n"
4921 "@end lisp")
4922 #define FUNC_NAME s_scm_integer_length
4923 {
4924 if (SCM_I_INUMP (n))
4925 {
4926 unsigned long c = 0;
4927 unsigned int l = 4;
4928 scm_t_inum nn = SCM_I_INUM (n);
4929 if (nn < 0)
4930 nn = -1 - nn;
4931 while (nn)
4932 {
4933 c += 4;
4934 l = scm_ilentab [15 & nn];
4935 nn >>= 4;
4936 }
4937 return SCM_I_MAKINUM (c - 4 + l);
4938 }
4939 else if (SCM_BIGP (n))
4940 {
4941 /* mpz_sizeinbase looks at the absolute value of negatives, whereas we
4942 want a ones-complement. If n is ...111100..00 then mpz_sizeinbase is
4943 1 too big, so check for that and adjust. */
4944 size_t size = mpz_sizeinbase (SCM_I_BIG_MPZ (n), 2);
4945 if (mpz_sgn (SCM_I_BIG_MPZ (n)) < 0
4946 && mpz_scan0 (SCM_I_BIG_MPZ (n), /* no 0 bits above the lowest 1 */
4947 mpz_scan1 (SCM_I_BIG_MPZ (n), 0)) == ULONG_MAX)
4948 size--;
4949 scm_remember_upto_here_1 (n);
4950 return SCM_I_MAKINUM (size);
4951 }
4952 else
4953 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
4954 }
4955 #undef FUNC_NAME
4956
4957 /*** NUMBERS -> STRINGS ***/
4958 #define SCM_MAX_DBL_PREC 60
4959 #define SCM_MAX_DBL_RADIX 36
4960
4961 /* this is an array starting with radix 2, and ending with radix SCM_MAX_DBL_RADIX */
4962 static int scm_dblprec[SCM_MAX_DBL_RADIX - 1];
4963 static double fx_per_radix[SCM_MAX_DBL_RADIX - 1][SCM_MAX_DBL_PREC];
4964
4965 static
4966 void init_dblprec(int *prec, int radix) {
4967 /* determine floating point precision by adding successively
4968 smaller increments to 1.0 until it is considered == 1.0 */
4969 double f = ((double)1.0)/radix;
4970 double fsum = 1.0 + f;
4971
4972 *prec = 0;
4973 while (fsum != 1.0)
4974 {
4975 if (++(*prec) > SCM_MAX_DBL_PREC)
4976 fsum = 1.0;
4977 else
4978 {
4979 f /= radix;
4980 fsum = f + 1.0;
4981 }
4982 }
4983 (*prec) -= 1;
4984 }
4985
4986 static
4987 void init_fx_radix(double *fx_list, int radix)
4988 {
4989 /* initialize a per-radix list of tolerances. When added
4990 to a number < 1.0, we can determine if we should raund
4991 up and quit converting a number to a string. */
4992 int i;
4993 fx_list[0] = 0.0;
4994 fx_list[1] = 0.5;
4995 for( i = 2 ; i < SCM_MAX_DBL_PREC; ++i )
4996 fx_list[i] = (fx_list[i-1] / radix);
4997 }
4998
4999 /* use this array as a way to generate a single digit */
5000 static const char number_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
5001
5002 static size_t
5003 idbl2str (double f, char *a, int radix)
5004 {
5005 int efmt, dpt, d, i, wp;
5006 double *fx;
5007 #ifdef DBL_MIN_10_EXP
5008 double f_cpy;
5009 int exp_cpy;
5010 #endif /* DBL_MIN_10_EXP */
5011 size_t ch = 0;
5012 int exp = 0;
5013
5014 if(radix < 2 ||
5015 radix > SCM_MAX_DBL_RADIX)
5016 {
5017 /* revert to existing behavior */
5018 radix = 10;
5019 }
5020
5021 wp = scm_dblprec[radix-2];
5022 fx = fx_per_radix[radix-2];
5023
5024 if (f == 0.0)
5025 {
5026 #ifdef HAVE_COPYSIGN
5027 double sgn = copysign (1.0, f);
5028
5029 if (sgn < 0.0)
5030 a[ch++] = '-';
5031 #endif
5032 goto zero; /*{a[0]='0'; a[1]='.'; a[2]='0'; return 3;} */
5033 }
5034
5035 if (isinf (f))
5036 {
5037 if (f < 0)
5038 strcpy (a, "-inf.0");
5039 else
5040 strcpy (a, "+inf.0");
5041 return ch+6;
5042 }
5043 else if (isnan (f))
5044 {
5045 strcpy (a, "+nan.0");
5046 return ch+6;
5047 }
5048
5049 if (f < 0.0)
5050 {
5051 f = -f;
5052 a[ch++] = '-';
5053 }
5054
5055 #ifdef DBL_MIN_10_EXP /* Prevent unnormalized values, as from
5056 make-uniform-vector, from causing infinite loops. */
5057 /* just do the checking...if it passes, we do the conversion for our
5058 radix again below */
5059 f_cpy = f;
5060 exp_cpy = exp;
5061
5062 while (f_cpy < 1.0)
5063 {
5064 f_cpy *= 10.0;
5065 if (exp_cpy-- < DBL_MIN_10_EXP)
5066 {
5067 a[ch++] = '#';
5068 a[ch++] = '.';
5069 a[ch++] = '#';
5070 return ch;
5071 }
5072 }
5073 while (f_cpy > 10.0)
5074 {
5075 f_cpy *= 0.10;
5076 if (exp_cpy++ > DBL_MAX_10_EXP)
5077 {
5078 a[ch++] = '#';
5079 a[ch++] = '.';
5080 a[ch++] = '#';
5081 return ch;
5082 }
5083 }
5084 #endif
5085
5086 while (f < 1.0)
5087 {
5088 f *= radix;
5089 exp--;
5090 }
5091 while (f > radix)
5092 {
5093 f /= radix;
5094 exp++;
5095 }
5096
5097 if (f + fx[wp] >= radix)
5098 {
5099 f = 1.0;
5100 exp++;
5101 }
5102 zero:
5103 #ifdef ENGNOT
5104 /* adding 9999 makes this equivalent to abs(x) % 3 */
5105 dpt = (exp + 9999) % 3;
5106 exp -= dpt++;
5107 efmt = 1;
5108 #else
5109 efmt = (exp < -3) || (exp > wp + 2);
5110 if (!efmt)
5111 {
5112 if (exp < 0)
5113 {
5114 a[ch++] = '0';
5115 a[ch++] = '.';
5116 dpt = exp;
5117 while (++dpt)
5118 a[ch++] = '0';
5119 }
5120 else
5121 dpt = exp + 1;
5122 }
5123 else
5124 dpt = 1;
5125 #endif
5126
5127 do
5128 {
5129 d = f;
5130 f -= d;
5131 a[ch++] = number_chars[d];
5132 if (f < fx[wp])
5133 break;
5134 if (f + fx[wp] >= 1.0)
5135 {
5136 a[ch - 1] = number_chars[d+1];
5137 break;
5138 }
5139 f *= radix;
5140 if (!(--dpt))
5141 a[ch++] = '.';
5142 }
5143 while (wp--);
5144
5145 if (dpt > 0)
5146 {
5147 #ifndef ENGNOT
5148 if ((dpt > 4) && (exp > 6))
5149 {
5150 d = (a[0] == '-' ? 2 : 1);
5151 for (i = ch++; i > d; i--)
5152 a[i] = a[i - 1];
5153 a[d] = '.';
5154 efmt = 1;
5155 }
5156 else
5157 #endif
5158 {
5159 while (--dpt)
5160 a[ch++] = '0';
5161 a[ch++] = '.';
5162 }
5163 }
5164 if (a[ch - 1] == '.')
5165 a[ch++] = '0'; /* trailing zero */
5166 if (efmt && exp)
5167 {
5168 a[ch++] = 'e';
5169 if (exp < 0)
5170 {
5171 exp = -exp;
5172 a[ch++] = '-';
5173 }
5174 for (i = radix; i <= exp; i *= radix);
5175 for (i /= radix; i; i /= radix)
5176 {
5177 a[ch++] = number_chars[exp / i];
5178 exp %= i;
5179 }
5180 }
5181 return ch;
5182 }
5183
5184
5185 static size_t
5186 icmplx2str (double real, double imag, char *str, int radix)
5187 {
5188 size_t i;
5189 double sgn;
5190
5191 i = idbl2str (real, str, radix);
5192 #ifdef HAVE_COPYSIGN
5193 sgn = copysign (1.0, imag);
5194 #else
5195 sgn = imag;
5196 #endif
5197 /* Don't output a '+' for negative numbers or for Inf and
5198 NaN. They will provide their own sign. */
5199 if (sgn >= 0 && DOUBLE_IS_FINITE (imag))
5200 str[i++] = '+';
5201 i += idbl2str (imag, &str[i], radix);
5202 str[i++] = 'i';
5203 return i;
5204 }
5205
5206 static size_t
5207 iflo2str (SCM flt, char *str, int radix)
5208 {
5209 size_t i;
5210 if (SCM_REALP (flt))
5211 i = idbl2str (SCM_REAL_VALUE (flt), str, radix);
5212 else
5213 i = icmplx2str (SCM_COMPLEX_REAL (flt), SCM_COMPLEX_IMAG (flt),
5214 str, radix);
5215 return i;
5216 }
5217
5218 /* convert a scm_t_intmax to a string (unterminated). returns the number of
5219 characters in the result.
5220 rad is output base
5221 p is destination: worst case (base 2) is SCM_INTBUFLEN */
5222 size_t
5223 scm_iint2str (scm_t_intmax num, int rad, char *p)
5224 {
5225 if (num < 0)
5226 {
5227 *p++ = '-';
5228 return scm_iuint2str (-num, rad, p) + 1;
5229 }
5230 else
5231 return scm_iuint2str (num, rad, p);
5232 }
5233
5234 /* convert a scm_t_intmax to a string (unterminated). returns the number of
5235 characters in the result.
5236 rad is output base
5237 p is destination: worst case (base 2) is SCM_INTBUFLEN */
5238 size_t
5239 scm_iuint2str (scm_t_uintmax num, int rad, char *p)
5240 {
5241 size_t j = 1;
5242 size_t i;
5243 scm_t_uintmax n = num;
5244
5245 if (rad < 2 || rad > 36)
5246 scm_out_of_range ("scm_iuint2str", scm_from_int (rad));
5247
5248 for (n /= rad; n > 0; n /= rad)
5249 j++;
5250
5251 i = j;
5252 n = num;
5253 while (i--)
5254 {
5255 int d = n % rad;
5256
5257 n /= rad;
5258 p[i] = number_chars[d];
5259 }
5260 return j;
5261 }
5262
5263 SCM_DEFINE (scm_number_to_string, "number->string", 1, 1, 0,
5264 (SCM n, SCM radix),
5265 "Return a string holding the external representation of the\n"
5266 "number @var{n} in the given @var{radix}. If @var{n} is\n"
5267 "inexact, a radix of 10 will be used.")
5268 #define FUNC_NAME s_scm_number_to_string
5269 {
5270 int base;
5271
5272 if (SCM_UNBNDP (radix))
5273 base = 10;
5274 else
5275 base = scm_to_signed_integer (radix, 2, 36);
5276
5277 if (SCM_I_INUMP (n))
5278 {
5279 char num_buf [SCM_INTBUFLEN];
5280 size_t length = scm_iint2str (SCM_I_INUM (n), base, num_buf);
5281 return scm_from_locale_stringn (num_buf, length);
5282 }
5283 else if (SCM_BIGP (n))
5284 {
5285 char *str = mpz_get_str (NULL, base, SCM_I_BIG_MPZ (n));
5286 scm_remember_upto_here_1 (n);
5287 return scm_take_locale_string (str);
5288 }
5289 else if (SCM_FRACTIONP (n))
5290 {
5291 return scm_string_append (scm_list_3 (scm_number_to_string (SCM_FRACTION_NUMERATOR (n), radix),
5292 scm_from_locale_string ("/"),
5293 scm_number_to_string (SCM_FRACTION_DENOMINATOR (n), radix)));
5294 }
5295 else if (SCM_INEXACTP (n))
5296 {
5297 char num_buf [FLOBUFLEN];
5298 return scm_from_locale_stringn (num_buf, iflo2str (n, num_buf, base));
5299 }
5300 else
5301 SCM_WRONG_TYPE_ARG (1, n);
5302 }
5303 #undef FUNC_NAME
5304
5305
5306 /* These print routines used to be stubbed here so that scm_repl.c
5307 wouldn't need SCM_BIGDIG conditionals (pre GMP) */
5308
5309 int
5310 scm_print_real (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
5311 {
5312 char num_buf[FLOBUFLEN];
5313 scm_lfwrite (num_buf, iflo2str (sexp, num_buf, 10), port);
5314 return !0;
5315 }
5316
5317 void
5318 scm_i_print_double (double val, SCM port)
5319 {
5320 char num_buf[FLOBUFLEN];
5321 scm_lfwrite (num_buf, idbl2str (val, num_buf, 10), port);
5322 }
5323
5324 int
5325 scm_print_complex (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
5326
5327 {
5328 char num_buf[FLOBUFLEN];
5329 scm_lfwrite (num_buf, iflo2str (sexp, num_buf, 10), port);
5330 return !0;
5331 }
5332
5333 void
5334 scm_i_print_complex (double real, double imag, SCM port)
5335 {
5336 char num_buf[FLOBUFLEN];
5337 scm_lfwrite (num_buf, icmplx2str (real, imag, num_buf, 10), port);
5338 }
5339
5340 int
5341 scm_i_print_fraction (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
5342 {
5343 SCM str;
5344 str = scm_number_to_string (sexp, SCM_UNDEFINED);
5345 scm_display (str, port);
5346 scm_remember_upto_here_1 (str);
5347 return !0;
5348 }
5349
5350 int
5351 scm_bigprint (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
5352 {
5353 char *str = mpz_get_str (NULL, 10, SCM_I_BIG_MPZ (exp));
5354 scm_remember_upto_here_1 (exp);
5355 scm_lfwrite (str, (size_t) strlen (str), port);
5356 free (str);
5357 return !0;
5358 }
5359 /*** END nums->strs ***/
5360
5361
5362 /*** STRINGS -> NUMBERS ***/
5363
5364 /* The following functions implement the conversion from strings to numbers.
5365 * The implementation somehow follows the grammar for numbers as it is given
5366 * in R5RS. Thus, the functions resemble syntactic units (<ureal R>,
5367 * <uinteger R>, ...) that are used to build up numbers in the grammar. Some
5368 * points should be noted about the implementation:
5369 *
5370 * * Each function keeps a local index variable 'idx' that points at the
5371 * current position within the parsed string. The global index is only
5372 * updated if the function could parse the corresponding syntactic unit
5373 * successfully.
5374 *
5375 * * Similarly, the functions keep track of indicators of inexactness ('#',
5376 * '.' or exponents) using local variables ('hash_seen', 'x').
5377 *
5378 * * Sequences of digits are parsed into temporary variables holding fixnums.
5379 * Only if these fixnums would overflow, the result variables are updated
5380 * using the standard functions scm_add, scm_product, scm_divide etc. Then,
5381 * the temporary variables holding the fixnums are cleared, and the process
5382 * starts over again. If for example fixnums were able to store five decimal
5383 * digits, a number 1234567890 would be parsed in two parts 12345 and 67890,
5384 * and the result was computed as 12345 * 100000 + 67890. In other words,
5385 * only every five digits two bignum operations were performed.
5386 *
5387 * Notes on the handling of exactness specifiers:
5388 *
5389 * When parsing non-real complex numbers, we apply exactness specifiers on
5390 * per-component basis, as is done in PLT Scheme. For complex numbers
5391 * written in rectangular form, exactness specifiers are applied to the
5392 * real and imaginary parts before calling scm_make_rectangular. For
5393 * complex numbers written in polar form, exactness specifiers are applied
5394 * to the magnitude and angle before calling scm_make_polar.
5395 *
5396 * There are two kinds of exactness specifiers: forced and implicit. A
5397 * forced exactness specifier is a "#e" or "#i" prefix at the beginning of
5398 * the entire number, and applies to both components of a complex number.
5399 * "#e" causes each component to be made exact, and "#i" causes each
5400 * component to be made inexact. If no forced exactness specifier is
5401 * present, then the exactness of each component is determined
5402 * independently by the presence or absence of a decimal point or hash mark
5403 * within that component. If a decimal point or hash mark is present, the
5404 * component is made inexact, otherwise it is made exact.
5405 *
5406 * After the exactness specifiers have been applied to each component, they
5407 * are passed to either scm_make_rectangular or scm_make_polar to produce
5408 * the final result. Note that this will result in a real number if the
5409 * imaginary part, magnitude, or angle is an exact 0.
5410 *
5411 * For example, (string->number "#i5.0+0i") does the equivalent of:
5412 *
5413 * (make-rectangular (exact->inexact 5) (exact->inexact 0))
5414 */
5415
5416 enum t_exactness {NO_EXACTNESS, INEXACT, EXACT};
5417
5418 /* R5RS, section 7.1.1, lexical structure of numbers: <uinteger R>. */
5419
5420 /* Caller is responsible for checking that the return value is in range
5421 for the given radix, which should be <= 36. */
5422 static unsigned int
5423 char_decimal_value (scm_t_uint32 c)
5424 {
5425 /* uc_decimal_value returns -1 on error. When cast to an unsigned int,
5426 that's certainly above any valid decimal, so we take advantage of
5427 that to elide some tests. */
5428 unsigned int d = (unsigned int) uc_decimal_value (c);
5429
5430 /* If that failed, try extended hexadecimals, then. Only accept ascii
5431 hexadecimals. */
5432 if (d >= 10U)
5433 {
5434 c = uc_tolower (c);
5435 if (c >= (scm_t_uint32) 'a')
5436 d = c - (scm_t_uint32)'a' + 10U;
5437 }
5438 return d;
5439 }
5440
5441 static SCM
5442 mem2uinteger (SCM mem, unsigned int *p_idx,
5443 unsigned int radix, enum t_exactness *p_exactness)
5444 {
5445 unsigned int idx = *p_idx;
5446 unsigned int hash_seen = 0;
5447 scm_t_bits shift = 1;
5448 scm_t_bits add = 0;
5449 unsigned int digit_value;
5450 SCM result;
5451 char c;
5452 size_t len = scm_i_string_length (mem);
5453
5454 if (idx == len)
5455 return SCM_BOOL_F;
5456
5457 c = scm_i_string_ref (mem, idx);
5458 digit_value = char_decimal_value (c);
5459 if (digit_value >= radix)
5460 return SCM_BOOL_F;
5461
5462 idx++;
5463 result = SCM_I_MAKINUM (digit_value);
5464 while (idx != len)
5465 {
5466 scm_t_wchar c = scm_i_string_ref (mem, idx);
5467 if (c == '#')
5468 {
5469 hash_seen = 1;
5470 digit_value = 0;
5471 }
5472 else if (hash_seen)
5473 break;
5474 else
5475 {
5476 digit_value = char_decimal_value (c);
5477 /* This check catches non-decimals in addition to out-of-range
5478 decimals. */
5479 if (digit_value >= radix)
5480 break;
5481 }
5482
5483 idx++;
5484 if (SCM_MOST_POSITIVE_FIXNUM / radix < shift)
5485 {
5486 result = scm_product (result, SCM_I_MAKINUM (shift));
5487 if (add > 0)
5488 result = scm_sum (result, SCM_I_MAKINUM (add));
5489
5490 shift = radix;
5491 add = digit_value;
5492 }
5493 else
5494 {
5495 shift = shift * radix;
5496 add = add * radix + digit_value;
5497 }
5498 };
5499
5500 if (shift > 1)
5501 result = scm_product (result, SCM_I_MAKINUM (shift));
5502 if (add > 0)
5503 result = scm_sum (result, SCM_I_MAKINUM (add));
5504
5505 *p_idx = idx;
5506 if (hash_seen)
5507 *p_exactness = INEXACT;
5508
5509 return result;
5510 }
5511
5512
5513 /* R5RS, section 7.1.1, lexical structure of numbers: <decimal 10>. Only
5514 * covers the parts of the rules that start at a potential point. The value
5515 * of the digits up to the point have been parsed by the caller and are given
5516 * in variable result. The content of *p_exactness indicates, whether a hash
5517 * has already been seen in the digits before the point.
5518 */
5519
5520 #define DIGIT2UINT(d) (uc_numeric_value(d).numerator)
5521
5522 static SCM
5523 mem2decimal_from_point (SCM result, SCM mem,
5524 unsigned int *p_idx, enum t_exactness *p_exactness)
5525 {
5526 unsigned int idx = *p_idx;
5527 enum t_exactness x = *p_exactness;
5528 size_t len = scm_i_string_length (mem);
5529
5530 if (idx == len)
5531 return result;
5532
5533 if (scm_i_string_ref (mem, idx) == '.')
5534 {
5535 scm_t_bits shift = 1;
5536 scm_t_bits add = 0;
5537 unsigned int digit_value;
5538 SCM big_shift = SCM_INUM1;
5539
5540 idx++;
5541 while (idx != len)
5542 {
5543 scm_t_wchar c = scm_i_string_ref (mem, idx);
5544 if (uc_is_property_decimal_digit ((scm_t_uint32) c))
5545 {
5546 if (x == INEXACT)
5547 return SCM_BOOL_F;
5548 else
5549 digit_value = DIGIT2UINT (c);
5550 }
5551 else if (c == '#')
5552 {
5553 x = INEXACT;
5554 digit_value = 0;
5555 }
5556 else
5557 break;
5558
5559 idx++;
5560 if (SCM_MOST_POSITIVE_FIXNUM / 10 < shift)
5561 {
5562 big_shift = scm_product (big_shift, SCM_I_MAKINUM (shift));
5563 result = scm_product (result, SCM_I_MAKINUM (shift));
5564 if (add > 0)
5565 result = scm_sum (result, SCM_I_MAKINUM (add));
5566
5567 shift = 10;
5568 add = digit_value;
5569 }
5570 else
5571 {
5572 shift = shift * 10;
5573 add = add * 10 + digit_value;
5574 }
5575 };
5576
5577 if (add > 0)
5578 {
5579 big_shift = scm_product (big_shift, SCM_I_MAKINUM (shift));
5580 result = scm_product (result, SCM_I_MAKINUM (shift));
5581 result = scm_sum (result, SCM_I_MAKINUM (add));
5582 }
5583
5584 result = scm_divide (result, big_shift);
5585
5586 /* We've seen a decimal point, thus the value is implicitly inexact. */
5587 x = INEXACT;
5588 }
5589
5590 if (idx != len)
5591 {
5592 int sign = 1;
5593 unsigned int start;
5594 scm_t_wchar c;
5595 int exponent;
5596 SCM e;
5597
5598 /* R5RS, section 7.1.1, lexical structure of numbers: <suffix> */
5599
5600 switch (scm_i_string_ref (mem, idx))
5601 {
5602 case 'd': case 'D':
5603 case 'e': case 'E':
5604 case 'f': case 'F':
5605 case 'l': case 'L':
5606 case 's': case 'S':
5607 idx++;
5608 if (idx == len)
5609 return SCM_BOOL_F;
5610
5611 start = idx;
5612 c = scm_i_string_ref (mem, idx);
5613 if (c == '-')
5614 {
5615 idx++;
5616 if (idx == len)
5617 return SCM_BOOL_F;
5618
5619 sign = -1;
5620 c = scm_i_string_ref (mem, idx);
5621 }
5622 else if (c == '+')
5623 {
5624 idx++;
5625 if (idx == len)
5626 return SCM_BOOL_F;
5627
5628 sign = 1;
5629 c = scm_i_string_ref (mem, idx);
5630 }
5631 else
5632 sign = 1;
5633
5634 if (!uc_is_property_decimal_digit ((scm_t_uint32) c))
5635 return SCM_BOOL_F;
5636
5637 idx++;
5638 exponent = DIGIT2UINT (c);
5639 while (idx != len)
5640 {
5641 scm_t_wchar c = scm_i_string_ref (mem, idx);
5642 if (uc_is_property_decimal_digit ((scm_t_uint32) c))
5643 {
5644 idx++;
5645 if (exponent <= SCM_MAXEXP)
5646 exponent = exponent * 10 + DIGIT2UINT (c);
5647 }
5648 else
5649 break;
5650 }
5651
5652 if (exponent > SCM_MAXEXP)
5653 {
5654 size_t exp_len = idx - start;
5655 SCM exp_string = scm_i_substring_copy (mem, start, start + exp_len);
5656 SCM exp_num = scm_string_to_number (exp_string, SCM_UNDEFINED);
5657 scm_out_of_range ("string->number", exp_num);
5658 }
5659
5660 e = scm_integer_expt (SCM_I_MAKINUM (10), SCM_I_MAKINUM (exponent));
5661 if (sign == 1)
5662 result = scm_product (result, e);
5663 else
5664 result = scm_divide2real (result, e);
5665
5666 /* We've seen an exponent, thus the value is implicitly inexact. */
5667 x = INEXACT;
5668
5669 break;
5670
5671 default:
5672 break;
5673 }
5674 }
5675
5676 *p_idx = idx;
5677 if (x == INEXACT)
5678 *p_exactness = x;
5679
5680 return result;
5681 }
5682
5683
5684 /* R5RS, section 7.1.1, lexical structure of numbers: <ureal R> */
5685
5686 static SCM
5687 mem2ureal (SCM mem, unsigned int *p_idx,
5688 unsigned int radix, enum t_exactness forced_x)
5689 {
5690 unsigned int idx = *p_idx;
5691 SCM result;
5692 size_t len = scm_i_string_length (mem);
5693
5694 /* Start off believing that the number will be exact. This changes
5695 to INEXACT if we see a decimal point or a hash. */
5696 enum t_exactness implicit_x = EXACT;
5697
5698 if (idx == len)
5699 return SCM_BOOL_F;
5700
5701 if (idx+5 <= len && !scm_i_string_strcmp (mem, idx, "inf.0"))
5702 {
5703 *p_idx = idx+5;
5704 return scm_inf ();
5705 }
5706
5707 if (idx+4 < len && !scm_i_string_strcmp (mem, idx, "nan."))
5708 {
5709 /* Cobble up the fractional part. We might want to set the
5710 NaN's mantissa from it. */
5711 idx += 4;
5712 mem2uinteger (mem, &idx, 10, &implicit_x);
5713 *p_idx = idx;
5714 return scm_nan ();
5715 }
5716
5717 if (scm_i_string_ref (mem, idx) == '.')
5718 {
5719 if (radix != 10)
5720 return SCM_BOOL_F;
5721 else if (idx + 1 == len)
5722 return SCM_BOOL_F;
5723 else if (!uc_is_property_decimal_digit ((scm_t_uint32) scm_i_string_ref (mem, idx+1)))
5724 return SCM_BOOL_F;
5725 else
5726 result = mem2decimal_from_point (SCM_INUM0, mem,
5727 p_idx, &implicit_x);
5728 }
5729 else
5730 {
5731 SCM uinteger;
5732
5733 uinteger = mem2uinteger (mem, &idx, radix, &implicit_x);
5734 if (scm_is_false (uinteger))
5735 return SCM_BOOL_F;
5736
5737 if (idx == len)
5738 result = uinteger;
5739 else if (scm_i_string_ref (mem, idx) == '/')
5740 {
5741 SCM divisor;
5742
5743 idx++;
5744 if (idx == len)
5745 return SCM_BOOL_F;
5746
5747 divisor = mem2uinteger (mem, &idx, radix, &implicit_x);
5748 if (scm_is_false (divisor))
5749 return SCM_BOOL_F;
5750
5751 /* both are int/big here, I assume */
5752 result = scm_i_make_ratio (uinteger, divisor);
5753 }
5754 else if (radix == 10)
5755 {
5756 result = mem2decimal_from_point (uinteger, mem, &idx, &implicit_x);
5757 if (scm_is_false (result))
5758 return SCM_BOOL_F;
5759 }
5760 else
5761 result = uinteger;
5762
5763 *p_idx = idx;
5764 }
5765
5766 switch (forced_x)
5767 {
5768 case EXACT:
5769 if (SCM_INEXACTP (result))
5770 return scm_inexact_to_exact (result);
5771 else
5772 return result;
5773 case INEXACT:
5774 if (SCM_INEXACTP (result))
5775 return result;
5776 else
5777 return scm_exact_to_inexact (result);
5778 case NO_EXACTNESS:
5779 if (implicit_x == INEXACT)
5780 {
5781 if (SCM_INEXACTP (result))
5782 return result;
5783 else
5784 return scm_exact_to_inexact (result);
5785 }
5786 else
5787 return result;
5788 }
5789
5790 /* We should never get here */
5791 scm_syserror ("mem2ureal");
5792 }
5793
5794
5795 /* R5RS, section 7.1.1, lexical structure of numbers: <complex R> */
5796
5797 static SCM
5798 mem2complex (SCM mem, unsigned int idx,
5799 unsigned int radix, enum t_exactness forced_x)
5800 {
5801 scm_t_wchar c;
5802 int sign = 0;
5803 SCM ureal;
5804 size_t len = scm_i_string_length (mem);
5805
5806 if (idx == len)
5807 return SCM_BOOL_F;
5808
5809 c = scm_i_string_ref (mem, idx);
5810 if (c == '+')
5811 {
5812 idx++;
5813 sign = 1;
5814 }
5815 else if (c == '-')
5816 {
5817 idx++;
5818 sign = -1;
5819 }
5820
5821 if (idx == len)
5822 return SCM_BOOL_F;
5823
5824 ureal = mem2ureal (mem, &idx, radix, forced_x);
5825 if (scm_is_false (ureal))
5826 {
5827 /* input must be either +i or -i */
5828
5829 if (sign == 0)
5830 return SCM_BOOL_F;
5831
5832 if (scm_i_string_ref (mem, idx) == 'i'
5833 || scm_i_string_ref (mem, idx) == 'I')
5834 {
5835 idx++;
5836 if (idx != len)
5837 return SCM_BOOL_F;
5838
5839 return scm_make_rectangular (SCM_INUM0, SCM_I_MAKINUM (sign));
5840 }
5841 else
5842 return SCM_BOOL_F;
5843 }
5844 else
5845 {
5846 if (sign == -1 && scm_is_false (scm_nan_p (ureal)))
5847 ureal = scm_difference (ureal, SCM_UNDEFINED);
5848
5849 if (idx == len)
5850 return ureal;
5851
5852 c = scm_i_string_ref (mem, idx);
5853 switch (c)
5854 {
5855 case 'i': case 'I':
5856 /* either +<ureal>i or -<ureal>i */
5857
5858 idx++;
5859 if (sign == 0)
5860 return SCM_BOOL_F;
5861 if (idx != len)
5862 return SCM_BOOL_F;
5863 return scm_make_rectangular (SCM_INUM0, ureal);
5864
5865 case '@':
5866 /* polar input: <real>@<real>. */
5867
5868 idx++;
5869 if (idx == len)
5870 return SCM_BOOL_F;
5871 else
5872 {
5873 int sign;
5874 SCM angle;
5875 SCM result;
5876
5877 c = scm_i_string_ref (mem, idx);
5878 if (c == '+')
5879 {
5880 idx++;
5881 if (idx == len)
5882 return SCM_BOOL_F;
5883 sign = 1;
5884 }
5885 else if (c == '-')
5886 {
5887 idx++;
5888 if (idx == len)
5889 return SCM_BOOL_F;
5890 sign = -1;
5891 }
5892 else
5893 sign = 1;
5894
5895 angle = mem2ureal (mem, &idx, radix, forced_x);
5896 if (scm_is_false (angle))
5897 return SCM_BOOL_F;
5898 if (idx != len)
5899 return SCM_BOOL_F;
5900
5901 if (sign == -1 && scm_is_false (scm_nan_p (ureal)))
5902 angle = scm_difference (angle, SCM_UNDEFINED);
5903
5904 result = scm_make_polar (ureal, angle);
5905 return result;
5906 }
5907 case '+':
5908 case '-':
5909 /* expecting input matching <real>[+-]<ureal>?i */
5910
5911 idx++;
5912 if (idx == len)
5913 return SCM_BOOL_F;
5914 else
5915 {
5916 int sign = (c == '+') ? 1 : -1;
5917 SCM imag = mem2ureal (mem, &idx, radix, forced_x);
5918
5919 if (scm_is_false (imag))
5920 imag = SCM_I_MAKINUM (sign);
5921 else if (sign == -1 && scm_is_false (scm_nan_p (imag)))
5922 imag = scm_difference (imag, SCM_UNDEFINED);
5923
5924 if (idx == len)
5925 return SCM_BOOL_F;
5926 if (scm_i_string_ref (mem, idx) != 'i'
5927 && scm_i_string_ref (mem, idx) != 'I')
5928 return SCM_BOOL_F;
5929
5930 idx++;
5931 if (idx != len)
5932 return SCM_BOOL_F;
5933
5934 return scm_make_rectangular (ureal, imag);
5935 }
5936 default:
5937 return SCM_BOOL_F;
5938 }
5939 }
5940 }
5941
5942
5943 /* R5RS, section 7.1.1, lexical structure of numbers: <number> */
5944
5945 enum t_radix {NO_RADIX=0, DUAL=2, OCT=8, DEC=10, HEX=16};
5946
5947 SCM
5948 scm_i_string_to_number (SCM mem, unsigned int default_radix)
5949 {
5950 unsigned int idx = 0;
5951 unsigned int radix = NO_RADIX;
5952 enum t_exactness forced_x = NO_EXACTNESS;
5953 size_t len = scm_i_string_length (mem);
5954
5955 /* R5RS, section 7.1.1, lexical structure of numbers: <prefix R> */
5956 while (idx + 2 < len && scm_i_string_ref (mem, idx) == '#')
5957 {
5958 switch (scm_i_string_ref (mem, idx + 1))
5959 {
5960 case 'b': case 'B':
5961 if (radix != NO_RADIX)
5962 return SCM_BOOL_F;
5963 radix = DUAL;
5964 break;
5965 case 'd': case 'D':
5966 if (radix != NO_RADIX)
5967 return SCM_BOOL_F;
5968 radix = DEC;
5969 break;
5970 case 'i': case 'I':
5971 if (forced_x != NO_EXACTNESS)
5972 return SCM_BOOL_F;
5973 forced_x = INEXACT;
5974 break;
5975 case 'e': case 'E':
5976 if (forced_x != NO_EXACTNESS)
5977 return SCM_BOOL_F;
5978 forced_x = EXACT;
5979 break;
5980 case 'o': case 'O':
5981 if (radix != NO_RADIX)
5982 return SCM_BOOL_F;
5983 radix = OCT;
5984 break;
5985 case 'x': case 'X':
5986 if (radix != NO_RADIX)
5987 return SCM_BOOL_F;
5988 radix = HEX;
5989 break;
5990 default:
5991 return SCM_BOOL_F;
5992 }
5993 idx += 2;
5994 }
5995
5996 /* R5RS, section 7.1.1, lexical structure of numbers: <complex R> */
5997 if (radix == NO_RADIX)
5998 radix = default_radix;
5999
6000 return mem2complex (mem, idx, radix, forced_x);
6001 }
6002
6003 SCM
6004 scm_c_locale_stringn_to_number (const char* mem, size_t len,
6005 unsigned int default_radix)
6006 {
6007 SCM str = scm_from_locale_stringn (mem, len);
6008
6009 return scm_i_string_to_number (str, default_radix);
6010 }
6011
6012
6013 SCM_DEFINE (scm_string_to_number, "string->number", 1, 1, 0,
6014 (SCM string, SCM radix),
6015 "Return a number of the maximally precise representation\n"
6016 "expressed by the given @var{string}. @var{radix} must be an\n"
6017 "exact integer, either 2, 8, 10, or 16. If supplied, @var{radix}\n"
6018 "is a default radix that may be overridden by an explicit radix\n"
6019 "prefix in @var{string} (e.g. \"#o177\"). If @var{radix} is not\n"
6020 "supplied, then the default radix is 10. If string is not a\n"
6021 "syntactically valid notation for a number, then\n"
6022 "@code{string->number} returns @code{#f}.")
6023 #define FUNC_NAME s_scm_string_to_number
6024 {
6025 SCM answer;
6026 unsigned int base;
6027 SCM_VALIDATE_STRING (1, string);
6028
6029 if (SCM_UNBNDP (radix))
6030 base = 10;
6031 else
6032 base = scm_to_unsigned_integer (radix, 2, INT_MAX);
6033
6034 answer = scm_i_string_to_number (string, base);
6035 scm_remember_upto_here_1 (string);
6036 return answer;
6037 }
6038 #undef FUNC_NAME
6039
6040
6041 /*** END strs->nums ***/
6042
6043
6044 SCM_DEFINE (scm_number_p, "number?", 1, 0, 0,
6045 (SCM x),
6046 "Return @code{#t} if @var{x} is a number, @code{#f}\n"
6047 "otherwise.")
6048 #define FUNC_NAME s_scm_number_p
6049 {
6050 return scm_from_bool (SCM_NUMBERP (x));
6051 }
6052 #undef FUNC_NAME
6053
6054 SCM_DEFINE (scm_complex_p, "complex?", 1, 0, 0,
6055 (SCM x),
6056 "Return @code{#t} if @var{x} is a complex number, @code{#f}\n"
6057 "otherwise. Note that the sets of real, rational and integer\n"
6058 "values form subsets of the set of complex numbers, i. e. the\n"
6059 "predicate will also be fulfilled if @var{x} is a real,\n"
6060 "rational or integer number.")
6061 #define FUNC_NAME s_scm_complex_p
6062 {
6063 /* all numbers are complex. */
6064 return scm_number_p (x);
6065 }
6066 #undef FUNC_NAME
6067
6068 SCM_DEFINE (scm_real_p, "real?", 1, 0, 0,
6069 (SCM x),
6070 "Return @code{#t} if @var{x} is a real number, @code{#f}\n"
6071 "otherwise. Note that the set of integer values forms a subset of\n"
6072 "the set of real numbers, i. e. the predicate will also be\n"
6073 "fulfilled if @var{x} is an integer number.")
6074 #define FUNC_NAME s_scm_real_p
6075 {
6076 return scm_from_bool
6077 (SCM_I_INUMP (x) || SCM_REALP (x) || SCM_BIGP (x) || SCM_FRACTIONP (x));
6078 }
6079 #undef FUNC_NAME
6080
6081 SCM_DEFINE (scm_rational_p, "rational?", 1, 0, 0,
6082 (SCM x),
6083 "Return @code{#t} if @var{x} is a rational number, @code{#f}\n"
6084 "otherwise. Note that the set of integer values forms a subset of\n"
6085 "the set of rational numbers, i. e. the predicate will also be\n"
6086 "fulfilled if @var{x} is an integer number.")
6087 #define FUNC_NAME s_scm_rational_p
6088 {
6089 if (SCM_I_INUMP (x) || SCM_BIGP (x) || SCM_FRACTIONP (x))
6090 return SCM_BOOL_T;
6091 else if (SCM_REALP (x))
6092 /* due to their limited precision, finite floating point numbers are
6093 rational as well. (finite means neither infinity nor a NaN) */
6094 return scm_from_bool (DOUBLE_IS_FINITE (SCM_REAL_VALUE (x)));
6095 else
6096 return SCM_BOOL_F;
6097 }
6098 #undef FUNC_NAME
6099
6100 SCM_DEFINE (scm_integer_p, "integer?", 1, 0, 0,
6101 (SCM x),
6102 "Return @code{#t} if @var{x} is an integer number, @code{#f}\n"
6103 "else.")
6104 #define FUNC_NAME s_scm_integer_p
6105 {
6106 if (SCM_I_INUMP (x) || SCM_BIGP (x))
6107 return SCM_BOOL_T;
6108 else if (SCM_REALP (x))
6109 {
6110 double val = SCM_REAL_VALUE (x);
6111 return scm_from_bool (!isinf (val) && (val == floor (val)));
6112 }
6113 else
6114 return SCM_BOOL_F;
6115 }
6116 #undef FUNC_NAME
6117
6118
6119 SCM scm_i_num_eq_p (SCM, SCM, SCM);
6120 SCM_PRIMITIVE_GENERIC (scm_i_num_eq_p, "=", 0, 2, 1,
6121 (SCM x, SCM y, SCM rest),
6122 "Return @code{#t} if all parameters are numerically equal.")
6123 #define FUNC_NAME s_scm_i_num_eq_p
6124 {
6125 if (SCM_UNBNDP (x) || SCM_UNBNDP (y))
6126 return SCM_BOOL_T;
6127 while (!scm_is_null (rest))
6128 {
6129 if (scm_is_false (scm_num_eq_p (x, y)))
6130 return SCM_BOOL_F;
6131 x = y;
6132 y = scm_car (rest);
6133 rest = scm_cdr (rest);
6134 }
6135 return scm_num_eq_p (x, y);
6136 }
6137 #undef FUNC_NAME
6138 SCM
6139 scm_num_eq_p (SCM x, SCM y)
6140 {
6141 again:
6142 if (SCM_I_INUMP (x))
6143 {
6144 scm_t_signed_bits xx = SCM_I_INUM (x);
6145 if (SCM_I_INUMP (y))
6146 {
6147 scm_t_signed_bits yy = SCM_I_INUM (y);
6148 return scm_from_bool (xx == yy);
6149 }
6150 else if (SCM_BIGP (y))
6151 return SCM_BOOL_F;
6152 else if (SCM_REALP (y))
6153 {
6154 /* On a 32-bit system an inum fits a double, we can cast the inum
6155 to a double and compare.
6156
6157 But on a 64-bit system an inum is bigger than a double and
6158 casting it to a double (call that dxx) will round. dxx is at
6159 worst 1 bigger or smaller than xx, so if dxx==yy we know yy is
6160 an integer and fits a long. So we cast yy to a long and
6161 compare with plain xx.
6162
6163 An alternative (for any size system actually) would be to check
6164 yy is an integer (with floor) and is in range of an inum
6165 (compare against appropriate powers of 2) then test
6166 xx==(scm_t_signed_bits)yy. It's just a matter of which
6167 casts/comparisons might be fastest or easiest for the cpu. */
6168
6169 double yy = SCM_REAL_VALUE (y);
6170 return scm_from_bool ((double) xx == yy
6171 && (DBL_MANT_DIG >= SCM_I_FIXNUM_BIT-1
6172 || xx == (scm_t_signed_bits) yy));
6173 }
6174 else if (SCM_COMPLEXP (y))
6175 return scm_from_bool (((double) xx == SCM_COMPLEX_REAL (y))
6176 && (0.0 == SCM_COMPLEX_IMAG (y)));
6177 else if (SCM_FRACTIONP (y))
6178 return SCM_BOOL_F;
6179 else
6180 SCM_WTA_DISPATCH_2 (g_scm_i_num_eq_p, x, y, SCM_ARGn, s_scm_i_num_eq_p);
6181 }
6182 else if (SCM_BIGP (x))
6183 {
6184 if (SCM_I_INUMP (y))
6185 return SCM_BOOL_F;
6186 else if (SCM_BIGP (y))
6187 {
6188 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
6189 scm_remember_upto_here_2 (x, y);
6190 return scm_from_bool (0 == cmp);
6191 }
6192 else if (SCM_REALP (y))
6193 {
6194 int cmp;
6195 if (isnan (SCM_REAL_VALUE (y)))
6196 return SCM_BOOL_F;
6197 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
6198 scm_remember_upto_here_1 (x);
6199 return scm_from_bool (0 == cmp);
6200 }
6201 else if (SCM_COMPLEXP (y))
6202 {
6203 int cmp;
6204 if (0.0 != SCM_COMPLEX_IMAG (y))
6205 return SCM_BOOL_F;
6206 if (isnan (SCM_COMPLEX_REAL (y)))
6207 return SCM_BOOL_F;
6208 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_COMPLEX_REAL (y));
6209 scm_remember_upto_here_1 (x);
6210 return scm_from_bool (0 == cmp);
6211 }
6212 else if (SCM_FRACTIONP (y))
6213 return SCM_BOOL_F;
6214 else
6215 SCM_WTA_DISPATCH_2 (g_scm_i_num_eq_p, x, y, SCM_ARGn, s_scm_i_num_eq_p);
6216 }
6217 else if (SCM_REALP (x))
6218 {
6219 double xx = SCM_REAL_VALUE (x);
6220 if (SCM_I_INUMP (y))
6221 {
6222 /* see comments with inum/real above */
6223 scm_t_signed_bits yy = SCM_I_INUM (y);
6224 return scm_from_bool (xx == (double) yy
6225 && (DBL_MANT_DIG >= SCM_I_FIXNUM_BIT-1
6226 || (scm_t_signed_bits) xx == yy));
6227 }
6228 else if (SCM_BIGP (y))
6229 {
6230 int cmp;
6231 if (isnan (SCM_REAL_VALUE (x)))
6232 return SCM_BOOL_F;
6233 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
6234 scm_remember_upto_here_1 (y);
6235 return scm_from_bool (0 == cmp);
6236 }
6237 else if (SCM_REALP (y))
6238 return scm_from_bool (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
6239 else if (SCM_COMPLEXP (y))
6240 return scm_from_bool ((SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y))
6241 && (0.0 == SCM_COMPLEX_IMAG (y)));
6242 else if (SCM_FRACTIONP (y))
6243 {
6244 double xx = SCM_REAL_VALUE (x);
6245 if (isnan (xx))
6246 return SCM_BOOL_F;
6247 if (isinf (xx))
6248 return scm_from_bool (xx < 0.0);
6249 x = scm_inexact_to_exact (x); /* with x as frac or int */
6250 goto again;
6251 }
6252 else
6253 SCM_WTA_DISPATCH_2 (g_scm_i_num_eq_p, x, y, SCM_ARGn, s_scm_i_num_eq_p);
6254 }
6255 else if (SCM_COMPLEXP (x))
6256 {
6257 if (SCM_I_INUMP (y))
6258 return scm_from_bool ((SCM_COMPLEX_REAL (x) == (double) SCM_I_INUM (y))
6259 && (SCM_COMPLEX_IMAG (x) == 0.0));
6260 else if (SCM_BIGP (y))
6261 {
6262 int cmp;
6263 if (0.0 != SCM_COMPLEX_IMAG (x))
6264 return SCM_BOOL_F;
6265 if (isnan (SCM_COMPLEX_REAL (x)))
6266 return SCM_BOOL_F;
6267 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_COMPLEX_REAL (x));
6268 scm_remember_upto_here_1 (y);
6269 return scm_from_bool (0 == cmp);
6270 }
6271 else if (SCM_REALP (y))
6272 return scm_from_bool ((SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y))
6273 && (SCM_COMPLEX_IMAG (x) == 0.0));
6274 else if (SCM_COMPLEXP (y))
6275 return scm_from_bool ((SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y))
6276 && (SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y)));
6277 else if (SCM_FRACTIONP (y))
6278 {
6279 double xx;
6280 if (SCM_COMPLEX_IMAG (x) != 0.0)
6281 return SCM_BOOL_F;
6282 xx = SCM_COMPLEX_REAL (x);
6283 if (isnan (xx))
6284 return SCM_BOOL_F;
6285 if (isinf (xx))
6286 return scm_from_bool (xx < 0.0);
6287 x = scm_inexact_to_exact (x); /* with x as frac or int */
6288 goto again;
6289 }
6290 else
6291 SCM_WTA_DISPATCH_2 (g_scm_i_num_eq_p, x, y, SCM_ARGn, s_scm_i_num_eq_p);
6292 }
6293 else if (SCM_FRACTIONP (x))
6294 {
6295 if (SCM_I_INUMP (y))
6296 return SCM_BOOL_F;
6297 else if (SCM_BIGP (y))
6298 return SCM_BOOL_F;
6299 else if (SCM_REALP (y))
6300 {
6301 double yy = SCM_REAL_VALUE (y);
6302 if (isnan (yy))
6303 return SCM_BOOL_F;
6304 if (isinf (yy))
6305 return scm_from_bool (0.0 < yy);
6306 y = scm_inexact_to_exact (y); /* with y as frac or int */
6307 goto again;
6308 }
6309 else if (SCM_COMPLEXP (y))
6310 {
6311 double yy;
6312 if (SCM_COMPLEX_IMAG (y) != 0.0)
6313 return SCM_BOOL_F;
6314 yy = SCM_COMPLEX_REAL (y);
6315 if (isnan (yy))
6316 return SCM_BOOL_F;
6317 if (isinf (yy))
6318 return scm_from_bool (0.0 < yy);
6319 y = scm_inexact_to_exact (y); /* with y as frac or int */
6320 goto again;
6321 }
6322 else if (SCM_FRACTIONP (y))
6323 return scm_i_fraction_equalp (x, y);
6324 else
6325 SCM_WTA_DISPATCH_2 (g_scm_i_num_eq_p, x, y, SCM_ARGn, s_scm_i_num_eq_p);
6326 }
6327 else
6328 SCM_WTA_DISPATCH_2 (g_scm_i_num_eq_p, x, y, SCM_ARG1, s_scm_i_num_eq_p);
6329 }
6330
6331
6332 /* OPTIMIZE-ME: For int/frac and frac/frac compares, the multiplications
6333 done are good for inums, but for bignums an answer can almost always be
6334 had by just examining a few high bits of the operands, as done by GMP in
6335 mpq_cmp. flonum/frac compares likewise, but with the slight complication
6336 of the float exponent to take into account. */
6337
6338 SCM_INTERNAL SCM scm_i_num_less_p (SCM, SCM, SCM);
6339 SCM_PRIMITIVE_GENERIC (scm_i_num_less_p, "<", 0, 2, 1,
6340 (SCM x, SCM y, SCM rest),
6341 "Return @code{#t} if the list of parameters is monotonically\n"
6342 "increasing.")
6343 #define FUNC_NAME s_scm_i_num_less_p
6344 {
6345 if (SCM_UNBNDP (x) || SCM_UNBNDP (y))
6346 return SCM_BOOL_T;
6347 while (!scm_is_null (rest))
6348 {
6349 if (scm_is_false (scm_less_p (x, y)))
6350 return SCM_BOOL_F;
6351 x = y;
6352 y = scm_car (rest);
6353 rest = scm_cdr (rest);
6354 }
6355 return scm_less_p (x, y);
6356 }
6357 #undef FUNC_NAME
6358 SCM
6359 scm_less_p (SCM x, SCM y)
6360 {
6361 again:
6362 if (SCM_I_INUMP (x))
6363 {
6364 scm_t_inum xx = SCM_I_INUM (x);
6365 if (SCM_I_INUMP (y))
6366 {
6367 scm_t_inum yy = SCM_I_INUM (y);
6368 return scm_from_bool (xx < yy);
6369 }
6370 else if (SCM_BIGP (y))
6371 {
6372 int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
6373 scm_remember_upto_here_1 (y);
6374 return scm_from_bool (sgn > 0);
6375 }
6376 else if (SCM_REALP (y))
6377 return scm_from_bool ((double) xx < SCM_REAL_VALUE (y));
6378 else if (SCM_FRACTIONP (y))
6379 {
6380 /* "x < a/b" becomes "x*b < a" */
6381 int_frac:
6382 x = scm_product (x, SCM_FRACTION_DENOMINATOR (y));
6383 y = SCM_FRACTION_NUMERATOR (y);
6384 goto again;
6385 }
6386 else
6387 SCM_WTA_DISPATCH_2 (g_scm_i_num_less_p, x, y, SCM_ARGn, s_scm_i_num_less_p);
6388 }
6389 else if (SCM_BIGP (x))
6390 {
6391 if (SCM_I_INUMP (y))
6392 {
6393 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
6394 scm_remember_upto_here_1 (x);
6395 return scm_from_bool (sgn < 0);
6396 }
6397 else if (SCM_BIGP (y))
6398 {
6399 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
6400 scm_remember_upto_here_2 (x, y);
6401 return scm_from_bool (cmp < 0);
6402 }
6403 else if (SCM_REALP (y))
6404 {
6405 int cmp;
6406 if (isnan (SCM_REAL_VALUE (y)))
6407 return SCM_BOOL_F;
6408 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
6409 scm_remember_upto_here_1 (x);
6410 return scm_from_bool (cmp < 0);
6411 }
6412 else if (SCM_FRACTIONP (y))
6413 goto int_frac;
6414 else
6415 SCM_WTA_DISPATCH_2 (g_scm_i_num_less_p, x, y, SCM_ARGn, s_scm_i_num_less_p);
6416 }
6417 else if (SCM_REALP (x))
6418 {
6419 if (SCM_I_INUMP (y))
6420 return scm_from_bool (SCM_REAL_VALUE (x) < (double) SCM_I_INUM (y));
6421 else if (SCM_BIGP (y))
6422 {
6423 int cmp;
6424 if (isnan (SCM_REAL_VALUE (x)))
6425 return SCM_BOOL_F;
6426 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
6427 scm_remember_upto_here_1 (y);
6428 return scm_from_bool (cmp > 0);
6429 }
6430 else if (SCM_REALP (y))
6431 return scm_from_bool (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y));
6432 else if (SCM_FRACTIONP (y))
6433 {
6434 double xx = SCM_REAL_VALUE (x);
6435 if (isnan (xx))
6436 return SCM_BOOL_F;
6437 if (isinf (xx))
6438 return scm_from_bool (xx < 0.0);
6439 x = scm_inexact_to_exact (x); /* with x as frac or int */
6440 goto again;
6441 }
6442 else
6443 SCM_WTA_DISPATCH_2 (g_scm_i_num_less_p, x, y, SCM_ARGn, s_scm_i_num_less_p);
6444 }
6445 else if (SCM_FRACTIONP (x))
6446 {
6447 if (SCM_I_INUMP (y) || SCM_BIGP (y))
6448 {
6449 /* "a/b < y" becomes "a < y*b" */
6450 y = scm_product (y, SCM_FRACTION_DENOMINATOR (x));
6451 x = SCM_FRACTION_NUMERATOR (x);
6452 goto again;
6453 }
6454 else if (SCM_REALP (y))
6455 {
6456 double yy = SCM_REAL_VALUE (y);
6457 if (isnan (yy))
6458 return SCM_BOOL_F;
6459 if (isinf (yy))
6460 return scm_from_bool (0.0 < yy);
6461 y = scm_inexact_to_exact (y); /* with y as frac or int */
6462 goto again;
6463 }
6464 else if (SCM_FRACTIONP (y))
6465 {
6466 /* "a/b < c/d" becomes "a*d < c*b" */
6467 SCM new_x = scm_product (SCM_FRACTION_NUMERATOR (x),
6468 SCM_FRACTION_DENOMINATOR (y));
6469 SCM new_y = scm_product (SCM_FRACTION_NUMERATOR (y),
6470 SCM_FRACTION_DENOMINATOR (x));
6471 x = new_x;
6472 y = new_y;
6473 goto again;
6474 }
6475 else
6476 SCM_WTA_DISPATCH_2 (g_scm_i_num_less_p, x, y, SCM_ARGn, s_scm_i_num_less_p);
6477 }
6478 else
6479 SCM_WTA_DISPATCH_2 (g_scm_i_num_less_p, x, y, SCM_ARG1, s_scm_i_num_less_p);
6480 }
6481
6482
6483 SCM scm_i_num_gr_p (SCM, SCM, SCM);
6484 SCM_PRIMITIVE_GENERIC (scm_i_num_gr_p, ">", 0, 2, 1,
6485 (SCM x, SCM y, SCM rest),
6486 "Return @code{#t} if the list of parameters is monotonically\n"
6487 "decreasing.")
6488 #define FUNC_NAME s_scm_i_num_gr_p
6489 {
6490 if (SCM_UNBNDP (x) || SCM_UNBNDP (y))
6491 return SCM_BOOL_T;
6492 while (!scm_is_null (rest))
6493 {
6494 if (scm_is_false (scm_gr_p (x, y)))
6495 return SCM_BOOL_F;
6496 x = y;
6497 y = scm_car (rest);
6498 rest = scm_cdr (rest);
6499 }
6500 return scm_gr_p (x, y);
6501 }
6502 #undef FUNC_NAME
6503 #define FUNC_NAME s_scm_i_num_gr_p
6504 SCM
6505 scm_gr_p (SCM x, SCM y)
6506 {
6507 if (!SCM_NUMBERP (x))
6508 SCM_WTA_DISPATCH_2 (g_scm_i_num_gr_p, x, y, SCM_ARG1, FUNC_NAME);
6509 else if (!SCM_NUMBERP (y))
6510 SCM_WTA_DISPATCH_2 (g_scm_i_num_gr_p, x, y, SCM_ARG2, FUNC_NAME);
6511 else
6512 return scm_less_p (y, x);
6513 }
6514 #undef FUNC_NAME
6515
6516
6517 SCM scm_i_num_leq_p (SCM, SCM, SCM);
6518 SCM_PRIMITIVE_GENERIC (scm_i_num_leq_p, "<=", 0, 2, 1,
6519 (SCM x, SCM y, SCM rest),
6520 "Return @code{#t} if the list of parameters is monotonically\n"
6521 "non-decreasing.")
6522 #define FUNC_NAME s_scm_i_num_leq_p
6523 {
6524 if (SCM_UNBNDP (x) || SCM_UNBNDP (y))
6525 return SCM_BOOL_T;
6526 while (!scm_is_null (rest))
6527 {
6528 if (scm_is_false (scm_leq_p (x, y)))
6529 return SCM_BOOL_F;
6530 x = y;
6531 y = scm_car (rest);
6532 rest = scm_cdr (rest);
6533 }
6534 return scm_leq_p (x, y);
6535 }
6536 #undef FUNC_NAME
6537 #define FUNC_NAME s_scm_i_num_leq_p
6538 SCM
6539 scm_leq_p (SCM x, SCM y)
6540 {
6541 if (!SCM_NUMBERP (x))
6542 SCM_WTA_DISPATCH_2 (g_scm_i_num_leq_p, x, y, SCM_ARG1, FUNC_NAME);
6543 else if (!SCM_NUMBERP (y))
6544 SCM_WTA_DISPATCH_2 (g_scm_i_num_leq_p, x, y, SCM_ARG2, FUNC_NAME);
6545 else if (scm_is_true (scm_nan_p (x)) || scm_is_true (scm_nan_p (y)))
6546 return SCM_BOOL_F;
6547 else
6548 return scm_not (scm_less_p (y, x));
6549 }
6550 #undef FUNC_NAME
6551
6552
6553 SCM scm_i_num_geq_p (SCM, SCM, SCM);
6554 SCM_PRIMITIVE_GENERIC (scm_i_num_geq_p, ">=", 0, 2, 1,
6555 (SCM x, SCM y, SCM rest),
6556 "Return @code{#t} if the list of parameters is monotonically\n"
6557 "non-increasing.")
6558 #define FUNC_NAME s_scm_i_num_geq_p
6559 {
6560 if (SCM_UNBNDP (x) || SCM_UNBNDP (y))
6561 return SCM_BOOL_T;
6562 while (!scm_is_null (rest))
6563 {
6564 if (scm_is_false (scm_geq_p (x, y)))
6565 return SCM_BOOL_F;
6566 x = y;
6567 y = scm_car (rest);
6568 rest = scm_cdr (rest);
6569 }
6570 return scm_geq_p (x, y);
6571 }
6572 #undef FUNC_NAME
6573 #define FUNC_NAME s_scm_i_num_geq_p
6574 SCM
6575 scm_geq_p (SCM x, SCM y)
6576 {
6577 if (!SCM_NUMBERP (x))
6578 SCM_WTA_DISPATCH_2 (g_scm_i_num_geq_p, x, y, SCM_ARG1, FUNC_NAME);
6579 else if (!SCM_NUMBERP (y))
6580 SCM_WTA_DISPATCH_2 (g_scm_i_num_geq_p, x, y, SCM_ARG2, FUNC_NAME);
6581 else if (scm_is_true (scm_nan_p (x)) || scm_is_true (scm_nan_p (y)))
6582 return SCM_BOOL_F;
6583 else
6584 return scm_not (scm_less_p (x, y));
6585 }
6586 #undef FUNC_NAME
6587
6588
6589 SCM_PRIMITIVE_GENERIC (scm_zero_p, "zero?", 1, 0, 0,
6590 (SCM z),
6591 "Return @code{#t} if @var{z} is an exact or inexact number equal to\n"
6592 "zero.")
6593 #define FUNC_NAME s_scm_zero_p
6594 {
6595 if (SCM_I_INUMP (z))
6596 return scm_from_bool (scm_is_eq (z, SCM_INUM0));
6597 else if (SCM_BIGP (z))
6598 return SCM_BOOL_F;
6599 else if (SCM_REALP (z))
6600 return scm_from_bool (SCM_REAL_VALUE (z) == 0.0);
6601 else if (SCM_COMPLEXP (z))
6602 return scm_from_bool (SCM_COMPLEX_REAL (z) == 0.0
6603 && SCM_COMPLEX_IMAG (z) == 0.0);
6604 else if (SCM_FRACTIONP (z))
6605 return SCM_BOOL_F;
6606 else
6607 SCM_WTA_DISPATCH_1 (g_scm_zero_p, z, SCM_ARG1, s_scm_zero_p);
6608 }
6609 #undef FUNC_NAME
6610
6611
6612 SCM_PRIMITIVE_GENERIC (scm_positive_p, "positive?", 1, 0, 0,
6613 (SCM x),
6614 "Return @code{#t} if @var{x} is an exact or inexact number greater than\n"
6615 "zero.")
6616 #define FUNC_NAME s_scm_positive_p
6617 {
6618 if (SCM_I_INUMP (x))
6619 return scm_from_bool (SCM_I_INUM (x) > 0);
6620 else if (SCM_BIGP (x))
6621 {
6622 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
6623 scm_remember_upto_here_1 (x);
6624 return scm_from_bool (sgn > 0);
6625 }
6626 else if (SCM_REALP (x))
6627 return scm_from_bool(SCM_REAL_VALUE (x) > 0.0);
6628 else if (SCM_FRACTIONP (x))
6629 return scm_positive_p (SCM_FRACTION_NUMERATOR (x));
6630 else
6631 SCM_WTA_DISPATCH_1 (g_scm_positive_p, x, SCM_ARG1, s_scm_positive_p);
6632 }
6633 #undef FUNC_NAME
6634
6635
6636 SCM_PRIMITIVE_GENERIC (scm_negative_p, "negative?", 1, 0, 0,
6637 (SCM x),
6638 "Return @code{#t} if @var{x} is an exact or inexact number less than\n"
6639 "zero.")
6640 #define FUNC_NAME s_scm_negative_p
6641 {
6642 if (SCM_I_INUMP (x))
6643 return scm_from_bool (SCM_I_INUM (x) < 0);
6644 else if (SCM_BIGP (x))
6645 {
6646 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
6647 scm_remember_upto_here_1 (x);
6648 return scm_from_bool (sgn < 0);
6649 }
6650 else if (SCM_REALP (x))
6651 return scm_from_bool(SCM_REAL_VALUE (x) < 0.0);
6652 else if (SCM_FRACTIONP (x))
6653 return scm_negative_p (SCM_FRACTION_NUMERATOR (x));
6654 else
6655 SCM_WTA_DISPATCH_1 (g_scm_negative_p, x, SCM_ARG1, s_scm_negative_p);
6656 }
6657 #undef FUNC_NAME
6658
6659
6660 /* scm_min and scm_max return an inexact when either argument is inexact, as
6661 required by r5rs. On that basis, for exact/inexact combinations the
6662 exact is converted to inexact to compare and possibly return. This is
6663 unlike scm_less_p above which takes some trouble to preserve all bits in
6664 its test, such trouble is not required for min and max. */
6665
6666 SCM_PRIMITIVE_GENERIC (scm_i_max, "max", 0, 2, 1,
6667 (SCM x, SCM y, SCM rest),
6668 "Return the maximum of all parameter values.")
6669 #define FUNC_NAME s_scm_i_max
6670 {
6671 while (!scm_is_null (rest))
6672 { x = scm_max (x, y);
6673 y = scm_car (rest);
6674 rest = scm_cdr (rest);
6675 }
6676 return scm_max (x, y);
6677 }
6678 #undef FUNC_NAME
6679
6680 #define s_max s_scm_i_max
6681 #define g_max g_scm_i_max
6682
6683 SCM
6684 scm_max (SCM x, SCM y)
6685 {
6686 if (SCM_UNBNDP (y))
6687 {
6688 if (SCM_UNBNDP (x))
6689 SCM_WTA_DISPATCH_0 (g_max, s_max);
6690 else if (SCM_I_INUMP(x) || SCM_BIGP(x) || SCM_REALP(x) || SCM_FRACTIONP(x))
6691 return x;
6692 else
6693 SCM_WTA_DISPATCH_1 (g_max, x, SCM_ARG1, s_max);
6694 }
6695
6696 if (SCM_I_INUMP (x))
6697 {
6698 scm_t_inum xx = SCM_I_INUM (x);
6699 if (SCM_I_INUMP (y))
6700 {
6701 scm_t_inum yy = SCM_I_INUM (y);
6702 return (xx < yy) ? y : x;
6703 }
6704 else if (SCM_BIGP (y))
6705 {
6706 int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
6707 scm_remember_upto_here_1 (y);
6708 return (sgn < 0) ? x : y;
6709 }
6710 else if (SCM_REALP (y))
6711 {
6712 double xxd = xx;
6713 double yyd = SCM_REAL_VALUE (y);
6714
6715 if (xxd > yyd)
6716 return scm_from_double (xxd);
6717 /* If y is a NaN, then "==" is false and we return the NaN */
6718 else if (SCM_LIKELY (!(xxd == yyd)))
6719 return y;
6720 /* Handle signed zeroes properly */
6721 else if (xx == 0)
6722 return flo0;
6723 else
6724 return y;
6725 }
6726 else if (SCM_FRACTIONP (y))
6727 {
6728 use_less:
6729 return (scm_is_false (scm_less_p (x, y)) ? x : y);
6730 }
6731 else
6732 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
6733 }
6734 else if (SCM_BIGP (x))
6735 {
6736 if (SCM_I_INUMP (y))
6737 {
6738 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
6739 scm_remember_upto_here_1 (x);
6740 return (sgn < 0) ? y : x;
6741 }
6742 else if (SCM_BIGP (y))
6743 {
6744 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
6745 scm_remember_upto_here_2 (x, y);
6746 return (cmp > 0) ? x : y;
6747 }
6748 else if (SCM_REALP (y))
6749 {
6750 /* if y==NaN then xx>yy is false, so we return the NaN y */
6751 double xx, yy;
6752 big_real:
6753 xx = scm_i_big2dbl (x);
6754 yy = SCM_REAL_VALUE (y);
6755 return (xx > yy ? scm_from_double (xx) : y);
6756 }
6757 else if (SCM_FRACTIONP (y))
6758 {
6759 goto use_less;
6760 }
6761 else
6762 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
6763 }
6764 else if (SCM_REALP (x))
6765 {
6766 if (SCM_I_INUMP (y))
6767 {
6768 scm_t_inum yy = SCM_I_INUM (y);
6769 double xxd = SCM_REAL_VALUE (x);
6770 double yyd = yy;
6771
6772 if (yyd > xxd)
6773 return scm_from_double (yyd);
6774 /* If x is a NaN, then "==" is false and we return the NaN */
6775 else if (SCM_LIKELY (!(xxd == yyd)))
6776 return x;
6777 /* Handle signed zeroes properly */
6778 else if (yy == 0)
6779 return flo0;
6780 else
6781 return x;
6782 }
6783 else if (SCM_BIGP (y))
6784 {
6785 SCM_SWAP (x, y);
6786 goto big_real;
6787 }
6788 else if (SCM_REALP (y))
6789 {
6790 double xx = SCM_REAL_VALUE (x);
6791 double yy = SCM_REAL_VALUE (y);
6792
6793 /* For purposes of max: +inf.0 > nan > everything else, per R6RS */
6794 if (xx > yy)
6795 return x;
6796 else if (SCM_LIKELY (xx < yy))
6797 return y;
6798 /* If neither (xx > yy) nor (xx < yy), then
6799 either they're equal or one is a NaN */
6800 else if (SCM_UNLIKELY (isnan (xx)))
6801 return DOUBLE_IS_POSITIVE_INFINITY (yy) ? y : x;
6802 else if (SCM_UNLIKELY (isnan (yy)))
6803 return DOUBLE_IS_POSITIVE_INFINITY (xx) ? x : y;
6804 /* xx == yy, but handle signed zeroes properly */
6805 else if (double_is_non_negative_zero (yy))
6806 return y;
6807 else
6808 return x;
6809 }
6810 else if (SCM_FRACTIONP (y))
6811 {
6812 double yy = scm_i_fraction2double (y);
6813 double xx = SCM_REAL_VALUE (x);
6814 return (xx < yy) ? scm_from_double (yy) : x;
6815 }
6816 else
6817 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
6818 }
6819 else if (SCM_FRACTIONP (x))
6820 {
6821 if (SCM_I_INUMP (y))
6822 {
6823 goto use_less;
6824 }
6825 else if (SCM_BIGP (y))
6826 {
6827 goto use_less;
6828 }
6829 else if (SCM_REALP (y))
6830 {
6831 double xx = scm_i_fraction2double (x);
6832 /* if y==NaN then ">" is false, so we return the NaN y */
6833 return (xx > SCM_REAL_VALUE (y)) ? scm_from_double (xx) : y;
6834 }
6835 else if (SCM_FRACTIONP (y))
6836 {
6837 goto use_less;
6838 }
6839 else
6840 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
6841 }
6842 else
6843 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARG1, s_max);
6844 }
6845
6846
6847 SCM_PRIMITIVE_GENERIC (scm_i_min, "min", 0, 2, 1,
6848 (SCM x, SCM y, SCM rest),
6849 "Return the minimum of all parameter values.")
6850 #define FUNC_NAME s_scm_i_min
6851 {
6852 while (!scm_is_null (rest))
6853 { x = scm_min (x, y);
6854 y = scm_car (rest);
6855 rest = scm_cdr (rest);
6856 }
6857 return scm_min (x, y);
6858 }
6859 #undef FUNC_NAME
6860
6861 #define s_min s_scm_i_min
6862 #define g_min g_scm_i_min
6863
6864 SCM
6865 scm_min (SCM x, SCM y)
6866 {
6867 if (SCM_UNBNDP (y))
6868 {
6869 if (SCM_UNBNDP (x))
6870 SCM_WTA_DISPATCH_0 (g_min, s_min);
6871 else if (SCM_I_INUMP(x) || SCM_BIGP(x) || SCM_REALP(x) || SCM_FRACTIONP(x))
6872 return x;
6873 else
6874 SCM_WTA_DISPATCH_1 (g_min, x, SCM_ARG1, s_min);
6875 }
6876
6877 if (SCM_I_INUMP (x))
6878 {
6879 scm_t_inum xx = SCM_I_INUM (x);
6880 if (SCM_I_INUMP (y))
6881 {
6882 scm_t_inum yy = SCM_I_INUM (y);
6883 return (xx < yy) ? x : y;
6884 }
6885 else if (SCM_BIGP (y))
6886 {
6887 int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
6888 scm_remember_upto_here_1 (y);
6889 return (sgn < 0) ? y : x;
6890 }
6891 else if (SCM_REALP (y))
6892 {
6893 double z = xx;
6894 /* if y==NaN then "<" is false and we return NaN */
6895 return (z < SCM_REAL_VALUE (y)) ? scm_from_double (z) : y;
6896 }
6897 else if (SCM_FRACTIONP (y))
6898 {
6899 use_less:
6900 return (scm_is_false (scm_less_p (x, y)) ? y : x);
6901 }
6902 else
6903 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
6904 }
6905 else if (SCM_BIGP (x))
6906 {
6907 if (SCM_I_INUMP (y))
6908 {
6909 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
6910 scm_remember_upto_here_1 (x);
6911 return (sgn < 0) ? x : y;
6912 }
6913 else if (SCM_BIGP (y))
6914 {
6915 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
6916 scm_remember_upto_here_2 (x, y);
6917 return (cmp > 0) ? y : x;
6918 }
6919 else if (SCM_REALP (y))
6920 {
6921 /* if y==NaN then xx<yy is false, so we return the NaN y */
6922 double xx, yy;
6923 big_real:
6924 xx = scm_i_big2dbl (x);
6925 yy = SCM_REAL_VALUE (y);
6926 return (xx < yy ? scm_from_double (xx) : y);
6927 }
6928 else if (SCM_FRACTIONP (y))
6929 {
6930 goto use_less;
6931 }
6932 else
6933 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
6934 }
6935 else if (SCM_REALP (x))
6936 {
6937 if (SCM_I_INUMP (y))
6938 {
6939 double z = SCM_I_INUM (y);
6940 /* if x==NaN then "<" is false and we return NaN */
6941 return (z < SCM_REAL_VALUE (x)) ? scm_from_double (z) : x;
6942 }
6943 else if (SCM_BIGP (y))
6944 {
6945 SCM_SWAP (x, y);
6946 goto big_real;
6947 }
6948 else if (SCM_REALP (y))
6949 {
6950 double xx = SCM_REAL_VALUE (x);
6951 double yy = SCM_REAL_VALUE (y);
6952
6953 /* For purposes of min: -inf.0 < nan < everything else, per R6RS */
6954 if (xx < yy)
6955 return x;
6956 else if (SCM_LIKELY (xx > yy))
6957 return y;
6958 /* If neither (xx < yy) nor (xx > yy), then
6959 either they're equal or one is a NaN */
6960 else if (SCM_UNLIKELY (isnan (xx)))
6961 return DOUBLE_IS_NEGATIVE_INFINITY (yy) ? y : x;
6962 else if (SCM_UNLIKELY (isnan (yy)))
6963 return DOUBLE_IS_NEGATIVE_INFINITY (xx) ? x : y;
6964 /* xx == yy, but handle signed zeroes properly */
6965 else if (double_is_non_negative_zero (xx))
6966 return y;
6967 else
6968 return x;
6969 }
6970 else if (SCM_FRACTIONP (y))
6971 {
6972 double yy = scm_i_fraction2double (y);
6973 double xx = SCM_REAL_VALUE (x);
6974 return (yy < xx) ? scm_from_double (yy) : x;
6975 }
6976 else
6977 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
6978 }
6979 else if (SCM_FRACTIONP (x))
6980 {
6981 if (SCM_I_INUMP (y))
6982 {
6983 goto use_less;
6984 }
6985 else if (SCM_BIGP (y))
6986 {
6987 goto use_less;
6988 }
6989 else if (SCM_REALP (y))
6990 {
6991 double xx = scm_i_fraction2double (x);
6992 /* if y==NaN then "<" is false, so we return the NaN y */
6993 return (xx < SCM_REAL_VALUE (y)) ? scm_from_double (xx) : y;
6994 }
6995 else if (SCM_FRACTIONP (y))
6996 {
6997 goto use_less;
6998 }
6999 else
7000 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
7001 }
7002 else
7003 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARG1, s_min);
7004 }
7005
7006
7007 SCM_PRIMITIVE_GENERIC (scm_i_sum, "+", 0, 2, 1,
7008 (SCM x, SCM y, SCM rest),
7009 "Return the sum of all parameter values. Return 0 if called without\n"
7010 "any parameters." )
7011 #define FUNC_NAME s_scm_i_sum
7012 {
7013 while (!scm_is_null (rest))
7014 { x = scm_sum (x, y);
7015 y = scm_car (rest);
7016 rest = scm_cdr (rest);
7017 }
7018 return scm_sum (x, y);
7019 }
7020 #undef FUNC_NAME
7021
7022 #define s_sum s_scm_i_sum
7023 #define g_sum g_scm_i_sum
7024
7025 SCM
7026 scm_sum (SCM x, SCM y)
7027 {
7028 if (SCM_UNLIKELY (SCM_UNBNDP (y)))
7029 {
7030 if (SCM_NUMBERP (x)) return x;
7031 if (SCM_UNBNDP (x)) return SCM_INUM0;
7032 SCM_WTA_DISPATCH_1 (g_sum, x, SCM_ARG1, s_sum);
7033 }
7034
7035 if (SCM_LIKELY (SCM_I_INUMP (x)))
7036 {
7037 if (SCM_LIKELY (SCM_I_INUMP (y)))
7038 {
7039 scm_t_inum xx = SCM_I_INUM (x);
7040 scm_t_inum yy = SCM_I_INUM (y);
7041 scm_t_inum z = xx + yy;
7042 return SCM_FIXABLE (z) ? SCM_I_MAKINUM (z) : scm_i_inum2big (z);
7043 }
7044 else if (SCM_BIGP (y))
7045 {
7046 SCM_SWAP (x, y);
7047 goto add_big_inum;
7048 }
7049 else if (SCM_REALP (y))
7050 {
7051 scm_t_inum xx = SCM_I_INUM (x);
7052 return scm_from_double (xx + SCM_REAL_VALUE (y));
7053 }
7054 else if (SCM_COMPLEXP (y))
7055 {
7056 scm_t_inum xx = SCM_I_INUM (x);
7057 return scm_c_make_rectangular (xx + SCM_COMPLEX_REAL (y),
7058 SCM_COMPLEX_IMAG (y));
7059 }
7060 else if (SCM_FRACTIONP (y))
7061 return scm_i_make_ratio (scm_sum (SCM_FRACTION_NUMERATOR (y),
7062 scm_product (x, SCM_FRACTION_DENOMINATOR (y))),
7063 SCM_FRACTION_DENOMINATOR (y));
7064 else
7065 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
7066 } else if (SCM_BIGP (x))
7067 {
7068 if (SCM_I_INUMP (y))
7069 {
7070 scm_t_inum inum;
7071 int bigsgn;
7072 add_big_inum:
7073 inum = SCM_I_INUM (y);
7074 if (inum == 0)
7075 return x;
7076 bigsgn = mpz_sgn (SCM_I_BIG_MPZ (x));
7077 if (inum < 0)
7078 {
7079 SCM result = scm_i_mkbig ();
7080 mpz_sub_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), - inum);
7081 scm_remember_upto_here_1 (x);
7082 /* we know the result will have to be a bignum */
7083 if (bigsgn == -1)
7084 return result;
7085 return scm_i_normbig (result);
7086 }
7087 else
7088 {
7089 SCM result = scm_i_mkbig ();
7090 mpz_add_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), inum);
7091 scm_remember_upto_here_1 (x);
7092 /* we know the result will have to be a bignum */
7093 if (bigsgn == 1)
7094 return result;
7095 return scm_i_normbig (result);
7096 }
7097 }
7098 else if (SCM_BIGP (y))
7099 {
7100 SCM result = scm_i_mkbig ();
7101 int sgn_x = mpz_sgn (SCM_I_BIG_MPZ (x));
7102 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
7103 mpz_add (SCM_I_BIG_MPZ (result),
7104 SCM_I_BIG_MPZ (x),
7105 SCM_I_BIG_MPZ (y));
7106 scm_remember_upto_here_2 (x, y);
7107 /* we know the result will have to be a bignum */
7108 if (sgn_x == sgn_y)
7109 return result;
7110 return scm_i_normbig (result);
7111 }
7112 else if (SCM_REALP (y))
7113 {
7114 double result = mpz_get_d (SCM_I_BIG_MPZ (x)) + SCM_REAL_VALUE (y);
7115 scm_remember_upto_here_1 (x);
7116 return scm_from_double (result);
7117 }
7118 else if (SCM_COMPLEXP (y))
7119 {
7120 double real_part = (mpz_get_d (SCM_I_BIG_MPZ (x))
7121 + SCM_COMPLEX_REAL (y));
7122 scm_remember_upto_here_1 (x);
7123 return scm_c_make_rectangular (real_part, SCM_COMPLEX_IMAG (y));
7124 }
7125 else if (SCM_FRACTIONP (y))
7126 return scm_i_make_ratio (scm_sum (SCM_FRACTION_NUMERATOR (y),
7127 scm_product (x, SCM_FRACTION_DENOMINATOR (y))),
7128 SCM_FRACTION_DENOMINATOR (y));
7129 else
7130 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
7131 }
7132 else if (SCM_REALP (x))
7133 {
7134 if (SCM_I_INUMP (y))
7135 return scm_from_double (SCM_REAL_VALUE (x) + SCM_I_INUM (y));
7136 else if (SCM_BIGP (y))
7137 {
7138 double result = mpz_get_d (SCM_I_BIG_MPZ (y)) + SCM_REAL_VALUE (x);
7139 scm_remember_upto_here_1 (y);
7140 return scm_from_double (result);
7141 }
7142 else if (SCM_REALP (y))
7143 return scm_from_double (SCM_REAL_VALUE (x) + SCM_REAL_VALUE (y));
7144 else if (SCM_COMPLEXP (y))
7145 return scm_c_make_rectangular (SCM_REAL_VALUE (x) + SCM_COMPLEX_REAL (y),
7146 SCM_COMPLEX_IMAG (y));
7147 else if (SCM_FRACTIONP (y))
7148 return scm_from_double (SCM_REAL_VALUE (x) + scm_i_fraction2double (y));
7149 else
7150 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
7151 }
7152 else if (SCM_COMPLEXP (x))
7153 {
7154 if (SCM_I_INUMP (y))
7155 return scm_c_make_rectangular (SCM_COMPLEX_REAL (x) + SCM_I_INUM (y),
7156 SCM_COMPLEX_IMAG (x));
7157 else if (SCM_BIGP (y))
7158 {
7159 double real_part = (mpz_get_d (SCM_I_BIG_MPZ (y))
7160 + SCM_COMPLEX_REAL (x));
7161 scm_remember_upto_here_1 (y);
7162 return scm_c_make_rectangular (real_part, SCM_COMPLEX_IMAG (x));
7163 }
7164 else if (SCM_REALP (y))
7165 return scm_c_make_rectangular (SCM_COMPLEX_REAL (x) + SCM_REAL_VALUE (y),
7166 SCM_COMPLEX_IMAG (x));
7167 else if (SCM_COMPLEXP (y))
7168 return scm_c_make_rectangular (SCM_COMPLEX_REAL (x) + SCM_COMPLEX_REAL (y),
7169 SCM_COMPLEX_IMAG (x) + SCM_COMPLEX_IMAG (y));
7170 else if (SCM_FRACTIONP (y))
7171 return scm_c_make_rectangular (SCM_COMPLEX_REAL (x) + scm_i_fraction2double (y),
7172 SCM_COMPLEX_IMAG (x));
7173 else
7174 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
7175 }
7176 else if (SCM_FRACTIONP (x))
7177 {
7178 if (SCM_I_INUMP (y))
7179 return scm_i_make_ratio (scm_sum (SCM_FRACTION_NUMERATOR (x),
7180 scm_product (y, SCM_FRACTION_DENOMINATOR (x))),
7181 SCM_FRACTION_DENOMINATOR (x));
7182 else if (SCM_BIGP (y))
7183 return scm_i_make_ratio (scm_sum (SCM_FRACTION_NUMERATOR (x),
7184 scm_product (y, SCM_FRACTION_DENOMINATOR (x))),
7185 SCM_FRACTION_DENOMINATOR (x));
7186 else if (SCM_REALP (y))
7187 return scm_from_double (SCM_REAL_VALUE (y) + scm_i_fraction2double (x));
7188 else if (SCM_COMPLEXP (y))
7189 return scm_c_make_rectangular (SCM_COMPLEX_REAL (y) + scm_i_fraction2double (x),
7190 SCM_COMPLEX_IMAG (y));
7191 else if (SCM_FRACTIONP (y))
7192 /* a/b + c/d = (ad + bc) / bd */
7193 return scm_i_make_ratio (scm_sum (scm_product (SCM_FRACTION_NUMERATOR (x), SCM_FRACTION_DENOMINATOR (y)),
7194 scm_product (SCM_FRACTION_NUMERATOR (y), SCM_FRACTION_DENOMINATOR (x))),
7195 scm_product (SCM_FRACTION_DENOMINATOR (x), SCM_FRACTION_DENOMINATOR (y)));
7196 else
7197 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
7198 }
7199 else
7200 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARG1, s_sum);
7201 }
7202
7203
7204 SCM_DEFINE (scm_oneplus, "1+", 1, 0, 0,
7205 (SCM x),
7206 "Return @math{@var{x}+1}.")
7207 #define FUNC_NAME s_scm_oneplus
7208 {
7209 return scm_sum (x, SCM_INUM1);
7210 }
7211 #undef FUNC_NAME
7212
7213
7214 SCM_PRIMITIVE_GENERIC (scm_i_difference, "-", 0, 2, 1,
7215 (SCM x, SCM y, SCM rest),
7216 "If called with one argument @var{z1}, -@var{z1} returned. Otherwise\n"
7217 "the sum of all but the first argument are subtracted from the first\n"
7218 "argument.")
7219 #define FUNC_NAME s_scm_i_difference
7220 {
7221 while (!scm_is_null (rest))
7222 { x = scm_difference (x, y);
7223 y = scm_car (rest);
7224 rest = scm_cdr (rest);
7225 }
7226 return scm_difference (x, y);
7227 }
7228 #undef FUNC_NAME
7229
7230 #define s_difference s_scm_i_difference
7231 #define g_difference g_scm_i_difference
7232
7233 SCM
7234 scm_difference (SCM x, SCM y)
7235 #define FUNC_NAME s_difference
7236 {
7237 if (SCM_UNLIKELY (SCM_UNBNDP (y)))
7238 {
7239 if (SCM_UNBNDP (x))
7240 SCM_WTA_DISPATCH_0 (g_difference, s_difference);
7241 else
7242 if (SCM_I_INUMP (x))
7243 {
7244 scm_t_inum xx = -SCM_I_INUM (x);
7245 if (SCM_FIXABLE (xx))
7246 return SCM_I_MAKINUM (xx);
7247 else
7248 return scm_i_inum2big (xx);
7249 }
7250 else if (SCM_BIGP (x))
7251 /* Must scm_i_normbig here because -SCM_MOST_NEGATIVE_FIXNUM is a
7252 bignum, but negating that gives a fixnum. */
7253 return scm_i_normbig (scm_i_clonebig (x, 0));
7254 else if (SCM_REALP (x))
7255 return scm_from_double (-SCM_REAL_VALUE (x));
7256 else if (SCM_COMPLEXP (x))
7257 return scm_c_make_rectangular (-SCM_COMPLEX_REAL (x),
7258 -SCM_COMPLEX_IMAG (x));
7259 else if (SCM_FRACTIONP (x))
7260 return scm_i_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x), SCM_UNDEFINED),
7261 SCM_FRACTION_DENOMINATOR (x));
7262 else
7263 SCM_WTA_DISPATCH_1 (g_difference, x, SCM_ARG1, s_difference);
7264 }
7265
7266 if (SCM_LIKELY (SCM_I_INUMP (x)))
7267 {
7268 if (SCM_LIKELY (SCM_I_INUMP (y)))
7269 {
7270 scm_t_inum xx = SCM_I_INUM (x);
7271 scm_t_inum yy = SCM_I_INUM (y);
7272 scm_t_inum z = xx - yy;
7273 if (SCM_FIXABLE (z))
7274 return SCM_I_MAKINUM (z);
7275 else
7276 return scm_i_inum2big (z);
7277 }
7278 else if (SCM_BIGP (y))
7279 {
7280 /* inum-x - big-y */
7281 scm_t_inum xx = SCM_I_INUM (x);
7282
7283 if (xx == 0)
7284 {
7285 /* Must scm_i_normbig here because -SCM_MOST_NEGATIVE_FIXNUM is a
7286 bignum, but negating that gives a fixnum. */
7287 return scm_i_normbig (scm_i_clonebig (y, 0));
7288 }
7289 else
7290 {
7291 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
7292 SCM result = scm_i_mkbig ();
7293
7294 if (xx >= 0)
7295 mpz_ui_sub (SCM_I_BIG_MPZ (result), xx, SCM_I_BIG_MPZ (y));
7296 else
7297 {
7298 /* x - y == -(y + -x) */
7299 mpz_add_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (y), -xx);
7300 mpz_neg (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result));
7301 }
7302 scm_remember_upto_here_1 (y);
7303
7304 if ((xx < 0 && (sgn_y > 0)) || ((xx > 0) && sgn_y < 0))
7305 /* we know the result will have to be a bignum */
7306 return result;
7307 else
7308 return scm_i_normbig (result);
7309 }
7310 }
7311 else if (SCM_REALP (y))
7312 {
7313 scm_t_inum xx = SCM_I_INUM (x);
7314
7315 /*
7316 * We need to handle x == exact 0
7317 * specially because R6RS states that:
7318 * (- 0.0) ==> -0.0 and
7319 * (- 0.0 0.0) ==> 0.0
7320 * and the scheme compiler changes
7321 * (- 0.0) into (- 0 0.0)
7322 * So we need to treat (- 0 0.0) like (- 0.0).
7323 * At the C level, (-x) is different than (0.0 - x).
7324 * (0.0 - 0.0) ==> 0.0, but (- 0.0) ==> -0.0.
7325 */
7326 if (xx == 0)
7327 return scm_from_double (- SCM_REAL_VALUE (y));
7328 else
7329 return scm_from_double (xx - SCM_REAL_VALUE (y));
7330 }
7331 else if (SCM_COMPLEXP (y))
7332 {
7333 scm_t_inum xx = SCM_I_INUM (x);
7334
7335 /* We need to handle x == exact 0 specially.
7336 See the comment above (for SCM_REALP (y)) */
7337 if (xx == 0)
7338 return scm_c_make_rectangular (- SCM_COMPLEX_REAL (y),
7339 - SCM_COMPLEX_IMAG (y));
7340 else
7341 return scm_c_make_rectangular (xx - SCM_COMPLEX_REAL (y),
7342 - SCM_COMPLEX_IMAG (y));
7343 }
7344 else if (SCM_FRACTIONP (y))
7345 /* a - b/c = (ac - b) / c */
7346 return scm_i_make_ratio (scm_difference (scm_product (x, SCM_FRACTION_DENOMINATOR (y)),
7347 SCM_FRACTION_NUMERATOR (y)),
7348 SCM_FRACTION_DENOMINATOR (y));
7349 else
7350 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
7351 }
7352 else if (SCM_BIGP (x))
7353 {
7354 if (SCM_I_INUMP (y))
7355 {
7356 /* big-x - inum-y */
7357 scm_t_inum yy = SCM_I_INUM (y);
7358 int sgn_x = mpz_sgn (SCM_I_BIG_MPZ (x));
7359
7360 scm_remember_upto_here_1 (x);
7361 if (sgn_x == 0)
7362 return (SCM_FIXABLE (-yy) ?
7363 SCM_I_MAKINUM (-yy) : scm_from_inum (-yy));
7364 else
7365 {
7366 SCM result = scm_i_mkbig ();
7367
7368 if (yy >= 0)
7369 mpz_sub_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), yy);
7370 else
7371 mpz_add_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), -yy);
7372 scm_remember_upto_here_1 (x);
7373
7374 if ((sgn_x < 0 && (yy > 0)) || ((sgn_x > 0) && yy < 0))
7375 /* we know the result will have to be a bignum */
7376 return result;
7377 else
7378 return scm_i_normbig (result);
7379 }
7380 }
7381 else if (SCM_BIGP (y))
7382 {
7383 int sgn_x = mpz_sgn (SCM_I_BIG_MPZ (x));
7384 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
7385 SCM result = scm_i_mkbig ();
7386 mpz_sub (SCM_I_BIG_MPZ (result),
7387 SCM_I_BIG_MPZ (x),
7388 SCM_I_BIG_MPZ (y));
7389 scm_remember_upto_here_2 (x, y);
7390 /* we know the result will have to be a bignum */
7391 if ((sgn_x == 1) && (sgn_y == -1))
7392 return result;
7393 if ((sgn_x == -1) && (sgn_y == 1))
7394 return result;
7395 return scm_i_normbig (result);
7396 }
7397 else if (SCM_REALP (y))
7398 {
7399 double result = mpz_get_d (SCM_I_BIG_MPZ (x)) - SCM_REAL_VALUE (y);
7400 scm_remember_upto_here_1 (x);
7401 return scm_from_double (result);
7402 }
7403 else if (SCM_COMPLEXP (y))
7404 {
7405 double real_part = (mpz_get_d (SCM_I_BIG_MPZ (x))
7406 - SCM_COMPLEX_REAL (y));
7407 scm_remember_upto_here_1 (x);
7408 return scm_c_make_rectangular (real_part, - SCM_COMPLEX_IMAG (y));
7409 }
7410 else if (SCM_FRACTIONP (y))
7411 return scm_i_make_ratio (scm_difference (scm_product (x, SCM_FRACTION_DENOMINATOR (y)),
7412 SCM_FRACTION_NUMERATOR (y)),
7413 SCM_FRACTION_DENOMINATOR (y));
7414 else SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
7415 }
7416 else if (SCM_REALP (x))
7417 {
7418 if (SCM_I_INUMP (y))
7419 return scm_from_double (SCM_REAL_VALUE (x) - SCM_I_INUM (y));
7420 else if (SCM_BIGP (y))
7421 {
7422 double result = SCM_REAL_VALUE (x) - mpz_get_d (SCM_I_BIG_MPZ (y));
7423 scm_remember_upto_here_1 (x);
7424 return scm_from_double (result);
7425 }
7426 else if (SCM_REALP (y))
7427 return scm_from_double (SCM_REAL_VALUE (x) - SCM_REAL_VALUE (y));
7428 else if (SCM_COMPLEXP (y))
7429 return scm_c_make_rectangular (SCM_REAL_VALUE (x) - SCM_COMPLEX_REAL (y),
7430 -SCM_COMPLEX_IMAG (y));
7431 else if (SCM_FRACTIONP (y))
7432 return scm_from_double (SCM_REAL_VALUE (x) - scm_i_fraction2double (y));
7433 else
7434 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
7435 }
7436 else if (SCM_COMPLEXP (x))
7437 {
7438 if (SCM_I_INUMP (y))
7439 return scm_c_make_rectangular (SCM_COMPLEX_REAL (x) - SCM_I_INUM (y),
7440 SCM_COMPLEX_IMAG (x));
7441 else if (SCM_BIGP (y))
7442 {
7443 double real_part = (SCM_COMPLEX_REAL (x)
7444 - mpz_get_d (SCM_I_BIG_MPZ (y)));
7445 scm_remember_upto_here_1 (x);
7446 return scm_c_make_rectangular (real_part, SCM_COMPLEX_IMAG (y));
7447 }
7448 else if (SCM_REALP (y))
7449 return scm_c_make_rectangular (SCM_COMPLEX_REAL (x) - SCM_REAL_VALUE (y),
7450 SCM_COMPLEX_IMAG (x));
7451 else if (SCM_COMPLEXP (y))
7452 return scm_c_make_rectangular (SCM_COMPLEX_REAL (x) - SCM_COMPLEX_REAL (y),
7453 SCM_COMPLEX_IMAG (x) - SCM_COMPLEX_IMAG (y));
7454 else if (SCM_FRACTIONP (y))
7455 return scm_c_make_rectangular (SCM_COMPLEX_REAL (x) - scm_i_fraction2double (y),
7456 SCM_COMPLEX_IMAG (x));
7457 else
7458 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
7459 }
7460 else if (SCM_FRACTIONP (x))
7461 {
7462 if (SCM_I_INUMP (y))
7463 /* a/b - c = (a - cb) / b */
7464 return scm_i_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x),
7465 scm_product(y, SCM_FRACTION_DENOMINATOR (x))),
7466 SCM_FRACTION_DENOMINATOR (x));
7467 else if (SCM_BIGP (y))
7468 return scm_i_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x),
7469 scm_product(y, SCM_FRACTION_DENOMINATOR (x))),
7470 SCM_FRACTION_DENOMINATOR (x));
7471 else if (SCM_REALP (y))
7472 return scm_from_double (scm_i_fraction2double (x) - SCM_REAL_VALUE (y));
7473 else if (SCM_COMPLEXP (y))
7474 return scm_c_make_rectangular (scm_i_fraction2double (x) - SCM_COMPLEX_REAL (y),
7475 -SCM_COMPLEX_IMAG (y));
7476 else if (SCM_FRACTIONP (y))
7477 /* a/b - c/d = (ad - bc) / bd */
7478 return scm_i_make_ratio (scm_difference (scm_product (SCM_FRACTION_NUMERATOR (x), SCM_FRACTION_DENOMINATOR (y)),
7479 scm_product (SCM_FRACTION_NUMERATOR (y), SCM_FRACTION_DENOMINATOR (x))),
7480 scm_product (SCM_FRACTION_DENOMINATOR (x), SCM_FRACTION_DENOMINATOR (y)));
7481 else
7482 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
7483 }
7484 else
7485 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARG1, s_difference);
7486 }
7487 #undef FUNC_NAME
7488
7489
7490 SCM_DEFINE (scm_oneminus, "1-", 1, 0, 0,
7491 (SCM x),
7492 "Return @math{@var{x}-1}.")
7493 #define FUNC_NAME s_scm_oneminus
7494 {
7495 return scm_difference (x, SCM_INUM1);
7496 }
7497 #undef FUNC_NAME
7498
7499
7500 SCM_PRIMITIVE_GENERIC (scm_i_product, "*", 0, 2, 1,
7501 (SCM x, SCM y, SCM rest),
7502 "Return the product of all arguments. If called without arguments,\n"
7503 "1 is returned.")
7504 #define FUNC_NAME s_scm_i_product
7505 {
7506 while (!scm_is_null (rest))
7507 { x = scm_product (x, y);
7508 y = scm_car (rest);
7509 rest = scm_cdr (rest);
7510 }
7511 return scm_product (x, y);
7512 }
7513 #undef FUNC_NAME
7514
7515 #define s_product s_scm_i_product
7516 #define g_product g_scm_i_product
7517
7518 SCM
7519 scm_product (SCM x, SCM y)
7520 {
7521 if (SCM_UNLIKELY (SCM_UNBNDP (y)))
7522 {
7523 if (SCM_UNBNDP (x))
7524 return SCM_I_MAKINUM (1L);
7525 else if (SCM_NUMBERP (x))
7526 return x;
7527 else
7528 SCM_WTA_DISPATCH_1 (g_product, x, SCM_ARG1, s_product);
7529 }
7530
7531 if (SCM_LIKELY (SCM_I_INUMP (x)))
7532 {
7533 scm_t_inum xx;
7534
7535 xinum:
7536 xx = SCM_I_INUM (x);
7537
7538 switch (xx)
7539 {
7540 case 1:
7541 /* exact1 is the universal multiplicative identity */
7542 return y;
7543 break;
7544 case 0:
7545 /* exact0 times a fixnum is exact0: optimize this case */
7546 if (SCM_LIKELY (SCM_I_INUMP (y)))
7547 return SCM_INUM0;
7548 /* if the other argument is inexact, the result is inexact,
7549 and we must do the multiplication in order to handle
7550 infinities and NaNs properly. */
7551 else if (SCM_REALP (y))
7552 return scm_from_double (0.0 * SCM_REAL_VALUE (y));
7553 else if (SCM_COMPLEXP (y))
7554 return scm_c_make_rectangular (0.0 * SCM_COMPLEX_REAL (y),
7555 0.0 * SCM_COMPLEX_IMAG (y));
7556 /* we've already handled inexact numbers,
7557 so y must be exact, and we return exact0 */
7558 else if (SCM_NUMP (y))
7559 return SCM_INUM0;
7560 else
7561 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
7562 break;
7563 case -1:
7564 /*
7565 * This case is important for more than just optimization.
7566 * It handles the case of negating
7567 * (+ 1 most-positive-fixnum) aka (- most-negative-fixnum),
7568 * which is a bignum that must be changed back into a fixnum.
7569 * Failure to do so will cause the following to return #f:
7570 * (= most-negative-fixnum (* -1 (- most-negative-fixnum)))
7571 */
7572 return scm_difference(y, SCM_UNDEFINED);
7573 break;
7574 }
7575
7576 if (SCM_LIKELY (SCM_I_INUMP (y)))
7577 {
7578 scm_t_inum yy = SCM_I_INUM (y);
7579 scm_t_inum kk = xx * yy;
7580 SCM k = SCM_I_MAKINUM (kk);
7581 if ((kk == SCM_I_INUM (k)) && (kk / xx == yy))
7582 return k;
7583 else
7584 {
7585 SCM result = scm_i_inum2big (xx);
7586 mpz_mul_si (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result), yy);
7587 return scm_i_normbig (result);
7588 }
7589 }
7590 else if (SCM_BIGP (y))
7591 {
7592 SCM result = scm_i_mkbig ();
7593 mpz_mul_si (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (y), xx);
7594 scm_remember_upto_here_1 (y);
7595 return result;
7596 }
7597 else if (SCM_REALP (y))
7598 return scm_from_double (xx * SCM_REAL_VALUE (y));
7599 else if (SCM_COMPLEXP (y))
7600 return scm_c_make_rectangular (xx * SCM_COMPLEX_REAL (y),
7601 xx * SCM_COMPLEX_IMAG (y));
7602 else if (SCM_FRACTIONP (y))
7603 return scm_i_make_ratio (scm_product (x, SCM_FRACTION_NUMERATOR (y)),
7604 SCM_FRACTION_DENOMINATOR (y));
7605 else
7606 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
7607 }
7608 else if (SCM_BIGP (x))
7609 {
7610 if (SCM_I_INUMP (y))
7611 {
7612 SCM_SWAP (x, y);
7613 goto xinum;
7614 }
7615 else if (SCM_BIGP (y))
7616 {
7617 SCM result = scm_i_mkbig ();
7618 mpz_mul (SCM_I_BIG_MPZ (result),
7619 SCM_I_BIG_MPZ (x),
7620 SCM_I_BIG_MPZ (y));
7621 scm_remember_upto_here_2 (x, y);
7622 return result;
7623 }
7624 else if (SCM_REALP (y))
7625 {
7626 double result = mpz_get_d (SCM_I_BIG_MPZ (x)) * SCM_REAL_VALUE (y);
7627 scm_remember_upto_here_1 (x);
7628 return scm_from_double (result);
7629 }
7630 else if (SCM_COMPLEXP (y))
7631 {
7632 double z = mpz_get_d (SCM_I_BIG_MPZ (x));
7633 scm_remember_upto_here_1 (x);
7634 return scm_c_make_rectangular (z * SCM_COMPLEX_REAL (y),
7635 z * SCM_COMPLEX_IMAG (y));
7636 }
7637 else if (SCM_FRACTIONP (y))
7638 return scm_i_make_ratio (scm_product (x, SCM_FRACTION_NUMERATOR (y)),
7639 SCM_FRACTION_DENOMINATOR (y));
7640 else
7641 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
7642 }
7643 else if (SCM_REALP (x))
7644 {
7645 if (SCM_I_INUMP (y))
7646 {
7647 SCM_SWAP (x, y);
7648 goto xinum;
7649 }
7650 else if (SCM_BIGP (y))
7651 {
7652 double result = mpz_get_d (SCM_I_BIG_MPZ (y)) * SCM_REAL_VALUE (x);
7653 scm_remember_upto_here_1 (y);
7654 return scm_from_double (result);
7655 }
7656 else if (SCM_REALP (y))
7657 return scm_from_double (SCM_REAL_VALUE (x) * SCM_REAL_VALUE (y));
7658 else if (SCM_COMPLEXP (y))
7659 return scm_c_make_rectangular (SCM_REAL_VALUE (x) * SCM_COMPLEX_REAL (y),
7660 SCM_REAL_VALUE (x) * SCM_COMPLEX_IMAG (y));
7661 else if (SCM_FRACTIONP (y))
7662 return scm_from_double (SCM_REAL_VALUE (x) * scm_i_fraction2double (y));
7663 else
7664 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
7665 }
7666 else if (SCM_COMPLEXP (x))
7667 {
7668 if (SCM_I_INUMP (y))
7669 {
7670 SCM_SWAP (x, y);
7671 goto xinum;
7672 }
7673 else if (SCM_BIGP (y))
7674 {
7675 double z = mpz_get_d (SCM_I_BIG_MPZ (y));
7676 scm_remember_upto_here_1 (y);
7677 return scm_c_make_rectangular (z * SCM_COMPLEX_REAL (x),
7678 z * SCM_COMPLEX_IMAG (x));
7679 }
7680 else if (SCM_REALP (y))
7681 return scm_c_make_rectangular (SCM_REAL_VALUE (y) * SCM_COMPLEX_REAL (x),
7682 SCM_REAL_VALUE (y) * SCM_COMPLEX_IMAG (x));
7683 else if (SCM_COMPLEXP (y))
7684 {
7685 return scm_c_make_rectangular (SCM_COMPLEX_REAL (x) * SCM_COMPLEX_REAL (y)
7686 - SCM_COMPLEX_IMAG (x) * SCM_COMPLEX_IMAG (y),
7687 SCM_COMPLEX_REAL (x) * SCM_COMPLEX_IMAG (y)
7688 + SCM_COMPLEX_IMAG (x) * SCM_COMPLEX_REAL (y));
7689 }
7690 else if (SCM_FRACTIONP (y))
7691 {
7692 double yy = scm_i_fraction2double (y);
7693 return scm_c_make_rectangular (yy * SCM_COMPLEX_REAL (x),
7694 yy * SCM_COMPLEX_IMAG (x));
7695 }
7696 else
7697 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
7698 }
7699 else if (SCM_FRACTIONP (x))
7700 {
7701 if (SCM_I_INUMP (y))
7702 return scm_i_make_ratio (scm_product (y, SCM_FRACTION_NUMERATOR (x)),
7703 SCM_FRACTION_DENOMINATOR (x));
7704 else if (SCM_BIGP (y))
7705 return scm_i_make_ratio (scm_product (y, SCM_FRACTION_NUMERATOR (x)),
7706 SCM_FRACTION_DENOMINATOR (x));
7707 else if (SCM_REALP (y))
7708 return scm_from_double (scm_i_fraction2double (x) * SCM_REAL_VALUE (y));
7709 else if (SCM_COMPLEXP (y))
7710 {
7711 double xx = scm_i_fraction2double (x);
7712 return scm_c_make_rectangular (xx * SCM_COMPLEX_REAL (y),
7713 xx * SCM_COMPLEX_IMAG (y));
7714 }
7715 else if (SCM_FRACTIONP (y))
7716 /* a/b * c/d = ac / bd */
7717 return scm_i_make_ratio (scm_product (SCM_FRACTION_NUMERATOR (x),
7718 SCM_FRACTION_NUMERATOR (y)),
7719 scm_product (SCM_FRACTION_DENOMINATOR (x),
7720 SCM_FRACTION_DENOMINATOR (y)));
7721 else
7722 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
7723 }
7724 else
7725 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARG1, s_product);
7726 }
7727
7728 #if ((defined (HAVE_ISINF) && defined (HAVE_ISNAN)) \
7729 || (defined (HAVE_FINITE) && defined (HAVE_ISNAN)))
7730 #define ALLOW_DIVIDE_BY_ZERO
7731 /* #define ALLOW_DIVIDE_BY_EXACT_ZERO */
7732 #endif
7733
7734 /* The code below for complex division is adapted from the GNU
7735 libstdc++, which adapted it from f2c's libF77, and is subject to
7736 this copyright: */
7737
7738 /****************************************************************
7739 Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories and Bellcore.
7740
7741 Permission to use, copy, modify, and distribute this software
7742 and its documentation for any purpose and without fee is hereby
7743 granted, provided that the above copyright notice appear in all
7744 copies and that both that the copyright notice and this
7745 permission notice and warranty disclaimer appear in supporting
7746 documentation, and that the names of AT&T Bell Laboratories or
7747 Bellcore or any of their entities not be used in advertising or
7748 publicity pertaining to distribution of the software without
7749 specific, written prior permission.
7750
7751 AT&T and Bellcore disclaim all warranties with regard to this
7752 software, including all implied warranties of merchantability
7753 and fitness. In no event shall AT&T or Bellcore be liable for
7754 any special, indirect or consequential damages or any damages
7755 whatsoever resulting from loss of use, data or profits, whether
7756 in an action of contract, negligence or other tortious action,
7757 arising out of or in connection with the use or performance of
7758 this software.
7759 ****************************************************************/
7760
7761 SCM_PRIMITIVE_GENERIC (scm_i_divide, "/", 0, 2, 1,
7762 (SCM x, SCM y, SCM rest),
7763 "Divide the first argument by the product of the remaining\n"
7764 "arguments. If called with one argument @var{z1}, 1/@var{z1} is\n"
7765 "returned.")
7766 #define FUNC_NAME s_scm_i_divide
7767 {
7768 while (!scm_is_null (rest))
7769 { x = scm_divide (x, y);
7770 y = scm_car (rest);
7771 rest = scm_cdr (rest);
7772 }
7773 return scm_divide (x, y);
7774 }
7775 #undef FUNC_NAME
7776
7777 #define s_divide s_scm_i_divide
7778 #define g_divide g_scm_i_divide
7779
7780 static SCM
7781 do_divide (SCM x, SCM y, int inexact)
7782 #define FUNC_NAME s_divide
7783 {
7784 double a;
7785
7786 if (SCM_UNLIKELY (SCM_UNBNDP (y)))
7787 {
7788 if (SCM_UNBNDP (x))
7789 SCM_WTA_DISPATCH_0 (g_divide, s_divide);
7790 else if (SCM_I_INUMP (x))
7791 {
7792 scm_t_inum xx = SCM_I_INUM (x);
7793 if (xx == 1 || xx == -1)
7794 return x;
7795 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
7796 else if (xx == 0)
7797 scm_num_overflow (s_divide);
7798 #endif
7799 else
7800 {
7801 if (inexact)
7802 return scm_from_double (1.0 / (double) xx);
7803 else return scm_i_make_ratio (SCM_INUM1, x);
7804 }
7805 }
7806 else if (SCM_BIGP (x))
7807 {
7808 if (inexact)
7809 return scm_from_double (1.0 / scm_i_big2dbl (x));
7810 else return scm_i_make_ratio (SCM_INUM1, x);
7811 }
7812 else if (SCM_REALP (x))
7813 {
7814 double xx = SCM_REAL_VALUE (x);
7815 #ifndef ALLOW_DIVIDE_BY_ZERO
7816 if (xx == 0.0)
7817 scm_num_overflow (s_divide);
7818 else
7819 #endif
7820 return scm_from_double (1.0 / xx);
7821 }
7822 else if (SCM_COMPLEXP (x))
7823 {
7824 double r = SCM_COMPLEX_REAL (x);
7825 double i = SCM_COMPLEX_IMAG (x);
7826 if (fabs(r) <= fabs(i))
7827 {
7828 double t = r / i;
7829 double d = i * (1.0 + t * t);
7830 return scm_c_make_rectangular (t / d, -1.0 / d);
7831 }
7832 else
7833 {
7834 double t = i / r;
7835 double d = r * (1.0 + t * t);
7836 return scm_c_make_rectangular (1.0 / d, -t / d);
7837 }
7838 }
7839 else if (SCM_FRACTIONP (x))
7840 return scm_i_make_ratio (SCM_FRACTION_DENOMINATOR (x),
7841 SCM_FRACTION_NUMERATOR (x));
7842 else
7843 SCM_WTA_DISPATCH_1 (g_divide, x, SCM_ARG1, s_divide);
7844 }
7845
7846 if (SCM_LIKELY (SCM_I_INUMP (x)))
7847 {
7848 scm_t_inum xx = SCM_I_INUM (x);
7849 if (SCM_LIKELY (SCM_I_INUMP (y)))
7850 {
7851 scm_t_inum yy = SCM_I_INUM (y);
7852 if (yy == 0)
7853 {
7854 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
7855 scm_num_overflow (s_divide);
7856 #else
7857 return scm_from_double ((double) xx / (double) yy);
7858 #endif
7859 }
7860 else if (xx % yy != 0)
7861 {
7862 if (inexact)
7863 return scm_from_double ((double) xx / (double) yy);
7864 else return scm_i_make_ratio (x, y);
7865 }
7866 else
7867 {
7868 scm_t_inum z = xx / yy;
7869 if (SCM_FIXABLE (z))
7870 return SCM_I_MAKINUM (z);
7871 else
7872 return scm_i_inum2big (z);
7873 }
7874 }
7875 else if (SCM_BIGP (y))
7876 {
7877 if (inexact)
7878 return scm_from_double ((double) xx / scm_i_big2dbl (y));
7879 else return scm_i_make_ratio (x, y);
7880 }
7881 else if (SCM_REALP (y))
7882 {
7883 double yy = SCM_REAL_VALUE (y);
7884 #ifndef ALLOW_DIVIDE_BY_ZERO
7885 if (yy == 0.0)
7886 scm_num_overflow (s_divide);
7887 else
7888 #endif
7889 return scm_from_double ((double) xx / yy);
7890 }
7891 else if (SCM_COMPLEXP (y))
7892 {
7893 a = xx;
7894 complex_div: /* y _must_ be a complex number */
7895 {
7896 double r = SCM_COMPLEX_REAL (y);
7897 double i = SCM_COMPLEX_IMAG (y);
7898 if (fabs(r) <= fabs(i))
7899 {
7900 double t = r / i;
7901 double d = i * (1.0 + t * t);
7902 return scm_c_make_rectangular ((a * t) / d, -a / d);
7903 }
7904 else
7905 {
7906 double t = i / r;
7907 double d = r * (1.0 + t * t);
7908 return scm_c_make_rectangular (a / d, -(a * t) / d);
7909 }
7910 }
7911 }
7912 else if (SCM_FRACTIONP (y))
7913 /* a / b/c = ac / b */
7914 return scm_i_make_ratio (scm_product (x, SCM_FRACTION_DENOMINATOR (y)),
7915 SCM_FRACTION_NUMERATOR (y));
7916 else
7917 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
7918 }
7919 else if (SCM_BIGP (x))
7920 {
7921 if (SCM_I_INUMP (y))
7922 {
7923 scm_t_inum yy = SCM_I_INUM (y);
7924 if (yy == 0)
7925 {
7926 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
7927 scm_num_overflow (s_divide);
7928 #else
7929 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
7930 scm_remember_upto_here_1 (x);
7931 return (sgn == 0) ? scm_nan () : scm_inf ();
7932 #endif
7933 }
7934 else if (yy == 1)
7935 return x;
7936 else
7937 {
7938 /* FIXME: HMM, what are the relative performance issues here?
7939 We need to test. Is it faster on average to test
7940 divisible_p, then perform whichever operation, or is it
7941 faster to perform the integer div opportunistically and
7942 switch to real if there's a remainder? For now we take the
7943 middle ground: test, then if divisible, use the faster div
7944 func. */
7945
7946 scm_t_inum abs_yy = yy < 0 ? -yy : yy;
7947 int divisible_p = mpz_divisible_ui_p (SCM_I_BIG_MPZ (x), abs_yy);
7948
7949 if (divisible_p)
7950 {
7951 SCM result = scm_i_mkbig ();
7952 mpz_divexact_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), abs_yy);
7953 scm_remember_upto_here_1 (x);
7954 if (yy < 0)
7955 mpz_neg (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result));
7956 return scm_i_normbig (result);
7957 }
7958 else
7959 {
7960 if (inexact)
7961 return scm_from_double (scm_i_big2dbl (x) / (double) yy);
7962 else return scm_i_make_ratio (x, y);
7963 }
7964 }
7965 }
7966 else if (SCM_BIGP (y))
7967 {
7968 /* big_x / big_y */
7969 if (inexact)
7970 {
7971 /* It's easily possible for the ratio x/y to fit a double
7972 but one or both x and y be too big to fit a double,
7973 hence the use of mpq_get_d rather than converting and
7974 dividing. */
7975 mpq_t q;
7976 *mpq_numref(q) = *SCM_I_BIG_MPZ (x);
7977 *mpq_denref(q) = *SCM_I_BIG_MPZ (y);
7978 return scm_from_double (mpq_get_d (q));
7979 }
7980 else
7981 {
7982 int divisible_p = mpz_divisible_p (SCM_I_BIG_MPZ (x),
7983 SCM_I_BIG_MPZ (y));
7984 if (divisible_p)
7985 {
7986 SCM result = scm_i_mkbig ();
7987 mpz_divexact (SCM_I_BIG_MPZ (result),
7988 SCM_I_BIG_MPZ (x),
7989 SCM_I_BIG_MPZ (y));
7990 scm_remember_upto_here_2 (x, y);
7991 return scm_i_normbig (result);
7992 }
7993 else
7994 return scm_i_make_ratio (x, y);
7995 }
7996 }
7997 else if (SCM_REALP (y))
7998 {
7999 double yy = SCM_REAL_VALUE (y);
8000 #ifndef ALLOW_DIVIDE_BY_ZERO
8001 if (yy == 0.0)
8002 scm_num_overflow (s_divide);
8003 else
8004 #endif
8005 return scm_from_double (scm_i_big2dbl (x) / yy);
8006 }
8007 else if (SCM_COMPLEXP (y))
8008 {
8009 a = scm_i_big2dbl (x);
8010 goto complex_div;
8011 }
8012 else if (SCM_FRACTIONP (y))
8013 return scm_i_make_ratio (scm_product (x, SCM_FRACTION_DENOMINATOR (y)),
8014 SCM_FRACTION_NUMERATOR (y));
8015 else
8016 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
8017 }
8018 else if (SCM_REALP (x))
8019 {
8020 double rx = SCM_REAL_VALUE (x);
8021 if (SCM_I_INUMP (y))
8022 {
8023 scm_t_inum yy = SCM_I_INUM (y);
8024 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
8025 if (yy == 0)
8026 scm_num_overflow (s_divide);
8027 else
8028 #endif
8029 return scm_from_double (rx / (double) yy);
8030 }
8031 else if (SCM_BIGP (y))
8032 {
8033 double dby = mpz_get_d (SCM_I_BIG_MPZ (y));
8034 scm_remember_upto_here_1 (y);
8035 return scm_from_double (rx / dby);
8036 }
8037 else if (SCM_REALP (y))
8038 {
8039 double yy = SCM_REAL_VALUE (y);
8040 #ifndef ALLOW_DIVIDE_BY_ZERO
8041 if (yy == 0.0)
8042 scm_num_overflow (s_divide);
8043 else
8044 #endif
8045 return scm_from_double (rx / yy);
8046 }
8047 else if (SCM_COMPLEXP (y))
8048 {
8049 a = rx;
8050 goto complex_div;
8051 }
8052 else if (SCM_FRACTIONP (y))
8053 return scm_from_double (rx / scm_i_fraction2double (y));
8054 else
8055 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
8056 }
8057 else if (SCM_COMPLEXP (x))
8058 {
8059 double rx = SCM_COMPLEX_REAL (x);
8060 double ix = SCM_COMPLEX_IMAG (x);
8061 if (SCM_I_INUMP (y))
8062 {
8063 scm_t_inum yy = SCM_I_INUM (y);
8064 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
8065 if (yy == 0)
8066 scm_num_overflow (s_divide);
8067 else
8068 #endif
8069 {
8070 double d = yy;
8071 return scm_c_make_rectangular (rx / d, ix / d);
8072 }
8073 }
8074 else if (SCM_BIGP (y))
8075 {
8076 double dby = mpz_get_d (SCM_I_BIG_MPZ (y));
8077 scm_remember_upto_here_1 (y);
8078 return scm_c_make_rectangular (rx / dby, ix / dby);
8079 }
8080 else if (SCM_REALP (y))
8081 {
8082 double yy = SCM_REAL_VALUE (y);
8083 #ifndef ALLOW_DIVIDE_BY_ZERO
8084 if (yy == 0.0)
8085 scm_num_overflow (s_divide);
8086 else
8087 #endif
8088 return scm_c_make_rectangular (rx / yy, ix / yy);
8089 }
8090 else if (SCM_COMPLEXP (y))
8091 {
8092 double ry = SCM_COMPLEX_REAL (y);
8093 double iy = SCM_COMPLEX_IMAG (y);
8094 if (fabs(ry) <= fabs(iy))
8095 {
8096 double t = ry / iy;
8097 double d = iy * (1.0 + t * t);
8098 return scm_c_make_rectangular ((rx * t + ix) / d, (ix * t - rx) / d);
8099 }
8100 else
8101 {
8102 double t = iy / ry;
8103 double d = ry * (1.0 + t * t);
8104 return scm_c_make_rectangular ((rx + ix * t) / d, (ix - rx * t) / d);
8105 }
8106 }
8107 else if (SCM_FRACTIONP (y))
8108 {
8109 double yy = scm_i_fraction2double (y);
8110 return scm_c_make_rectangular (rx / yy, ix / yy);
8111 }
8112 else
8113 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
8114 }
8115 else if (SCM_FRACTIONP (x))
8116 {
8117 if (SCM_I_INUMP (y))
8118 {
8119 scm_t_inum yy = SCM_I_INUM (y);
8120 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
8121 if (yy == 0)
8122 scm_num_overflow (s_divide);
8123 else
8124 #endif
8125 return scm_i_make_ratio (SCM_FRACTION_NUMERATOR (x),
8126 scm_product (SCM_FRACTION_DENOMINATOR (x), y));
8127 }
8128 else if (SCM_BIGP (y))
8129 {
8130 return scm_i_make_ratio (SCM_FRACTION_NUMERATOR (x),
8131 scm_product (SCM_FRACTION_DENOMINATOR (x), y));
8132 }
8133 else if (SCM_REALP (y))
8134 {
8135 double yy = SCM_REAL_VALUE (y);
8136 #ifndef ALLOW_DIVIDE_BY_ZERO
8137 if (yy == 0.0)
8138 scm_num_overflow (s_divide);
8139 else
8140 #endif
8141 return scm_from_double (scm_i_fraction2double (x) / yy);
8142 }
8143 else if (SCM_COMPLEXP (y))
8144 {
8145 a = scm_i_fraction2double (x);
8146 goto complex_div;
8147 }
8148 else if (SCM_FRACTIONP (y))
8149 return scm_i_make_ratio (scm_product (SCM_FRACTION_NUMERATOR (x), SCM_FRACTION_DENOMINATOR (y)),
8150 scm_product (SCM_FRACTION_NUMERATOR (y), SCM_FRACTION_DENOMINATOR (x)));
8151 else
8152 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
8153 }
8154 else
8155 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARG1, s_divide);
8156 }
8157
8158 SCM
8159 scm_divide (SCM x, SCM y)
8160 {
8161 return do_divide (x, y, 0);
8162 }
8163
8164 static SCM scm_divide2real (SCM x, SCM y)
8165 {
8166 return do_divide (x, y, 1);
8167 }
8168 #undef FUNC_NAME
8169
8170
8171 double
8172 scm_c_truncate (double x)
8173 {
8174 return trunc (x);
8175 }
8176
8177 /* scm_c_round is done using floor(x+0.5) to round to nearest and with
8178 half-way case (ie. when x is an integer plus 0.5) going upwards.
8179 Then half-way cases are identified and adjusted down if the
8180 round-upwards didn't give the desired even integer.
8181
8182 "plus_half == result" identifies a half-way case. If plus_half, which is
8183 x + 0.5, is an integer then x must be an integer plus 0.5.
8184
8185 An odd "result" value is identified with result/2 != floor(result/2).
8186 This is done with plus_half, since that value is ready for use sooner in
8187 a pipelined cpu, and we're already requiring plus_half == result.
8188
8189 Note however that we need to be careful when x is big and already an
8190 integer. In that case "x+0.5" may round to an adjacent integer, causing
8191 us to return such a value, incorrectly. For instance if the hardware is
8192 in the usual default nearest-even rounding, then for x = 0x1FFFFFFFFFFFFF
8193 (ie. 53 one bits) we will have x+0.5 = 0x20000000000000 and that value
8194 returned. Or if the hardware is in round-upwards mode, then other bigger
8195 values like say x == 2^128 will see x+0.5 rounding up to the next higher
8196 representable value, 2^128+2^76 (or whatever), again incorrect.
8197
8198 These bad roundings of x+0.5 are avoided by testing at the start whether
8199 x is already an integer. If it is then clearly that's the desired result
8200 already. And if it's not then the exponent must be small enough to allow
8201 an 0.5 to be represented, and hence added without a bad rounding. */
8202
8203 double
8204 scm_c_round (double x)
8205 {
8206 double plus_half, result;
8207
8208 if (x == floor (x))
8209 return x;
8210
8211 plus_half = x + 0.5;
8212 result = floor (plus_half);
8213 /* Adjust so that the rounding is towards even. */
8214 return ((plus_half == result && plus_half / 2 != floor (plus_half / 2))
8215 ? result - 1
8216 : result);
8217 }
8218
8219 SCM_PRIMITIVE_GENERIC (scm_truncate_number, "truncate", 1, 0, 0,
8220 (SCM x),
8221 "Round the number @var{x} towards zero.")
8222 #define FUNC_NAME s_scm_truncate_number
8223 {
8224 if (SCM_I_INUMP (x) || SCM_BIGP (x))
8225 return x;
8226 else if (SCM_REALP (x))
8227 return scm_from_double (trunc (SCM_REAL_VALUE (x)));
8228 else if (SCM_FRACTIONP (x))
8229 return scm_truncate_quotient (SCM_FRACTION_NUMERATOR (x),
8230 SCM_FRACTION_DENOMINATOR (x));
8231 else
8232 SCM_WTA_DISPATCH_1 (g_scm_truncate_number, x, SCM_ARG1,
8233 s_scm_truncate_number);
8234 }
8235 #undef FUNC_NAME
8236
8237 SCM_PRIMITIVE_GENERIC (scm_round_number, "round", 1, 0, 0,
8238 (SCM x),
8239 "Round the number @var{x} towards the nearest integer. "
8240 "When it is exactly halfway between two integers, "
8241 "round towards the even one.")
8242 #define FUNC_NAME s_scm_round_number
8243 {
8244 if (SCM_I_INUMP (x) || SCM_BIGP (x))
8245 return x;
8246 else if (SCM_REALP (x))
8247 return scm_from_double (scm_c_round (SCM_REAL_VALUE (x)));
8248 else if (SCM_FRACTIONP (x))
8249 return scm_round_quotient (SCM_FRACTION_NUMERATOR (x),
8250 SCM_FRACTION_DENOMINATOR (x));
8251 else
8252 SCM_WTA_DISPATCH_1 (g_scm_round_number, x, SCM_ARG1,
8253 s_scm_round_number);
8254 }
8255 #undef FUNC_NAME
8256
8257 SCM_PRIMITIVE_GENERIC (scm_floor, "floor", 1, 0, 0,
8258 (SCM x),
8259 "Round the number @var{x} towards minus infinity.")
8260 #define FUNC_NAME s_scm_floor
8261 {
8262 if (SCM_I_INUMP (x) || SCM_BIGP (x))
8263 return x;
8264 else if (SCM_REALP (x))
8265 return scm_from_double (floor (SCM_REAL_VALUE (x)));
8266 else if (SCM_FRACTIONP (x))
8267 return scm_floor_quotient (SCM_FRACTION_NUMERATOR (x),
8268 SCM_FRACTION_DENOMINATOR (x));
8269 else
8270 SCM_WTA_DISPATCH_1 (g_scm_floor, x, 1, s_scm_floor);
8271 }
8272 #undef FUNC_NAME
8273
8274 SCM_PRIMITIVE_GENERIC (scm_ceiling, "ceiling", 1, 0, 0,
8275 (SCM x),
8276 "Round the number @var{x} towards infinity.")
8277 #define FUNC_NAME s_scm_ceiling
8278 {
8279 if (SCM_I_INUMP (x) || SCM_BIGP (x))
8280 return x;
8281 else if (SCM_REALP (x))
8282 return scm_from_double (ceil (SCM_REAL_VALUE (x)));
8283 else if (SCM_FRACTIONP (x))
8284 return scm_ceiling_quotient (SCM_FRACTION_NUMERATOR (x),
8285 SCM_FRACTION_DENOMINATOR (x));
8286 else
8287 SCM_WTA_DISPATCH_1 (g_scm_ceiling, x, 1, s_scm_ceiling);
8288 }
8289 #undef FUNC_NAME
8290
8291 SCM_PRIMITIVE_GENERIC (scm_expt, "expt", 2, 0, 0,
8292 (SCM x, SCM y),
8293 "Return @var{x} raised to the power of @var{y}.")
8294 #define FUNC_NAME s_scm_expt
8295 {
8296 if (scm_is_integer (y))
8297 {
8298 if (scm_is_true (scm_exact_p (y)))
8299 return scm_integer_expt (x, y);
8300 else
8301 {
8302 /* Here we handle the case where the exponent is an inexact
8303 integer. We make the exponent exact in order to use
8304 scm_integer_expt, and thus avoid the spurious imaginary
8305 parts that may result from round-off errors in the general
8306 e^(y log x) method below (for example when squaring a large
8307 negative number). In this case, we must return an inexact
8308 result for correctness. We also make the base inexact so
8309 that scm_integer_expt will use fast inexact arithmetic
8310 internally. Note that making the base inexact is not
8311 sufficient to guarantee an inexact result, because
8312 scm_integer_expt will return an exact 1 when the exponent
8313 is 0, even if the base is inexact. */
8314 return scm_exact_to_inexact
8315 (scm_integer_expt (scm_exact_to_inexact (x),
8316 scm_inexact_to_exact (y)));
8317 }
8318 }
8319 else if (scm_is_real (x) && scm_is_real (y) && scm_to_double (x) >= 0.0)
8320 {
8321 return scm_from_double (pow (scm_to_double (x), scm_to_double (y)));
8322 }
8323 else if (scm_is_complex (x) && scm_is_complex (y))
8324 return scm_exp (scm_product (scm_log (x), y));
8325 else if (scm_is_complex (x))
8326 SCM_WTA_DISPATCH_2 (g_scm_expt, x, y, SCM_ARG2, s_scm_expt);
8327 else
8328 SCM_WTA_DISPATCH_2 (g_scm_expt, x, y, SCM_ARG1, s_scm_expt);
8329 }
8330 #undef FUNC_NAME
8331
8332 /* sin/cos/tan/asin/acos/atan
8333 sinh/cosh/tanh/asinh/acosh/atanh
8334 Derived from "Transcen.scm", Complex trancendental functions for SCM.
8335 Written by Jerry D. Hedden, (C) FSF.
8336 See the file `COPYING' for terms applying to this program. */
8337
8338 SCM_PRIMITIVE_GENERIC (scm_sin, "sin", 1, 0, 0,
8339 (SCM z),
8340 "Compute the sine of @var{z}.")
8341 #define FUNC_NAME s_scm_sin
8342 {
8343 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8344 return z; /* sin(exact0) = exact0 */
8345 else if (scm_is_real (z))
8346 return scm_from_double (sin (scm_to_double (z)));
8347 else if (SCM_COMPLEXP (z))
8348 { double x, y;
8349 x = SCM_COMPLEX_REAL (z);
8350 y = SCM_COMPLEX_IMAG (z);
8351 return scm_c_make_rectangular (sin (x) * cosh (y),
8352 cos (x) * sinh (y));
8353 }
8354 else
8355 SCM_WTA_DISPATCH_1 (g_scm_sin, z, 1, s_scm_sin);
8356 }
8357 #undef FUNC_NAME
8358
8359 SCM_PRIMITIVE_GENERIC (scm_cos, "cos", 1, 0, 0,
8360 (SCM z),
8361 "Compute the cosine of @var{z}.")
8362 #define FUNC_NAME s_scm_cos
8363 {
8364 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8365 return SCM_INUM1; /* cos(exact0) = exact1 */
8366 else if (scm_is_real (z))
8367 return scm_from_double (cos (scm_to_double (z)));
8368 else if (SCM_COMPLEXP (z))
8369 { double x, y;
8370 x = SCM_COMPLEX_REAL (z);
8371 y = SCM_COMPLEX_IMAG (z);
8372 return scm_c_make_rectangular (cos (x) * cosh (y),
8373 -sin (x) * sinh (y));
8374 }
8375 else
8376 SCM_WTA_DISPATCH_1 (g_scm_cos, z, 1, s_scm_cos);
8377 }
8378 #undef FUNC_NAME
8379
8380 SCM_PRIMITIVE_GENERIC (scm_tan, "tan", 1, 0, 0,
8381 (SCM z),
8382 "Compute the tangent of @var{z}.")
8383 #define FUNC_NAME s_scm_tan
8384 {
8385 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8386 return z; /* tan(exact0) = exact0 */
8387 else if (scm_is_real (z))
8388 return scm_from_double (tan (scm_to_double (z)));
8389 else if (SCM_COMPLEXP (z))
8390 { double x, y, w;
8391 x = 2.0 * SCM_COMPLEX_REAL (z);
8392 y = 2.0 * SCM_COMPLEX_IMAG (z);
8393 w = cos (x) + cosh (y);
8394 #ifndef ALLOW_DIVIDE_BY_ZERO
8395 if (w == 0.0)
8396 scm_num_overflow (s_scm_tan);
8397 #endif
8398 return scm_c_make_rectangular (sin (x) / w, sinh (y) / w);
8399 }
8400 else
8401 SCM_WTA_DISPATCH_1 (g_scm_tan, z, 1, s_scm_tan);
8402 }
8403 #undef FUNC_NAME
8404
8405 SCM_PRIMITIVE_GENERIC (scm_sinh, "sinh", 1, 0, 0,
8406 (SCM z),
8407 "Compute the hyperbolic sine of @var{z}.")
8408 #define FUNC_NAME s_scm_sinh
8409 {
8410 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8411 return z; /* sinh(exact0) = exact0 */
8412 else if (scm_is_real (z))
8413 return scm_from_double (sinh (scm_to_double (z)));
8414 else if (SCM_COMPLEXP (z))
8415 { double x, y;
8416 x = SCM_COMPLEX_REAL (z);
8417 y = SCM_COMPLEX_IMAG (z);
8418 return scm_c_make_rectangular (sinh (x) * cos (y),
8419 cosh (x) * sin (y));
8420 }
8421 else
8422 SCM_WTA_DISPATCH_1 (g_scm_sinh, z, 1, s_scm_sinh);
8423 }
8424 #undef FUNC_NAME
8425
8426 SCM_PRIMITIVE_GENERIC (scm_cosh, "cosh", 1, 0, 0,
8427 (SCM z),
8428 "Compute the hyperbolic cosine of @var{z}.")
8429 #define FUNC_NAME s_scm_cosh
8430 {
8431 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8432 return SCM_INUM1; /* cosh(exact0) = exact1 */
8433 else if (scm_is_real (z))
8434 return scm_from_double (cosh (scm_to_double (z)));
8435 else if (SCM_COMPLEXP (z))
8436 { double x, y;
8437 x = SCM_COMPLEX_REAL (z);
8438 y = SCM_COMPLEX_IMAG (z);
8439 return scm_c_make_rectangular (cosh (x) * cos (y),
8440 sinh (x) * sin (y));
8441 }
8442 else
8443 SCM_WTA_DISPATCH_1 (g_scm_cosh, z, 1, s_scm_cosh);
8444 }
8445 #undef FUNC_NAME
8446
8447 SCM_PRIMITIVE_GENERIC (scm_tanh, "tanh", 1, 0, 0,
8448 (SCM z),
8449 "Compute the hyperbolic tangent of @var{z}.")
8450 #define FUNC_NAME s_scm_tanh
8451 {
8452 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8453 return z; /* tanh(exact0) = exact0 */
8454 else if (scm_is_real (z))
8455 return scm_from_double (tanh (scm_to_double (z)));
8456 else if (SCM_COMPLEXP (z))
8457 { double x, y, w;
8458 x = 2.0 * SCM_COMPLEX_REAL (z);
8459 y = 2.0 * SCM_COMPLEX_IMAG (z);
8460 w = cosh (x) + cos (y);
8461 #ifndef ALLOW_DIVIDE_BY_ZERO
8462 if (w == 0.0)
8463 scm_num_overflow (s_scm_tanh);
8464 #endif
8465 return scm_c_make_rectangular (sinh (x) / w, sin (y) / w);
8466 }
8467 else
8468 SCM_WTA_DISPATCH_1 (g_scm_tanh, z, 1, s_scm_tanh);
8469 }
8470 #undef FUNC_NAME
8471
8472 SCM_PRIMITIVE_GENERIC (scm_asin, "asin", 1, 0, 0,
8473 (SCM z),
8474 "Compute the arc sine of @var{z}.")
8475 #define FUNC_NAME s_scm_asin
8476 {
8477 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8478 return z; /* asin(exact0) = exact0 */
8479 else if (scm_is_real (z))
8480 {
8481 double w = scm_to_double (z);
8482 if (w >= -1.0 && w <= 1.0)
8483 return scm_from_double (asin (w));
8484 else
8485 return scm_product (scm_c_make_rectangular (0, -1),
8486 scm_sys_asinh (scm_c_make_rectangular (0, w)));
8487 }
8488 else if (SCM_COMPLEXP (z))
8489 { double x, y;
8490 x = SCM_COMPLEX_REAL (z);
8491 y = SCM_COMPLEX_IMAG (z);
8492 return scm_product (scm_c_make_rectangular (0, -1),
8493 scm_sys_asinh (scm_c_make_rectangular (-y, x)));
8494 }
8495 else
8496 SCM_WTA_DISPATCH_1 (g_scm_asin, z, 1, s_scm_asin);
8497 }
8498 #undef FUNC_NAME
8499
8500 SCM_PRIMITIVE_GENERIC (scm_acos, "acos", 1, 0, 0,
8501 (SCM z),
8502 "Compute the arc cosine of @var{z}.")
8503 #define FUNC_NAME s_scm_acos
8504 {
8505 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM1)))
8506 return SCM_INUM0; /* acos(exact1) = exact0 */
8507 else if (scm_is_real (z))
8508 {
8509 double w = scm_to_double (z);
8510 if (w >= -1.0 && w <= 1.0)
8511 return scm_from_double (acos (w));
8512 else
8513 return scm_sum (scm_from_double (acos (0.0)),
8514 scm_product (scm_c_make_rectangular (0, 1),
8515 scm_sys_asinh (scm_c_make_rectangular (0, w))));
8516 }
8517 else if (SCM_COMPLEXP (z))
8518 { double x, y;
8519 x = SCM_COMPLEX_REAL (z);
8520 y = SCM_COMPLEX_IMAG (z);
8521 return scm_sum (scm_from_double (acos (0.0)),
8522 scm_product (scm_c_make_rectangular (0, 1),
8523 scm_sys_asinh (scm_c_make_rectangular (-y, x))));
8524 }
8525 else
8526 SCM_WTA_DISPATCH_1 (g_scm_acos, z, 1, s_scm_acos);
8527 }
8528 #undef FUNC_NAME
8529
8530 SCM_PRIMITIVE_GENERIC (scm_atan, "atan", 1, 1, 0,
8531 (SCM z, SCM y),
8532 "With one argument, compute the arc tangent of @var{z}.\n"
8533 "If @var{y} is present, compute the arc tangent of @var{z}/@var{y},\n"
8534 "using the sign of @var{z} and @var{y} to determine the quadrant.")
8535 #define FUNC_NAME s_scm_atan
8536 {
8537 if (SCM_UNBNDP (y))
8538 {
8539 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8540 return z; /* atan(exact0) = exact0 */
8541 else if (scm_is_real (z))
8542 return scm_from_double (atan (scm_to_double (z)));
8543 else if (SCM_COMPLEXP (z))
8544 {
8545 double v, w;
8546 v = SCM_COMPLEX_REAL (z);
8547 w = SCM_COMPLEX_IMAG (z);
8548 return scm_divide (scm_log (scm_divide (scm_c_make_rectangular (v, w - 1.0),
8549 scm_c_make_rectangular (v, w + 1.0))),
8550 scm_c_make_rectangular (0, 2));
8551 }
8552 else
8553 SCM_WTA_DISPATCH_1 (g_scm_atan, z, SCM_ARG1, s_scm_atan);
8554 }
8555 else if (scm_is_real (z))
8556 {
8557 if (scm_is_real (y))
8558 return scm_from_double (atan2 (scm_to_double (z), scm_to_double (y)));
8559 else
8560 SCM_WTA_DISPATCH_2 (g_scm_atan, z, y, SCM_ARG2, s_scm_atan);
8561 }
8562 else
8563 SCM_WTA_DISPATCH_2 (g_scm_atan, z, y, SCM_ARG1, s_scm_atan);
8564 }
8565 #undef FUNC_NAME
8566
8567 SCM_PRIMITIVE_GENERIC (scm_sys_asinh, "asinh", 1, 0, 0,
8568 (SCM z),
8569 "Compute the inverse hyperbolic sine of @var{z}.")
8570 #define FUNC_NAME s_scm_sys_asinh
8571 {
8572 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8573 return z; /* asinh(exact0) = exact0 */
8574 else if (scm_is_real (z))
8575 return scm_from_double (asinh (scm_to_double (z)));
8576 else if (scm_is_number (z))
8577 return scm_log (scm_sum (z,
8578 scm_sqrt (scm_sum (scm_product (z, z),
8579 SCM_INUM1))));
8580 else
8581 SCM_WTA_DISPATCH_1 (g_scm_sys_asinh, z, 1, s_scm_sys_asinh);
8582 }
8583 #undef FUNC_NAME
8584
8585 SCM_PRIMITIVE_GENERIC (scm_sys_acosh, "acosh", 1, 0, 0,
8586 (SCM z),
8587 "Compute the inverse hyperbolic cosine of @var{z}.")
8588 #define FUNC_NAME s_scm_sys_acosh
8589 {
8590 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM1)))
8591 return SCM_INUM0; /* acosh(exact1) = exact0 */
8592 else if (scm_is_real (z) && scm_to_double (z) >= 1.0)
8593 return scm_from_double (acosh (scm_to_double (z)));
8594 else if (scm_is_number (z))
8595 return scm_log (scm_sum (z,
8596 scm_sqrt (scm_difference (scm_product (z, z),
8597 SCM_INUM1))));
8598 else
8599 SCM_WTA_DISPATCH_1 (g_scm_sys_acosh, z, 1, s_scm_sys_acosh);
8600 }
8601 #undef FUNC_NAME
8602
8603 SCM_PRIMITIVE_GENERIC (scm_sys_atanh, "atanh", 1, 0, 0,
8604 (SCM z),
8605 "Compute the inverse hyperbolic tangent of @var{z}.")
8606 #define FUNC_NAME s_scm_sys_atanh
8607 {
8608 if (SCM_UNLIKELY (scm_is_eq (z, SCM_INUM0)))
8609 return z; /* atanh(exact0) = exact0 */
8610 else if (scm_is_real (z) && scm_to_double (z) >= -1.0 && scm_to_double (z) <= 1.0)
8611 return scm_from_double (atanh (scm_to_double (z)));
8612 else if (scm_is_number (z))
8613 return scm_divide (scm_log (scm_divide (scm_sum (SCM_INUM1, z),
8614 scm_difference (SCM_INUM1, z))),
8615 SCM_I_MAKINUM (2));
8616 else
8617 SCM_WTA_DISPATCH_1 (g_scm_sys_atanh, z, 1, s_scm_sys_atanh);
8618 }
8619 #undef FUNC_NAME
8620
8621 SCM
8622 scm_c_make_rectangular (double re, double im)
8623 {
8624 SCM z;
8625
8626 z = PTR2SCM (scm_gc_malloc_pointerless (sizeof (scm_t_complex),
8627 "complex"));
8628 SCM_SET_CELL_TYPE (z, scm_tc16_complex);
8629 SCM_COMPLEX_REAL (z) = re;
8630 SCM_COMPLEX_IMAG (z) = im;
8631 return z;
8632 }
8633
8634 SCM_DEFINE (scm_make_rectangular, "make-rectangular", 2, 0, 0,
8635 (SCM real_part, SCM imaginary_part),
8636 "Return a complex number constructed of the given @var{real-part} "
8637 "and @var{imaginary-part} parts.")
8638 #define FUNC_NAME s_scm_make_rectangular
8639 {
8640 SCM_ASSERT_TYPE (scm_is_real (real_part), real_part,
8641 SCM_ARG1, FUNC_NAME, "real");
8642 SCM_ASSERT_TYPE (scm_is_real (imaginary_part), imaginary_part,
8643 SCM_ARG2, FUNC_NAME, "real");
8644
8645 /* Return a real if and only if the imaginary_part is an _exact_ 0 */
8646 if (scm_is_eq (imaginary_part, SCM_INUM0))
8647 return real_part;
8648 else
8649 return scm_c_make_rectangular (scm_to_double (real_part),
8650 scm_to_double (imaginary_part));
8651 }
8652 #undef FUNC_NAME
8653
8654 SCM
8655 scm_c_make_polar (double mag, double ang)
8656 {
8657 double s, c;
8658
8659 /* The sincos(3) function is undocumented an broken on Tru64. Thus we only
8660 use it on Glibc-based systems that have it (it's a GNU extension). See
8661 http://lists.gnu.org/archive/html/guile-user/2009-04/msg00033.html for
8662 details. */
8663 #if (defined HAVE_SINCOS) && (defined __GLIBC__) && (defined _GNU_SOURCE)
8664 sincos (ang, &s, &c);
8665 #else
8666 s = sin (ang);
8667 c = cos (ang);
8668 #endif
8669
8670 /* If s and c are NaNs, this indicates that the angle is a NaN,
8671 infinite, or perhaps simply too large to determine its value
8672 mod 2*pi. However, we know something that the floating-point
8673 implementation doesn't know: We know that s and c are finite.
8674 Therefore, if the magnitude is zero, return a complex zero.
8675
8676 The reason we check for the NaNs instead of using this case
8677 whenever mag == 0.0 is because when the angle is known, we'd
8678 like to return the correct kind of non-real complex zero:
8679 +0.0+0.0i, -0.0+0.0i, -0.0-0.0i, or +0.0-0.0i, depending
8680 on which quadrant the angle is in.
8681 */
8682 if (SCM_UNLIKELY (isnan(s)) && isnan(c) && (mag == 0.0))
8683 return scm_c_make_rectangular (0.0, 0.0);
8684 else
8685 return scm_c_make_rectangular (mag * c, mag * s);
8686 }
8687
8688 SCM_DEFINE (scm_make_polar, "make-polar", 2, 0, 0,
8689 (SCM mag, SCM ang),
8690 "Return the complex number @var{mag} * e^(i * @var{ang}).")
8691 #define FUNC_NAME s_scm_make_polar
8692 {
8693 SCM_ASSERT_TYPE (scm_is_real (mag), mag, SCM_ARG1, FUNC_NAME, "real");
8694 SCM_ASSERT_TYPE (scm_is_real (ang), ang, SCM_ARG2, FUNC_NAME, "real");
8695
8696 /* If mag is exact0, return exact0 */
8697 if (scm_is_eq (mag, SCM_INUM0))
8698 return SCM_INUM0;
8699 /* Return a real if ang is exact0 */
8700 else if (scm_is_eq (ang, SCM_INUM0))
8701 return mag;
8702 else
8703 return scm_c_make_polar (scm_to_double (mag), scm_to_double (ang));
8704 }
8705 #undef FUNC_NAME
8706
8707
8708 SCM_PRIMITIVE_GENERIC (scm_real_part, "real-part", 1, 0, 0,
8709 (SCM z),
8710 "Return the real part of the number @var{z}.")
8711 #define FUNC_NAME s_scm_real_part
8712 {
8713 if (SCM_COMPLEXP (z))
8714 return scm_from_double (SCM_COMPLEX_REAL (z));
8715 else if (SCM_I_INUMP (z) || SCM_BIGP (z) || SCM_REALP (z) || SCM_FRACTIONP (z))
8716 return z;
8717 else
8718 SCM_WTA_DISPATCH_1 (g_scm_real_part, z, SCM_ARG1, s_scm_real_part);
8719 }
8720 #undef FUNC_NAME
8721
8722
8723 SCM_PRIMITIVE_GENERIC (scm_imag_part, "imag-part", 1, 0, 0,
8724 (SCM z),
8725 "Return the imaginary part of the number @var{z}.")
8726 #define FUNC_NAME s_scm_imag_part
8727 {
8728 if (SCM_COMPLEXP (z))
8729 return scm_from_double (SCM_COMPLEX_IMAG (z));
8730 else if (SCM_I_INUMP (z) || SCM_REALP (z) || SCM_BIGP (z) || SCM_FRACTIONP (z))
8731 return SCM_INUM0;
8732 else
8733 SCM_WTA_DISPATCH_1 (g_scm_imag_part, z, SCM_ARG1, s_scm_imag_part);
8734 }
8735 #undef FUNC_NAME
8736
8737 SCM_PRIMITIVE_GENERIC (scm_numerator, "numerator", 1, 0, 0,
8738 (SCM z),
8739 "Return the numerator of the number @var{z}.")
8740 #define FUNC_NAME s_scm_numerator
8741 {
8742 if (SCM_I_INUMP (z) || SCM_BIGP (z))
8743 return z;
8744 else if (SCM_FRACTIONP (z))
8745 return SCM_FRACTION_NUMERATOR (z);
8746 else if (SCM_REALP (z))
8747 return scm_exact_to_inexact (scm_numerator (scm_inexact_to_exact (z)));
8748 else
8749 SCM_WTA_DISPATCH_1 (g_scm_numerator, z, SCM_ARG1, s_scm_numerator);
8750 }
8751 #undef FUNC_NAME
8752
8753
8754 SCM_PRIMITIVE_GENERIC (scm_denominator, "denominator", 1, 0, 0,
8755 (SCM z),
8756 "Return the denominator of the number @var{z}.")
8757 #define FUNC_NAME s_scm_denominator
8758 {
8759 if (SCM_I_INUMP (z) || SCM_BIGP (z))
8760 return SCM_INUM1;
8761 else if (SCM_FRACTIONP (z))
8762 return SCM_FRACTION_DENOMINATOR (z);
8763 else if (SCM_REALP (z))
8764 return scm_exact_to_inexact (scm_denominator (scm_inexact_to_exact (z)));
8765 else
8766 SCM_WTA_DISPATCH_1 (g_scm_denominator, z, SCM_ARG1, s_scm_denominator);
8767 }
8768 #undef FUNC_NAME
8769
8770
8771 SCM_PRIMITIVE_GENERIC (scm_magnitude, "magnitude", 1, 0, 0,
8772 (SCM z),
8773 "Return the magnitude of the number @var{z}. This is the same as\n"
8774 "@code{abs} for real arguments, but also allows complex numbers.")
8775 #define FUNC_NAME s_scm_magnitude
8776 {
8777 if (SCM_I_INUMP (z))
8778 {
8779 scm_t_inum zz = SCM_I_INUM (z);
8780 if (zz >= 0)
8781 return z;
8782 else if (SCM_POSFIXABLE (-zz))
8783 return SCM_I_MAKINUM (-zz);
8784 else
8785 return scm_i_inum2big (-zz);
8786 }
8787 else if (SCM_BIGP (z))
8788 {
8789 int sgn = mpz_sgn (SCM_I_BIG_MPZ (z));
8790 scm_remember_upto_here_1 (z);
8791 if (sgn < 0)
8792 return scm_i_clonebig (z, 0);
8793 else
8794 return z;
8795 }
8796 else if (SCM_REALP (z))
8797 return scm_from_double (fabs (SCM_REAL_VALUE (z)));
8798 else if (SCM_COMPLEXP (z))
8799 return scm_from_double (hypot (SCM_COMPLEX_REAL (z), SCM_COMPLEX_IMAG (z)));
8800 else if (SCM_FRACTIONP (z))
8801 {
8802 if (scm_is_false (scm_negative_p (SCM_FRACTION_NUMERATOR (z))))
8803 return z;
8804 return scm_i_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (z), SCM_UNDEFINED),
8805 SCM_FRACTION_DENOMINATOR (z));
8806 }
8807 else
8808 SCM_WTA_DISPATCH_1 (g_scm_magnitude, z, SCM_ARG1, s_scm_magnitude);
8809 }
8810 #undef FUNC_NAME
8811
8812
8813 SCM_PRIMITIVE_GENERIC (scm_angle, "angle", 1, 0, 0,
8814 (SCM z),
8815 "Return the angle of the complex number @var{z}.")
8816 #define FUNC_NAME s_scm_angle
8817 {
8818 /* atan(0,-1) is pi and it'd be possible to have that as a constant like
8819 flo0 to save allocating a new flonum with scm_from_double each time.
8820 But if atan2 follows the floating point rounding mode, then the value
8821 is not a constant. Maybe it'd be close enough though. */
8822 if (SCM_I_INUMP (z))
8823 {
8824 if (SCM_I_INUM (z) >= 0)
8825 return flo0;
8826 else
8827 return scm_from_double (atan2 (0.0, -1.0));
8828 }
8829 else if (SCM_BIGP (z))
8830 {
8831 int sgn = mpz_sgn (SCM_I_BIG_MPZ (z));
8832 scm_remember_upto_here_1 (z);
8833 if (sgn < 0)
8834 return scm_from_double (atan2 (0.0, -1.0));
8835 else
8836 return flo0;
8837 }
8838 else if (SCM_REALP (z))
8839 {
8840 if (SCM_REAL_VALUE (z) >= 0)
8841 return flo0;
8842 else
8843 return scm_from_double (atan2 (0.0, -1.0));
8844 }
8845 else if (SCM_COMPLEXP (z))
8846 return scm_from_double (atan2 (SCM_COMPLEX_IMAG (z), SCM_COMPLEX_REAL (z)));
8847 else if (SCM_FRACTIONP (z))
8848 {
8849 if (scm_is_false (scm_negative_p (SCM_FRACTION_NUMERATOR (z))))
8850 return flo0;
8851 else return scm_from_double (atan2 (0.0, -1.0));
8852 }
8853 else
8854 SCM_WTA_DISPATCH_1 (g_scm_angle, z, SCM_ARG1, s_scm_angle);
8855 }
8856 #undef FUNC_NAME
8857
8858
8859 SCM_PRIMITIVE_GENERIC (scm_exact_to_inexact, "exact->inexact", 1, 0, 0,
8860 (SCM z),
8861 "Convert the number @var{z} to its inexact representation.\n")
8862 #define FUNC_NAME s_scm_exact_to_inexact
8863 {
8864 if (SCM_I_INUMP (z))
8865 return scm_from_double ((double) SCM_I_INUM (z));
8866 else if (SCM_BIGP (z))
8867 return scm_from_double (scm_i_big2dbl (z));
8868 else if (SCM_FRACTIONP (z))
8869 return scm_from_double (scm_i_fraction2double (z));
8870 else if (SCM_INEXACTP (z))
8871 return z;
8872 else
8873 SCM_WTA_DISPATCH_1 (g_scm_exact_to_inexact, z, 1, s_scm_exact_to_inexact);
8874 }
8875 #undef FUNC_NAME
8876
8877
8878 SCM_PRIMITIVE_GENERIC (scm_inexact_to_exact, "inexact->exact", 1, 0, 0,
8879 (SCM z),
8880 "Return an exact number that is numerically closest to @var{z}.")
8881 #define FUNC_NAME s_scm_inexact_to_exact
8882 {
8883 if (SCM_I_INUMP (z) || SCM_BIGP (z) || SCM_FRACTIONP (z))
8884 return z;
8885 else
8886 {
8887 double val;
8888
8889 if (SCM_REALP (z))
8890 val = SCM_REAL_VALUE (z);
8891 else if (SCM_COMPLEXP (z) && SCM_COMPLEX_IMAG (z) == 0.0)
8892 val = SCM_COMPLEX_REAL (z);
8893 else
8894 SCM_WTA_DISPATCH_1 (g_scm_inexact_to_exact, z, 1, s_scm_inexact_to_exact);
8895
8896 if (!SCM_LIKELY (DOUBLE_IS_FINITE (val)))
8897 SCM_OUT_OF_RANGE (1, z);
8898 else
8899 {
8900 mpq_t frac;
8901 SCM q;
8902
8903 mpq_init (frac);
8904 mpq_set_d (frac, val);
8905 q = scm_i_make_ratio (scm_i_mpz2num (mpq_numref (frac)),
8906 scm_i_mpz2num (mpq_denref (frac)));
8907
8908 /* When scm_i_make_ratio throws, we leak the memory allocated
8909 for frac...
8910 */
8911 mpq_clear (frac);
8912 return q;
8913 }
8914 }
8915 }
8916 #undef FUNC_NAME
8917
8918 SCM_DEFINE (scm_rationalize, "rationalize", 2, 0, 0,
8919 (SCM x, SCM eps),
8920 "Returns the @emph{simplest} rational number differing\n"
8921 "from @var{x} by no more than @var{eps}.\n"
8922 "\n"
8923 "As required by @acronym{R5RS}, @code{rationalize} only returns an\n"
8924 "exact result when both its arguments are exact. Thus, you might need\n"
8925 "to use @code{inexact->exact} on the arguments.\n"
8926 "\n"
8927 "@lisp\n"
8928 "(rationalize (inexact->exact 1.2) 1/100)\n"
8929 "@result{} 6/5\n"
8930 "@end lisp")
8931 #define FUNC_NAME s_scm_rationalize
8932 {
8933 SCM_ASSERT_TYPE (scm_is_real (x), x, SCM_ARG1, FUNC_NAME, "real");
8934 SCM_ASSERT_TYPE (scm_is_real (eps), eps, SCM_ARG2, FUNC_NAME, "real");
8935 eps = scm_abs (eps);
8936 if (scm_is_false (scm_positive_p (eps)))
8937 {
8938 /* eps is either zero or a NaN */
8939 if (scm_is_true (scm_nan_p (eps)))
8940 return scm_nan ();
8941 else if (SCM_INEXACTP (eps))
8942 return scm_exact_to_inexact (x);
8943 else
8944 return x;
8945 }
8946 else if (scm_is_false (scm_finite_p (eps)))
8947 {
8948 if (scm_is_true (scm_finite_p (x)))
8949 return flo0;
8950 else
8951 return scm_nan ();
8952 }
8953 else if (scm_is_false (scm_finite_p (x))) /* checks for both inf and nan */
8954 return x;
8955 else if (scm_is_false (scm_less_p (scm_floor (scm_sum (x, eps)),
8956 scm_ceiling (scm_difference (x, eps)))))
8957 {
8958 /* There's an integer within range; we want the one closest to zero */
8959 if (scm_is_false (scm_less_p (eps, scm_abs (x))))
8960 {
8961 /* zero is within range */
8962 if (SCM_INEXACTP (x) || SCM_INEXACTP (eps))
8963 return flo0;
8964 else
8965 return SCM_INUM0;
8966 }
8967 else if (scm_is_true (scm_positive_p (x)))
8968 return scm_ceiling (scm_difference (x, eps));
8969 else
8970 return scm_floor (scm_sum (x, eps));
8971 }
8972 else
8973 {
8974 /* Use continued fractions to find closest ratio. All
8975 arithmetic is done with exact numbers.
8976 */
8977
8978 SCM ex = scm_inexact_to_exact (x);
8979 SCM int_part = scm_floor (ex);
8980 SCM tt = SCM_INUM1;
8981 SCM a1 = SCM_INUM0, a2 = SCM_INUM1, a = SCM_INUM0;
8982 SCM b1 = SCM_INUM1, b2 = SCM_INUM0, b = SCM_INUM0;
8983 SCM rx;
8984 int i = 0;
8985
8986 ex = scm_difference (ex, int_part); /* x = x-int_part */
8987 rx = scm_divide (ex, SCM_UNDEFINED); /* rx = 1/x */
8988
8989 /* We stop after a million iterations just to be absolutely sure
8990 that we don't go into an infinite loop. The process normally
8991 converges after less than a dozen iterations.
8992 */
8993
8994 while (++i < 1000000)
8995 {
8996 a = scm_sum (scm_product (a1, tt), a2); /* a = a1*tt + a2 */
8997 b = scm_sum (scm_product (b1, tt), b2); /* b = b1*tt + b2 */
8998 if (scm_is_false (scm_zero_p (b)) && /* b != 0 */
8999 scm_is_false
9000 (scm_gr_p (scm_abs (scm_difference (ex, scm_divide (a, b))),
9001 eps))) /* abs(x-a/b) <= eps */
9002 {
9003 SCM res = scm_sum (int_part, scm_divide (a, b));
9004 if (SCM_INEXACTP (x) || SCM_INEXACTP (eps))
9005 return scm_exact_to_inexact (res);
9006 else
9007 return res;
9008 }
9009 rx = scm_divide (scm_difference (rx, tt), /* rx = 1/(rx - tt) */
9010 SCM_UNDEFINED);
9011 tt = scm_floor (rx); /* tt = floor (rx) */
9012 a2 = a1;
9013 b2 = b1;
9014 a1 = a;
9015 b1 = b;
9016 }
9017 scm_num_overflow (s_scm_rationalize);
9018 }
9019 }
9020 #undef FUNC_NAME
9021
9022 /* conversion functions */
9023
9024 int
9025 scm_is_integer (SCM val)
9026 {
9027 return scm_is_true (scm_integer_p (val));
9028 }
9029
9030 int
9031 scm_is_signed_integer (SCM val, scm_t_intmax min, scm_t_intmax max)
9032 {
9033 if (SCM_I_INUMP (val))
9034 {
9035 scm_t_signed_bits n = SCM_I_INUM (val);
9036 return n >= min && n <= max;
9037 }
9038 else if (SCM_BIGP (val))
9039 {
9040 if (min >= SCM_MOST_NEGATIVE_FIXNUM && max <= SCM_MOST_POSITIVE_FIXNUM)
9041 return 0;
9042 else if (min >= LONG_MIN && max <= LONG_MAX)
9043 {
9044 if (mpz_fits_slong_p (SCM_I_BIG_MPZ (val)))
9045 {
9046 long n = mpz_get_si (SCM_I_BIG_MPZ (val));
9047 return n >= min && n <= max;
9048 }
9049 else
9050 return 0;
9051 }
9052 else
9053 {
9054 scm_t_intmax n;
9055 size_t count;
9056
9057 if (mpz_sizeinbase (SCM_I_BIG_MPZ (val), 2)
9058 > CHAR_BIT*sizeof (scm_t_uintmax))
9059 return 0;
9060
9061 mpz_export (&n, &count, 1, sizeof (scm_t_uintmax), 0, 0,
9062 SCM_I_BIG_MPZ (val));
9063
9064 if (mpz_sgn (SCM_I_BIG_MPZ (val)) >= 0)
9065 {
9066 if (n < 0)
9067 return 0;
9068 }
9069 else
9070 {
9071 n = -n;
9072 if (n >= 0)
9073 return 0;
9074 }
9075
9076 return n >= min && n <= max;
9077 }
9078 }
9079 else
9080 return 0;
9081 }
9082
9083 int
9084 scm_is_unsigned_integer (SCM val, scm_t_uintmax min, scm_t_uintmax max)
9085 {
9086 if (SCM_I_INUMP (val))
9087 {
9088 scm_t_signed_bits n = SCM_I_INUM (val);
9089 return n >= 0 && ((scm_t_uintmax)n) >= min && ((scm_t_uintmax)n) <= max;
9090 }
9091 else if (SCM_BIGP (val))
9092 {
9093 if (max <= SCM_MOST_POSITIVE_FIXNUM)
9094 return 0;
9095 else if (max <= ULONG_MAX)
9096 {
9097 if (mpz_fits_ulong_p (SCM_I_BIG_MPZ (val)))
9098 {
9099 unsigned long n = mpz_get_ui (SCM_I_BIG_MPZ (val));
9100 return n >= min && n <= max;
9101 }
9102 else
9103 return 0;
9104 }
9105 else
9106 {
9107 scm_t_uintmax n;
9108 size_t count;
9109
9110 if (mpz_sgn (SCM_I_BIG_MPZ (val)) < 0)
9111 return 0;
9112
9113 if (mpz_sizeinbase (SCM_I_BIG_MPZ (val), 2)
9114 > CHAR_BIT*sizeof (scm_t_uintmax))
9115 return 0;
9116
9117 mpz_export (&n, &count, 1, sizeof (scm_t_uintmax), 0, 0,
9118 SCM_I_BIG_MPZ (val));
9119
9120 return n >= min && n <= max;
9121 }
9122 }
9123 else
9124 return 0;
9125 }
9126
9127 static void
9128 scm_i_range_error (SCM bad_val, SCM min, SCM max)
9129 {
9130 scm_error (scm_out_of_range_key,
9131 NULL,
9132 "Value out of range ~S to ~S: ~S",
9133 scm_list_3 (min, max, bad_val),
9134 scm_list_1 (bad_val));
9135 }
9136
9137 #define TYPE scm_t_intmax
9138 #define TYPE_MIN min
9139 #define TYPE_MAX max
9140 #define SIZEOF_TYPE 0
9141 #define SCM_TO_TYPE_PROTO(arg) scm_to_signed_integer (arg, scm_t_intmax min, scm_t_intmax max)
9142 #define SCM_FROM_TYPE_PROTO(arg) scm_from_signed_integer (arg)
9143 #include "libguile/conv-integer.i.c"
9144
9145 #define TYPE scm_t_uintmax
9146 #define TYPE_MIN min
9147 #define TYPE_MAX max
9148 #define SIZEOF_TYPE 0
9149 #define SCM_TO_TYPE_PROTO(arg) scm_to_unsigned_integer (arg, scm_t_uintmax min, scm_t_uintmax max)
9150 #define SCM_FROM_TYPE_PROTO(arg) scm_from_unsigned_integer (arg)
9151 #include "libguile/conv-uinteger.i.c"
9152
9153 #define TYPE scm_t_int8
9154 #define TYPE_MIN SCM_T_INT8_MIN
9155 #define TYPE_MAX SCM_T_INT8_MAX
9156 #define SIZEOF_TYPE 1
9157 #define SCM_TO_TYPE_PROTO(arg) scm_to_int8 (arg)
9158 #define SCM_FROM_TYPE_PROTO(arg) scm_from_int8 (arg)
9159 #include "libguile/conv-integer.i.c"
9160
9161 #define TYPE scm_t_uint8
9162 #define TYPE_MIN 0
9163 #define TYPE_MAX SCM_T_UINT8_MAX
9164 #define SIZEOF_TYPE 1
9165 #define SCM_TO_TYPE_PROTO(arg) scm_to_uint8 (arg)
9166 #define SCM_FROM_TYPE_PROTO(arg) scm_from_uint8 (arg)
9167 #include "libguile/conv-uinteger.i.c"
9168
9169 #define TYPE scm_t_int16
9170 #define TYPE_MIN SCM_T_INT16_MIN
9171 #define TYPE_MAX SCM_T_INT16_MAX
9172 #define SIZEOF_TYPE 2
9173 #define SCM_TO_TYPE_PROTO(arg) scm_to_int16 (arg)
9174 #define SCM_FROM_TYPE_PROTO(arg) scm_from_int16 (arg)
9175 #include "libguile/conv-integer.i.c"
9176
9177 #define TYPE scm_t_uint16
9178 #define TYPE_MIN 0
9179 #define TYPE_MAX SCM_T_UINT16_MAX
9180 #define SIZEOF_TYPE 2
9181 #define SCM_TO_TYPE_PROTO(arg) scm_to_uint16 (arg)
9182 #define SCM_FROM_TYPE_PROTO(arg) scm_from_uint16 (arg)
9183 #include "libguile/conv-uinteger.i.c"
9184
9185 #define TYPE scm_t_int32
9186 #define TYPE_MIN SCM_T_INT32_MIN
9187 #define TYPE_MAX SCM_T_INT32_MAX
9188 #define SIZEOF_TYPE 4
9189 #define SCM_TO_TYPE_PROTO(arg) scm_to_int32 (arg)
9190 #define SCM_FROM_TYPE_PROTO(arg) scm_from_int32 (arg)
9191 #include "libguile/conv-integer.i.c"
9192
9193 #define TYPE scm_t_uint32
9194 #define TYPE_MIN 0
9195 #define TYPE_MAX SCM_T_UINT32_MAX
9196 #define SIZEOF_TYPE 4
9197 #define SCM_TO_TYPE_PROTO(arg) scm_to_uint32 (arg)
9198 #define SCM_FROM_TYPE_PROTO(arg) scm_from_uint32 (arg)
9199 #include "libguile/conv-uinteger.i.c"
9200
9201 #define TYPE scm_t_wchar
9202 #define TYPE_MIN (scm_t_int32)-1
9203 #define TYPE_MAX (scm_t_int32)0x10ffff
9204 #define SIZEOF_TYPE 4
9205 #define SCM_TO_TYPE_PROTO(arg) scm_to_wchar (arg)
9206 #define SCM_FROM_TYPE_PROTO(arg) scm_from_wchar (arg)
9207 #include "libguile/conv-integer.i.c"
9208
9209 #define TYPE scm_t_int64
9210 #define TYPE_MIN SCM_T_INT64_MIN
9211 #define TYPE_MAX SCM_T_INT64_MAX
9212 #define SIZEOF_TYPE 8
9213 #define SCM_TO_TYPE_PROTO(arg) scm_to_int64 (arg)
9214 #define SCM_FROM_TYPE_PROTO(arg) scm_from_int64 (arg)
9215 #include "libguile/conv-integer.i.c"
9216
9217 #define TYPE scm_t_uint64
9218 #define TYPE_MIN 0
9219 #define TYPE_MAX SCM_T_UINT64_MAX
9220 #define SIZEOF_TYPE 8
9221 #define SCM_TO_TYPE_PROTO(arg) scm_to_uint64 (arg)
9222 #define SCM_FROM_TYPE_PROTO(arg) scm_from_uint64 (arg)
9223 #include "libguile/conv-uinteger.i.c"
9224
9225 void
9226 scm_to_mpz (SCM val, mpz_t rop)
9227 {
9228 if (SCM_I_INUMP (val))
9229 mpz_set_si (rop, SCM_I_INUM (val));
9230 else if (SCM_BIGP (val))
9231 mpz_set (rop, SCM_I_BIG_MPZ (val));
9232 else
9233 scm_wrong_type_arg_msg (NULL, 0, val, "exact integer");
9234 }
9235
9236 SCM
9237 scm_from_mpz (mpz_t val)
9238 {
9239 return scm_i_mpz2num (val);
9240 }
9241
9242 int
9243 scm_is_real (SCM val)
9244 {
9245 return scm_is_true (scm_real_p (val));
9246 }
9247
9248 int
9249 scm_is_rational (SCM val)
9250 {
9251 return scm_is_true (scm_rational_p (val));
9252 }
9253
9254 double
9255 scm_to_double (SCM val)
9256 {
9257 if (SCM_I_INUMP (val))
9258 return SCM_I_INUM (val);
9259 else if (SCM_BIGP (val))
9260 return scm_i_big2dbl (val);
9261 else if (SCM_FRACTIONP (val))
9262 return scm_i_fraction2double (val);
9263 else if (SCM_REALP (val))
9264 return SCM_REAL_VALUE (val);
9265 else
9266 scm_wrong_type_arg_msg (NULL, 0, val, "real number");
9267 }
9268
9269 SCM
9270 scm_from_double (double val)
9271 {
9272 SCM z;
9273
9274 z = PTR2SCM (scm_gc_malloc_pointerless (sizeof (scm_t_double), "real"));
9275
9276 SCM_SET_CELL_TYPE (z, scm_tc16_real);
9277 SCM_REAL_VALUE (z) = val;
9278
9279 return z;
9280 }
9281
9282 #if SCM_ENABLE_DEPRECATED == 1
9283
9284 float
9285 scm_num2float (SCM num, unsigned long pos, const char *s_caller)
9286 {
9287 scm_c_issue_deprecation_warning
9288 ("`scm_num2float' is deprecated. Use scm_to_double instead.");
9289
9290 if (SCM_BIGP (num))
9291 {
9292 float res = mpz_get_d (SCM_I_BIG_MPZ (num));
9293 if (!isinf (res))
9294 return res;
9295 else
9296 scm_out_of_range (NULL, num);
9297 }
9298 else
9299 return scm_to_double (num);
9300 }
9301
9302 double
9303 scm_num2double (SCM num, unsigned long pos, const char *s_caller)
9304 {
9305 scm_c_issue_deprecation_warning
9306 ("`scm_num2double' is deprecated. Use scm_to_double instead.");
9307
9308 if (SCM_BIGP (num))
9309 {
9310 double res = mpz_get_d (SCM_I_BIG_MPZ (num));
9311 if (!isinf (res))
9312 return res;
9313 else
9314 scm_out_of_range (NULL, num);
9315 }
9316 else
9317 return scm_to_double (num);
9318 }
9319
9320 #endif
9321
9322 int
9323 scm_is_complex (SCM val)
9324 {
9325 return scm_is_true (scm_complex_p (val));
9326 }
9327
9328 double
9329 scm_c_real_part (SCM z)
9330 {
9331 if (SCM_COMPLEXP (z))
9332 return SCM_COMPLEX_REAL (z);
9333 else
9334 {
9335 /* Use the scm_real_part to get proper error checking and
9336 dispatching.
9337 */
9338 return scm_to_double (scm_real_part (z));
9339 }
9340 }
9341
9342 double
9343 scm_c_imag_part (SCM z)
9344 {
9345 if (SCM_COMPLEXP (z))
9346 return SCM_COMPLEX_IMAG (z);
9347 else
9348 {
9349 /* Use the scm_imag_part to get proper error checking and
9350 dispatching. The result will almost always be 0.0, but not
9351 always.
9352 */
9353 return scm_to_double (scm_imag_part (z));
9354 }
9355 }
9356
9357 double
9358 scm_c_magnitude (SCM z)
9359 {
9360 return scm_to_double (scm_magnitude (z));
9361 }
9362
9363 double
9364 scm_c_angle (SCM z)
9365 {
9366 return scm_to_double (scm_angle (z));
9367 }
9368
9369 int
9370 scm_is_number (SCM z)
9371 {
9372 return scm_is_true (scm_number_p (z));
9373 }
9374
9375
9376 /* Returns log(x * 2^shift) */
9377 static SCM
9378 log_of_shifted_double (double x, long shift)
9379 {
9380 double ans = log (fabs (x)) + shift * M_LN2;
9381
9382 if (x > 0.0 || double_is_non_negative_zero (x))
9383 return scm_from_double (ans);
9384 else
9385 return scm_c_make_rectangular (ans, M_PI);
9386 }
9387
9388 /* Returns log(n), for exact integer n of integer-length size */
9389 static SCM
9390 log_of_exact_integer_with_size (SCM n, long size)
9391 {
9392 long shift = size - 2 * scm_dblprec[0];
9393
9394 if (shift > 0)
9395 return log_of_shifted_double
9396 (scm_to_double (scm_ash (n, scm_from_long(-shift))),
9397 shift);
9398 else
9399 return log_of_shifted_double (scm_to_double (n), 0);
9400 }
9401
9402 /* Returns log(n), for exact integer n of integer-length size */
9403 static SCM
9404 log_of_exact_integer (SCM n)
9405 {
9406 return log_of_exact_integer_with_size
9407 (n, scm_to_long (scm_integer_length (n)));
9408 }
9409
9410 /* Returns log(n/d), for exact non-zero integers n and d */
9411 static SCM
9412 log_of_fraction (SCM n, SCM d)
9413 {
9414 long n_size = scm_to_long (scm_integer_length (n));
9415 long d_size = scm_to_long (scm_integer_length (d));
9416
9417 if (abs (n_size - d_size) > 1)
9418 return (scm_difference (log_of_exact_integer_with_size (n, n_size),
9419 log_of_exact_integer_with_size (d, d_size)));
9420 else if (scm_is_false (scm_negative_p (n)))
9421 return scm_from_double
9422 (log1p (scm_to_double (scm_divide2real (scm_difference (n, d), d))));
9423 else
9424 return scm_c_make_rectangular
9425 (log1p (scm_to_double (scm_divide2real
9426 (scm_difference (scm_abs (n), d),
9427 d))),
9428 M_PI);
9429 }
9430
9431
9432 /* In the following functions we dispatch to the real-arg funcs like log()
9433 when we know the arg is real, instead of just handing everything to
9434 clog() for instance. This is in case clog() doesn't optimize for a
9435 real-only case, and because we have to test SCM_COMPLEXP anyway so may as
9436 well use it to go straight to the applicable C func. */
9437
9438 SCM_PRIMITIVE_GENERIC (scm_log, "log", 1, 0, 0,
9439 (SCM z),
9440 "Return the natural logarithm of @var{z}.")
9441 #define FUNC_NAME s_scm_log
9442 {
9443 if (SCM_COMPLEXP (z))
9444 {
9445 #if HAVE_COMPLEX_DOUBLE && HAVE_CLOG && defined (SCM_COMPLEX_VALUE)
9446 return scm_from_complex_double (clog (SCM_COMPLEX_VALUE (z)));
9447 #else
9448 double re = SCM_COMPLEX_REAL (z);
9449 double im = SCM_COMPLEX_IMAG (z);
9450 return scm_c_make_rectangular (log (hypot (re, im)),
9451 atan2 (im, re));
9452 #endif
9453 }
9454 else if (SCM_REALP (z))
9455 return log_of_shifted_double (SCM_REAL_VALUE (z), 0);
9456 else if (SCM_I_INUMP (z))
9457 {
9458 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
9459 if (scm_is_eq (z, SCM_INUM0))
9460 scm_num_overflow (s_scm_log);
9461 #endif
9462 return log_of_shifted_double (SCM_I_INUM (z), 0);
9463 }
9464 else if (SCM_BIGP (z))
9465 return log_of_exact_integer (z);
9466 else if (SCM_FRACTIONP (z))
9467 return log_of_fraction (SCM_FRACTION_NUMERATOR (z),
9468 SCM_FRACTION_DENOMINATOR (z));
9469 else
9470 SCM_WTA_DISPATCH_1 (g_scm_log, z, 1, s_scm_log);
9471 }
9472 #undef FUNC_NAME
9473
9474
9475 SCM_PRIMITIVE_GENERIC (scm_log10, "log10", 1, 0, 0,
9476 (SCM z),
9477 "Return the base 10 logarithm of @var{z}.")
9478 #define FUNC_NAME s_scm_log10
9479 {
9480 if (SCM_COMPLEXP (z))
9481 {
9482 /* Mingw has clog() but not clog10(). (Maybe it'd be worth using
9483 clog() and a multiply by M_LOG10E, rather than the fallback
9484 log10+hypot+atan2.) */
9485 #if defined HAVE_COMPLEX_DOUBLE && defined HAVE_CLOG10 \
9486 && defined SCM_COMPLEX_VALUE
9487 return scm_from_complex_double (clog10 (SCM_COMPLEX_VALUE (z)));
9488 #else
9489 double re = SCM_COMPLEX_REAL (z);
9490 double im = SCM_COMPLEX_IMAG (z);
9491 return scm_c_make_rectangular (log10 (hypot (re, im)),
9492 M_LOG10E * atan2 (im, re));
9493 #endif
9494 }
9495 else if (SCM_REALP (z) || SCM_I_INUMP (z))
9496 {
9497 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
9498 if (scm_is_eq (z, SCM_INUM0))
9499 scm_num_overflow (s_scm_log10);
9500 #endif
9501 {
9502 double re = scm_to_double (z);
9503 double l = log10 (fabs (re));
9504 if (re > 0.0 || double_is_non_negative_zero (re))
9505 return scm_from_double (l);
9506 else
9507 return scm_c_make_rectangular (l, M_LOG10E * M_PI);
9508 }
9509 }
9510 else if (SCM_BIGP (z))
9511 return scm_product (flo_log10e, log_of_exact_integer (z));
9512 else if (SCM_FRACTIONP (z))
9513 return scm_product (flo_log10e,
9514 log_of_fraction (SCM_FRACTION_NUMERATOR (z),
9515 SCM_FRACTION_DENOMINATOR (z)));
9516 else
9517 SCM_WTA_DISPATCH_1 (g_scm_log10, z, 1, s_scm_log10);
9518 }
9519 #undef FUNC_NAME
9520
9521
9522 SCM_PRIMITIVE_GENERIC (scm_exp, "exp", 1, 0, 0,
9523 (SCM z),
9524 "Return @math{e} to the power of @var{z}, where @math{e} is the\n"
9525 "base of natural logarithms (2.71828@dots{}).")
9526 #define FUNC_NAME s_scm_exp
9527 {
9528 if (SCM_COMPLEXP (z))
9529 {
9530 #if HAVE_COMPLEX_DOUBLE && HAVE_CEXP && defined (SCM_COMPLEX_VALUE)
9531 return scm_from_complex_double (cexp (SCM_COMPLEX_VALUE (z)));
9532 #else
9533 return scm_c_make_polar (exp (SCM_COMPLEX_REAL (z)),
9534 SCM_COMPLEX_IMAG (z));
9535 #endif
9536 }
9537 else if (SCM_NUMBERP (z))
9538 {
9539 /* When z is a negative bignum the conversion to double overflows,
9540 giving -infinity, but that's ok, the exp is still 0.0. */
9541 return scm_from_double (exp (scm_to_double (z)));
9542 }
9543 else
9544 SCM_WTA_DISPATCH_1 (g_scm_exp, z, 1, s_scm_exp);
9545 }
9546 #undef FUNC_NAME
9547
9548
9549 SCM_PRIMITIVE_GENERIC (scm_sqrt, "sqrt", 1, 0, 0,
9550 (SCM z),
9551 "Return the square root of @var{z}. Of the two possible roots\n"
9552 "(positive and negative), the one with positive real part\n"
9553 "is returned, or if that's zero then a positive imaginary part.\n"
9554 "Thus,\n"
9555 "\n"
9556 "@example\n"
9557 "(sqrt 9.0) @result{} 3.0\n"
9558 "(sqrt -9.0) @result{} 0.0+3.0i\n"
9559 "(sqrt 1.0+1.0i) @result{} 1.09868411346781+0.455089860562227i\n"
9560 "(sqrt -1.0-1.0i) @result{} 0.455089860562227-1.09868411346781i\n"
9561 "@end example")
9562 #define FUNC_NAME s_scm_sqrt
9563 {
9564 if (SCM_COMPLEXP (z))
9565 {
9566 #if defined HAVE_COMPLEX_DOUBLE && defined HAVE_USABLE_CSQRT \
9567 && defined SCM_COMPLEX_VALUE
9568 return scm_from_complex_double (csqrt (SCM_COMPLEX_VALUE (z)));
9569 #else
9570 double re = SCM_COMPLEX_REAL (z);
9571 double im = SCM_COMPLEX_IMAG (z);
9572 return scm_c_make_polar (sqrt (hypot (re, im)),
9573 0.5 * atan2 (im, re));
9574 #endif
9575 }
9576 else if (SCM_NUMBERP (z))
9577 {
9578 double xx = scm_to_double (z);
9579 if (xx < 0)
9580 return scm_c_make_rectangular (0.0, sqrt (-xx));
9581 else
9582 return scm_from_double (sqrt (xx));
9583 }
9584 else
9585 SCM_WTA_DISPATCH_1 (g_scm_sqrt, z, 1, s_scm_sqrt);
9586 }
9587 #undef FUNC_NAME
9588
9589
9590
9591 void
9592 scm_init_numbers ()
9593 {
9594 int i;
9595
9596 mpz_init_set_si (z_negative_one, -1);
9597
9598 /* It may be possible to tune the performance of some algorithms by using
9599 * the following constants to avoid the creation of bignums. Please, before
9600 * using these values, remember the two rules of program optimization:
9601 * 1st Rule: Don't do it. 2nd Rule (experts only): Don't do it yet. */
9602 scm_c_define ("most-positive-fixnum",
9603 SCM_I_MAKINUM (SCM_MOST_POSITIVE_FIXNUM));
9604 scm_c_define ("most-negative-fixnum",
9605 SCM_I_MAKINUM (SCM_MOST_NEGATIVE_FIXNUM));
9606
9607 scm_add_feature ("complex");
9608 scm_add_feature ("inexact");
9609 flo0 = scm_from_double (0.0);
9610 flo_log10e = scm_from_double (M_LOG10E);
9611
9612 /* determine floating point precision */
9613 for (i=2; i <= SCM_MAX_DBL_RADIX; ++i)
9614 {
9615 init_dblprec(&scm_dblprec[i-2],i);
9616 init_fx_radix(fx_per_radix[i-2],i);
9617 }
9618 #ifdef DBL_DIG
9619 /* hard code precision for base 10 if the preprocessor tells us to... */
9620 scm_dblprec[10-2] = (DBL_DIG > 20) ? 20 : DBL_DIG;
9621 #endif
9622
9623 exactly_one_half = scm_divide (SCM_INUM1, SCM_I_MAKINUM (2));
9624 #include "libguile/numbers.x"
9625 }
9626
9627 /*
9628 Local Variables:
9629 c-file-style: "gnu"
9630 End:
9631 */