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