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