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