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