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