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