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