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