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