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