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