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