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