* numbers.c (scm_make_ratio): Rewritten to have a simpler
[bpt/guile.git] / libguile / numbers.c
1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003 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
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 \f
23 /* General assumptions:
24 * All objects satisfying SCM_COMPLEXP() have a non-zero complex component.
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 * All objects satisfying SCM_FRACTIONP are never an integer.
29 */
30
31 /* TODO:
32
33 - see if special casing bignums and reals in integer-exponent when
34 possible (to use mpz_pow and mpf_pow_ui) is faster.
35
36 - look in to better short-circuiting of common cases in
37 integer-expt and elsewhere.
38
39 - see if direct mpz operations can help in ash and elsewhere.
40
41 */
42
43 /* tell glibc (2.3) to give prototype for C99 trunc() */
44 #define _GNU_SOURCE
45
46 #if HAVE_CONFIG_H
47 # include <config.h>
48 #endif
49
50 #include <math.h>
51 #include <ctype.h>
52 #include <string.h>
53 #include <gmp.h>
54
55 #include "libguile/_scm.h"
56 #include "libguile/feature.h"
57 #include "libguile/ports.h"
58 #include "libguile/root.h"
59 #include "libguile/smob.h"
60 #include "libguile/strings.h"
61
62 #include "libguile/validate.h"
63 #include "libguile/numbers.h"
64 #include "libguile/deprecation.h"
65
66 #include "libguile/eq.h"
67
68 \f
69
70 /*
71 Wonder if this might be faster for some of our code? A switch on
72 the numtag would jump directly to the right case, and the
73 SCM_I_NUMTAG code might be faster than repeated SCM_FOOP tests...
74
75 #define SCM_I_NUMTAG_NOTNUM 0
76 #define SCM_I_NUMTAG_INUM 1
77 #define SCM_I_NUMTAG_BIG scm_tc16_big
78 #define SCM_I_NUMTAG_REAL scm_tc16_real
79 #define SCM_I_NUMTAG_COMPLEX scm_tc16_complex
80 #define SCM_I_NUMTAG(x) \
81 (SCM_INUMP(x) ? SCM_I_NUMTAG_INUM \
82 : (SCM_IMP(x) ? SCM_I_NUMTAG_NOTNUM \
83 : (((0xfcff & SCM_CELL_TYPE (x)) == scm_tc7_number) ? SCM_TYP16(x) \
84 : SCM_I_NUMTAG_NOTNUM)))
85 */
86 /* the macro above will not work as is with fractions */
87
88
89 #define SCM_SWAP(x, y) do { SCM __t = x; x = y; y = __t; } while (0)
90
91 /* FLOBUFLEN is the maximum number of characters neccessary for the
92 * printed or scm_string representation of an inexact number.
93 */
94 #define FLOBUFLEN (10+2*(sizeof(double)/sizeof(char)*SCM_CHAR_BIT*3+9)/10)
95
96 #if defined (SCO)
97 #if ! defined (HAVE_ISNAN)
98 #define HAVE_ISNAN
99 static int
100 isnan (double x)
101 {
102 return (IsNANorINF (x) && NaN (x) && ! IsINF (x)) ? 1 : 0;
103 }
104 #endif
105 #if ! defined (HAVE_ISINF)
106 #define HAVE_ISINF
107 static int
108 isinf (double x)
109 {
110 return (IsNANorINF (x) && IsINF (x)) ? 1 : 0;
111 }
112
113 #endif
114 #endif
115
116
117 /* mpz_cmp_d only recognises infinities in gmp 4.2 and up.
118 For prior versions use an explicit check here. */
119 #if __GNU_MP_VERSION < 4 \
120 || (__GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR < 2)
121 #define xmpz_cmp_d(z, d) \
122 (xisinf (d) ? (d < 0.0 ? 1 : -1) : mpz_cmp_d (z, d))
123 #else
124 #define xmpz_cmp_d(z, d) mpz_cmp_d (z, d)
125 #endif
126
127 static int
128 xisinf (double x)
129 {
130 #if defined (HAVE_ISINF)
131 return isinf (x);
132 #elif defined (HAVE_FINITE) && defined (HAVE_ISNAN)
133 return (! (finite (x) || isnan (x)));
134 #else
135 return 0;
136 #endif
137 }
138
139 static int
140 xisnan (double x)
141 {
142 #if defined (HAVE_ISNAN)
143 return isnan (x);
144 #else
145 return 0;
146 #endif
147 }
148
149 \f
150
151 static SCM abs_most_negative_fixnum;
152 static mpz_t z_negative_one;
153
154 \f
155
156 static const char s_bignum[] = "bignum";
157
158 SCM_C_INLINE_KEYWORD SCM
159 scm_i_mkbig ()
160 {
161 /* Return a newly created bignum. */
162 SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
163 mpz_init (SCM_I_BIG_MPZ (z));
164 return z;
165 }
166
167 SCM_C_INLINE_KEYWORD static SCM
168 scm_i_clonebig (SCM src_big, int same_sign_p)
169 {
170 /* Copy src_big's value, negate it if same_sign_p is false, and return. */
171 SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
172 mpz_init_set (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (src_big));
173 if (!same_sign_p)
174 mpz_neg (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (z));
175 return z;
176 }
177
178 SCM_C_INLINE_KEYWORD int
179 scm_i_bigcmp (SCM x, SCM y)
180 {
181 /* Return neg if x < y, pos if x > y, and 0 if x == y */
182 /* presume we already know x and y are bignums */
183 int result = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
184 scm_remember_upto_here_2 (x, y);
185 return result;
186 }
187
188 SCM_C_INLINE_KEYWORD SCM
189 scm_i_dbl2big (double d)
190 {
191 /* results are only defined if d is an integer */
192 SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
193 mpz_init_set_d (SCM_I_BIG_MPZ (z), d);
194 return z;
195 }
196
197 /* Convert a integer in double representation to a SCM number. */
198
199 SCM_C_INLINE_KEYWORD SCM
200 scm_i_dbl2num (double u)
201 {
202 /* SCM_MOST_POSITIVE_FIXNUM+1 and SCM_MOST_NEGATIVE_FIXNUM are both
203 powers of 2, so there's no rounding when making "double" values
204 from them. If plain SCM_MOST_POSITIVE_FIXNUM was used it could
205 get rounded on a 64-bit machine, hence the "+1".
206
207 The use of floor() to force to an integer value ensures we get a
208 "numerically closest" value without depending on how a
209 double->long cast or how mpz_set_d will round. For reference,
210 double->long probably follows the hardware rounding mode,
211 mpz_set_d truncates towards zero. */
212
213 /* XXX - what happens when SCM_MOST_POSITIVE_FIXNUM etc is not
214 representable as a double? */
215
216 if (u < (double) (SCM_MOST_POSITIVE_FIXNUM+1)
217 && u >= (double) SCM_MOST_NEGATIVE_FIXNUM)
218 return SCM_MAKINUM ((long) u);
219 else
220 return scm_i_dbl2big (u);
221 }
222
223 /* scm_i_big2dbl() rounds to the closest representable double, in accordance
224 with R5RS exact->inexact.
225
226 The approach is to use mpz_get_d to pick out the high DBL_MANT_DIG bits
227 (ie. it truncates towards zero), then adjust to get the closest double by
228 examining the next lower bit and adding 1 if necessary.
229
230 Note that bignums exactly half way between representable doubles are
231 rounded to the next higher absolute value (ie. away from zero). This
232 seems like an adequate interpretation of R5RS "numerically closest", and
233 it's easier and faster than a full "nearest-even" style.
234
235 The bit test is done on the absolute value of the mpz_t, which means we
236 must use mpz_getlimbn. mpz_tstbit is not right, it treats negatives as
237 twos complement.
238
239 Prior to GMP 4.2, the rounding done by mpz_get_d was unspecified. It
240 happened to follow the hardware rounding mode, but on the absolute value
241 of its operand. This is not what we want, so we put the high
242 DBL_MANT_DIG bits into a temporary. This extra init/clear is a slowdown,
243 but doesn't matter too much since it's only for older GMP. */
244
245 double
246 scm_i_big2dbl (SCM b)
247 {
248 double result;
249 size_t bits;
250
251 bits = mpz_sizeinbase (SCM_I_BIG_MPZ (b), 2);
252
253 #if __GNU_MP_VERSION < 4 \
254 || (__GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR < 2)
255 {
256 /* GMP prior to 4.2, force truncate towards zero */
257 mpz_t tmp;
258 if (bits > DBL_MANT_DIG)
259 {
260 size_t shift = bits - DBL_MANT_DIG;
261 mpz_init2 (tmp, DBL_MANT_DIG);
262 mpz_tdiv_q_2exp (tmp, SCM_I_BIG_MPZ (b), shift);
263 result = ldexp (mpz_get_d (tmp), shift);
264 mpz_clear (tmp);
265 }
266 else
267 {
268 result = mpz_get_d (SCM_I_BIG_MPZ (b));
269 }
270 }
271 #else
272 /* GMP 4.2 and up */
273 result = mpz_get_d (SCM_I_BIG_MPZ (b));
274 #endif
275
276 if (bits > DBL_MANT_DIG)
277 {
278 unsigned long pos = bits - DBL_MANT_DIG - 1;
279 /* test bit number "pos" in absolute value */
280 if (mpz_getlimbn (SCM_I_BIG_MPZ (b), pos / GMP_NUMB_BITS)
281 & ((mp_limb_t) 1 << (pos % GMP_NUMB_BITS)))
282 {
283 result += ldexp ((double) mpz_sgn (SCM_I_BIG_MPZ (b)), pos + 1);
284 }
285 }
286
287 scm_remember_upto_here_1 (b);
288 return result;
289 }
290
291 SCM_C_INLINE_KEYWORD SCM
292 scm_i_normbig (SCM b)
293 {
294 /* convert a big back to a fixnum if it'll fit */
295 /* presume b is a bignum */
296 if (mpz_fits_slong_p (SCM_I_BIG_MPZ (b)))
297 {
298 long val = mpz_get_si (SCM_I_BIG_MPZ (b));
299 if (SCM_FIXABLE (val))
300 b = SCM_MAKINUM (val);
301 }
302 return b;
303 }
304
305 static SCM_C_INLINE_KEYWORD SCM
306 scm_i_mpz2num (mpz_t b)
307 {
308 /* convert a mpz number to a SCM number. */
309 if (mpz_fits_slong_p (b))
310 {
311 long val = mpz_get_si (b);
312 if (SCM_FIXABLE (val))
313 return SCM_MAKINUM (val);
314 }
315
316 {
317 SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
318 mpz_init_set (SCM_I_BIG_MPZ (z), b);
319 return z;
320 }
321 }
322
323 /* this is needed when we want scm_divide to make a float, not a ratio, even if passed two ints */
324 static SCM scm_divide2real (SCM x, SCM y);
325
326 SCM
327 scm_make_ratio (SCM numerator, SCM denominator)
328 #define FUNC_NAME "make-ratio"
329 {
330 /* First make sure the arguments are proper.
331 */
332 if (SCM_INUMP (denominator))
333 {
334 if (SCM_EQ_P (denominator, SCM_INUM0))
335 scm_num_overflow ("make-ratio");
336 if (SCM_EQ_P (denominator, SCM_MAKINUM(1)))
337 return numerator;
338 }
339 else
340 {
341 if (!(SCM_BIGP(denominator)))
342 SCM_WRONG_TYPE_ARG (2, denominator);
343 }
344 if (!SCM_INUMP (numerator) && !SCM_BIGP (numerator))
345 SCM_WRONG_TYPE_ARG (1, numerator);
346
347 /* Then flip signs so that the denominator is positive.
348 */
349 if (SCM_NFALSEP (scm_negative_p (denominator)))
350 {
351 numerator = scm_difference (numerator, SCM_UNDEFINED);
352 denominator = scm_difference (denominator, SCM_UNDEFINED);
353 }
354
355 /* Now consider for each of the four fixnum/bignum combinations
356 whether the rational number is really an integer.
357 */
358 if (SCM_INUMP (numerator))
359 {
360 if (SCM_EQ_P (numerator, SCM_INUM0))
361 return SCM_INUM0;
362 if (SCM_INUMP (denominator))
363 {
364 long x, y;
365 x = SCM_INUM (numerator);
366 y = SCM_INUM (denominator);
367 if (x == y)
368 return SCM_MAKINUM(1);
369 if ((x % y) == 0)
370 return SCM_MAKINUM (x / y);
371 }
372 }
373 else if (SCM_BIGP (numerator))
374 {
375 if (SCM_INUMP (denominator))
376 {
377 long yy = SCM_INUM (denominator);
378 if (mpz_divisible_ui_p (SCM_I_BIG_MPZ (numerator), yy))
379 return scm_divide (numerator, denominator);
380 }
381 else
382 {
383 if (SCM_EQ_P (numerator, denominator))
384 return SCM_MAKINUM(1);
385 if (mpz_divisible_p (SCM_I_BIG_MPZ (numerator),
386 SCM_I_BIG_MPZ (denominator)))
387 return scm_divide(numerator, denominator);
388 }
389 }
390
391 /* No, it's a proper fraction.
392 */
393 return scm_double_cell (scm_tc16_fraction,
394 SCM_UNPACK (numerator),
395 SCM_UNPACK (denominator), 0);
396 }
397 #undef FUNC_NAME
398
399 static void scm_i_fraction_reduce (SCM z)
400 {
401 if (!(SCM_FRACTION_REDUCED (z)))
402 {
403 SCM divisor;
404 divisor = scm_gcd (SCM_FRACTION_NUMERATOR (z), SCM_FRACTION_DENOMINATOR (z));
405 if (!(SCM_EQ_P (divisor, SCM_MAKINUM(1))))
406 {
407 /* is this safe? */
408 SCM_FRACTION_SET_NUMERATOR (z, scm_divide (SCM_FRACTION_NUMERATOR (z), divisor));
409 SCM_FRACTION_SET_DENOMINATOR (z, scm_divide (SCM_FRACTION_DENOMINATOR (z), divisor));
410 }
411 SCM_FRACTION_REDUCED_SET (z);
412 }
413 }
414
415 double
416 scm_i_fraction2double (SCM z)
417 {
418 return scm_num2dbl (scm_divide2real (SCM_FRACTION_NUMERATOR (z),
419 SCM_FRACTION_DENOMINATOR (z)),
420 "fraction2real");
421 }
422
423 SCM_DEFINE (scm_exact_p, "exact?", 1, 0, 0,
424 (SCM x),
425 "Return @code{#t} if @var{x} is an exact number, @code{#f}\n"
426 "otherwise.")
427 #define FUNC_NAME s_scm_exact_p
428 {
429 if (SCM_INUMP (x))
430 return SCM_BOOL_T;
431 if (SCM_BIGP (x))
432 return SCM_BOOL_T;
433 if (SCM_FRACTIONP (x))
434 return SCM_BOOL_T;
435 if (SCM_NUMBERP (x))
436 return SCM_BOOL_F;
437 SCM_WRONG_TYPE_ARG (1, x);
438 }
439 #undef FUNC_NAME
440
441
442 SCM_DEFINE (scm_odd_p, "odd?", 1, 0, 0,
443 (SCM n),
444 "Return @code{#t} if @var{n} is an odd number, @code{#f}\n"
445 "otherwise.")
446 #define FUNC_NAME s_scm_odd_p
447 {
448 if (SCM_INUMP (n))
449 {
450 long val = SCM_INUM (n);
451 return SCM_BOOL ((val & 1L) != 0);
452 }
453 else if (SCM_BIGP (n))
454 {
455 int odd_p = mpz_odd_p (SCM_I_BIG_MPZ (n));
456 scm_remember_upto_here_1 (n);
457 return SCM_BOOL (odd_p);
458 }
459 else if (!SCM_FALSEP (scm_inf_p (n)))
460 return SCM_BOOL_T;
461 else if (SCM_REALP (n))
462 {
463 double rem = fabs (fmod (SCM_REAL_VALUE(n), 2.0));
464 if (rem == 1.0)
465 return SCM_BOOL_T;
466 else if (rem == 0.0)
467 return SCM_BOOL_F;
468 else
469 SCM_WRONG_TYPE_ARG (1, n);
470 }
471 else
472 SCM_WRONG_TYPE_ARG (1, n);
473 }
474 #undef FUNC_NAME
475
476
477 SCM_DEFINE (scm_even_p, "even?", 1, 0, 0,
478 (SCM n),
479 "Return @code{#t} if @var{n} is an even number, @code{#f}\n"
480 "otherwise.")
481 #define FUNC_NAME s_scm_even_p
482 {
483 if (SCM_INUMP (n))
484 {
485 long val = SCM_INUM (n);
486 return SCM_BOOL ((val & 1L) == 0);
487 }
488 else if (SCM_BIGP (n))
489 {
490 int even_p = mpz_even_p (SCM_I_BIG_MPZ (n));
491 scm_remember_upto_here_1 (n);
492 return SCM_BOOL (even_p);
493 }
494 else if (!SCM_FALSEP (scm_inf_p (n)))
495 return SCM_BOOL_T;
496 else if (SCM_REALP (n))
497 {
498 double rem = fabs (fmod (SCM_REAL_VALUE(n), 2.0));
499 if (rem == 1.0)
500 return SCM_BOOL_F;
501 else if (rem == 0.0)
502 return SCM_BOOL_T;
503 else
504 SCM_WRONG_TYPE_ARG (1, n);
505 }
506 else
507 SCM_WRONG_TYPE_ARG (1, n);
508 }
509 #undef FUNC_NAME
510
511 SCM_DEFINE (scm_inf_p, "inf?", 1, 0, 0,
512 (SCM n),
513 "Return @code{#t} if @var{n} is infinite, @code{#f}\n"
514 "otherwise.")
515 #define FUNC_NAME s_scm_inf_p
516 {
517 if (SCM_REALP (n))
518 return SCM_BOOL (xisinf (SCM_REAL_VALUE (n)));
519 else if (SCM_COMPLEXP (n))
520 return SCM_BOOL (xisinf (SCM_COMPLEX_REAL (n))
521 || xisinf (SCM_COMPLEX_IMAG (n)));
522 else
523 return SCM_BOOL_F;
524 }
525 #undef FUNC_NAME
526
527 SCM_DEFINE (scm_nan_p, "nan?", 1, 0, 0,
528 (SCM n),
529 "Return @code{#t} if @var{n} is a NaN, @code{#f}\n"
530 "otherwise.")
531 #define FUNC_NAME s_scm_nan_p
532 {
533 if (SCM_REALP (n))
534 return SCM_BOOL (xisnan (SCM_REAL_VALUE (n)));
535 else if (SCM_COMPLEXP (n))
536 return SCM_BOOL (xisnan (SCM_COMPLEX_REAL (n))
537 || xisnan (SCM_COMPLEX_IMAG (n)));
538 else
539 return SCM_BOOL_F;
540 }
541 #undef FUNC_NAME
542
543 /* Guile's idea of infinity. */
544 static double guile_Inf;
545
546 /* Guile's idea of not a number. */
547 static double guile_NaN;
548
549 static void
550 guile_ieee_init (void)
551 {
552 #if defined (HAVE_ISINF) || defined (HAVE_FINITE)
553
554 /* Some version of gcc on some old version of Linux used to crash when
555 trying to make Inf and NaN. */
556
557 #if defined (SCO)
558 double tmp = 1.0;
559 guile_Inf = 1.0 / (tmp - tmp);
560 #elif defined (__alpha__) && ! defined (linux)
561 extern unsigned int DINFINITY[2];
562 guile_Inf = (*(X_CAST(double *, DINFINITY)));
563 #else
564 double tmp = 1e+10;
565 guile_Inf = tmp;
566 for (;;)
567 {
568 guile_Inf *= 1e+10;
569 if (guile_Inf == tmp)
570 break;
571 tmp = guile_Inf;
572 }
573 #endif
574
575 #endif
576
577 #if defined (HAVE_ISNAN)
578
579 #if defined (__alpha__) && ! defined (linux)
580 extern unsigned int DQNAN[2];
581 guile_NaN = (*(X_CAST(double *, DQNAN)));
582 #else
583 guile_NaN = guile_Inf / guile_Inf;
584 #endif
585
586 #endif
587 }
588
589 SCM_DEFINE (scm_inf, "inf", 0, 0, 0,
590 (void),
591 "Return Inf.")
592 #define FUNC_NAME s_scm_inf
593 {
594 static int initialized = 0;
595 if (! initialized)
596 {
597 guile_ieee_init ();
598 initialized = 1;
599 }
600 return scm_make_real (guile_Inf);
601 }
602 #undef FUNC_NAME
603
604 SCM_DEFINE (scm_nan, "nan", 0, 0, 0,
605 (void),
606 "Return NaN.")
607 #define FUNC_NAME s_scm_nan
608 {
609 static int initialized = 0;
610 if (!initialized)
611 {
612 guile_ieee_init ();
613 initialized = 1;
614 }
615 return scm_make_real (guile_NaN);
616 }
617 #undef FUNC_NAME
618
619
620 SCM_PRIMITIVE_GENERIC (scm_abs, "abs", 1, 0, 0,
621 (SCM x),
622 "Return the absolute value of @var{x}.")
623 #define FUNC_NAME
624 {
625 if (SCM_INUMP (x))
626 {
627 long int xx = SCM_INUM (x);
628 if (xx >= 0)
629 return x;
630 else if (SCM_POSFIXABLE (-xx))
631 return SCM_MAKINUM (-xx);
632 else
633 return scm_i_long2big (-xx);
634 }
635 else if (SCM_BIGP (x))
636 {
637 const int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
638 if (sgn < 0)
639 return scm_i_clonebig (x, 0);
640 else
641 return x;
642 }
643 else if (SCM_REALP (x))
644 return scm_make_real (fabs (SCM_REAL_VALUE (x)));
645 else if (SCM_FRACTIONP (x))
646 {
647 if (SCM_FALSEP (scm_negative_p (SCM_FRACTION_NUMERATOR (x))))
648 return x;
649 return scm_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x), SCM_UNDEFINED),
650 SCM_FRACTION_DENOMINATOR (x));
651 }
652 else
653 SCM_WTA_DISPATCH_1 (g_scm_abs, x, 1, s_scm_abs);
654 }
655 #undef FUNC_NAME
656
657
658 SCM_GPROC (s_quotient, "quotient", 2, 0, 0, scm_quotient, g_quotient);
659 /* "Return the quotient of the numbers @var{x} and @var{y}."
660 */
661 SCM
662 scm_quotient (SCM x, SCM y)
663 {
664 if (SCM_INUMP (x))
665 {
666 long xx = SCM_INUM (x);
667 if (SCM_INUMP (y))
668 {
669 long yy = SCM_INUM (y);
670 if (yy == 0)
671 scm_num_overflow (s_quotient);
672 else
673 {
674 long z = xx / yy;
675 if (SCM_FIXABLE (z))
676 return SCM_MAKINUM (z);
677 else
678 return scm_i_long2big (z);
679 }
680 }
681 else if (SCM_BIGP (y))
682 {
683 if ((SCM_INUM (x) == SCM_MOST_NEGATIVE_FIXNUM)
684 && (scm_i_bigcmp (abs_most_negative_fixnum, y) == 0))
685 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
686 return SCM_MAKINUM (-1);
687 else
688 return SCM_MAKINUM (0);
689 }
690 else
691 SCM_WTA_DISPATCH_2 (g_quotient, x, y, SCM_ARG2, s_quotient);
692 }
693 else if (SCM_BIGP (x))
694 {
695 if (SCM_INUMP (y))
696 {
697 long yy = SCM_INUM (y);
698 if (yy == 0)
699 scm_num_overflow (s_quotient);
700 else if (yy == 1)
701 return x;
702 else
703 {
704 SCM result = scm_i_mkbig ();
705 if (yy < 0)
706 {
707 mpz_tdiv_q_ui (SCM_I_BIG_MPZ (result),
708 SCM_I_BIG_MPZ (x),
709 - yy);
710 mpz_neg (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result));
711 }
712 else
713 mpz_tdiv_q_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), yy);
714 scm_remember_upto_here_1 (x);
715 return scm_i_normbig (result);
716 }
717 }
718 else if (SCM_BIGP (y))
719 {
720 SCM result = scm_i_mkbig ();
721 mpz_tdiv_q (SCM_I_BIG_MPZ (result),
722 SCM_I_BIG_MPZ (x),
723 SCM_I_BIG_MPZ (y));
724 scm_remember_upto_here_2 (x, y);
725 return scm_i_normbig (result);
726 }
727 else
728 SCM_WTA_DISPATCH_2 (g_quotient, x, y, SCM_ARG2, s_quotient);
729 }
730 else
731 SCM_WTA_DISPATCH_2 (g_quotient, x, y, SCM_ARG1, s_quotient);
732 }
733
734 SCM_GPROC (s_remainder, "remainder", 2, 0, 0, scm_remainder, g_remainder);
735 /* "Return the remainder of the numbers @var{x} and @var{y}.\n"
736 * "@lisp\n"
737 * "(remainder 13 4) @result{} 1\n"
738 * "(remainder -13 4) @result{} -1\n"
739 * "@end lisp"
740 */
741 SCM
742 scm_remainder (SCM x, SCM y)
743 {
744 if (SCM_INUMP (x))
745 {
746 if (SCM_INUMP (y))
747 {
748 long yy = SCM_INUM (y);
749 if (yy == 0)
750 scm_num_overflow (s_remainder);
751 else
752 {
753 long z = SCM_INUM (x) % yy;
754 return SCM_MAKINUM (z);
755 }
756 }
757 else if (SCM_BIGP (y))
758 {
759 if ((SCM_INUM (x) == SCM_MOST_NEGATIVE_FIXNUM)
760 && (scm_i_bigcmp (abs_most_negative_fixnum, y) == 0))
761 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
762 return SCM_MAKINUM (0);
763 else
764 return x;
765 }
766 else
767 SCM_WTA_DISPATCH_2 (g_remainder, x, y, SCM_ARG2, s_remainder);
768 }
769 else if (SCM_BIGP (x))
770 {
771 if (SCM_INUMP (y))
772 {
773 long yy = SCM_INUM (y);
774 if (yy == 0)
775 scm_num_overflow (s_remainder);
776 else
777 {
778 SCM result = scm_i_mkbig ();
779 if (yy < 0)
780 yy = - yy;
781 mpz_tdiv_r_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ(x), yy);
782 scm_remember_upto_here_1 (x);
783 return scm_i_normbig (result);
784 }
785 }
786 else if (SCM_BIGP (y))
787 {
788 SCM result = scm_i_mkbig ();
789 mpz_tdiv_r (SCM_I_BIG_MPZ (result),
790 SCM_I_BIG_MPZ (x),
791 SCM_I_BIG_MPZ (y));
792 scm_remember_upto_here_2 (x, y);
793 return scm_i_normbig (result);
794 }
795 else
796 SCM_WTA_DISPATCH_2 (g_remainder, x, y, SCM_ARG2, s_remainder);
797 }
798 else
799 SCM_WTA_DISPATCH_2 (g_remainder, x, y, SCM_ARG1, s_remainder);
800 }
801
802
803 SCM_GPROC (s_modulo, "modulo", 2, 0, 0, scm_modulo, g_modulo);
804 /* "Return the modulo of the numbers @var{x} and @var{y}.\n"
805 * "@lisp\n"
806 * "(modulo 13 4) @result{} 1\n"
807 * "(modulo -13 4) @result{} 3\n"
808 * "@end lisp"
809 */
810 SCM
811 scm_modulo (SCM x, SCM y)
812 {
813 if (SCM_INUMP (x))
814 {
815 long xx = SCM_INUM (x);
816 if (SCM_INUMP (y))
817 {
818 long yy = SCM_INUM (y);
819 if (yy == 0)
820 scm_num_overflow (s_modulo);
821 else
822 {
823 /* FIXME: I think this may be a bug on some arches -- results
824 of % with negative second arg are undefined... */
825 long z = xx % yy;
826 long result;
827
828 if (yy < 0)
829 {
830 if (z > 0)
831 result = z + yy;
832 else
833 result = z;
834 }
835 else
836 {
837 if (z < 0)
838 result = z + yy;
839 else
840 result = z;
841 }
842 return SCM_MAKINUM (result);
843 }
844 }
845 else if (SCM_BIGP (y))
846 {
847 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
848
849 if (sgn_y == 0)
850 scm_num_overflow (s_modulo);
851 else
852 {
853 mpz_t z_x;
854 SCM result;
855
856 if (sgn_y < 0)
857 {
858 SCM pos_y = scm_i_clonebig (y, 0);
859 /* do this after the last scm_op */
860 mpz_init_set_si (z_x, xx);
861 result = pos_y; /* re-use this bignum */
862 mpz_mod (SCM_I_BIG_MPZ (result),
863 z_x,
864 SCM_I_BIG_MPZ (pos_y));
865 scm_remember_upto_here_1 (pos_y);
866 }
867 else
868 {
869 result = scm_i_mkbig ();
870 /* do this after the last scm_op */
871 mpz_init_set_si (z_x, xx);
872 mpz_mod (SCM_I_BIG_MPZ (result),
873 z_x,
874 SCM_I_BIG_MPZ (y));
875 scm_remember_upto_here_1 (y);
876 }
877
878 if ((sgn_y < 0) && mpz_sgn (SCM_I_BIG_MPZ (result)) != 0)
879 mpz_add (SCM_I_BIG_MPZ (result),
880 SCM_I_BIG_MPZ (y),
881 SCM_I_BIG_MPZ (result));
882 scm_remember_upto_here_1 (y);
883 /* and do this before the next one */
884 mpz_clear (z_x);
885 return scm_i_normbig (result);
886 }
887 }
888 else
889 SCM_WTA_DISPATCH_2 (g_modulo, x, y, SCM_ARG2, s_modulo);
890 }
891 else if (SCM_BIGP (x))
892 {
893 if (SCM_INUMP (y))
894 {
895 long yy = SCM_INUM (y);
896 if (yy == 0)
897 scm_num_overflow (s_modulo);
898 else
899 {
900 SCM result = scm_i_mkbig ();
901 mpz_mod_ui (SCM_I_BIG_MPZ (result),
902 SCM_I_BIG_MPZ (x),
903 (yy < 0) ? - yy : yy);
904 scm_remember_upto_here_1 (x);
905 if ((yy < 0) && (mpz_sgn (SCM_I_BIG_MPZ (result)) != 0))
906 mpz_sub_ui (SCM_I_BIG_MPZ (result),
907 SCM_I_BIG_MPZ (result),
908 - yy);
909 return scm_i_normbig (result);
910 }
911 }
912 else if (SCM_BIGP (y))
913 {
914 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
915 if (sgn_y == 0)
916 scm_num_overflow (s_modulo);
917 else
918 {
919 SCM result = scm_i_mkbig ();
920 int y_sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
921 SCM pos_y = scm_i_clonebig (y, y_sgn >= 0);
922 mpz_mod (SCM_I_BIG_MPZ (result),
923 SCM_I_BIG_MPZ (x),
924 SCM_I_BIG_MPZ (pos_y));
925
926 scm_remember_upto_here_1 (x);
927 if ((y_sgn < 0) && (mpz_sgn (SCM_I_BIG_MPZ (result)) != 0))
928 mpz_add (SCM_I_BIG_MPZ (result),
929 SCM_I_BIG_MPZ (y),
930 SCM_I_BIG_MPZ (result));
931 scm_remember_upto_here_2 (y, pos_y);
932 return scm_i_normbig (result);
933 }
934 }
935 else
936 SCM_WTA_DISPATCH_2 (g_modulo, x, y, SCM_ARG2, s_modulo);
937 }
938 else
939 SCM_WTA_DISPATCH_2 (g_modulo, x, y, SCM_ARG1, s_modulo);
940 }
941
942 SCM_GPROC1 (s_gcd, "gcd", scm_tc7_asubr, scm_gcd, g_gcd);
943 /* "Return the greatest common divisor of all arguments.\n"
944 * "If called without arguments, 0 is returned."
945 */
946 SCM
947 scm_gcd (SCM x, SCM y)
948 {
949 if (SCM_UNBNDP (y))
950 return SCM_UNBNDP (x) ? SCM_INUM0 : x;
951
952 if (SCM_INUMP (x))
953 {
954 if (SCM_INUMP (y))
955 {
956 long xx = SCM_INUM (x);
957 long yy = SCM_INUM (y);
958 long u = xx < 0 ? -xx : xx;
959 long v = yy < 0 ? -yy : yy;
960 long result;
961 if (xx == 0)
962 result = v;
963 else if (yy == 0)
964 result = u;
965 else
966 {
967 long k = 1;
968 long t;
969 /* Determine a common factor 2^k */
970 while (!(1 & (u | v)))
971 {
972 k <<= 1;
973 u >>= 1;
974 v >>= 1;
975 }
976 /* Now, any factor 2^n can be eliminated */
977 if (u & 1)
978 t = -v;
979 else
980 {
981 t = u;
982 b3:
983 t = SCM_SRS (t, 1);
984 }
985 if (!(1 & t))
986 goto b3;
987 if (t > 0)
988 u = t;
989 else
990 v = -t;
991 t = u - v;
992 if (t != 0)
993 goto b3;
994 result = u * k;
995 }
996 return (SCM_POSFIXABLE (result)
997 ? SCM_MAKINUM (result)
998 : scm_i_long2big (result));
999 }
1000 else if (SCM_BIGP (y))
1001 {
1002 SCM result = scm_i_mkbig ();
1003 SCM mx = scm_i_mkbig ();
1004 mpz_set_si (SCM_I_BIG_MPZ (mx), SCM_INUM (x));
1005 scm_remember_upto_here_1 (x);
1006 mpz_gcd (SCM_I_BIG_MPZ (result),
1007 SCM_I_BIG_MPZ (mx),
1008 SCM_I_BIG_MPZ (y));
1009 scm_remember_upto_here_2 (mx, y);
1010 return scm_i_normbig (result);
1011 }
1012 else
1013 SCM_WTA_DISPATCH_2 (g_gcd, x, y, SCM_ARG2, s_gcd);
1014 }
1015 else if (SCM_BIGP (x))
1016 {
1017 if (SCM_INUMP (y))
1018 {
1019 unsigned long result;
1020 long yy = SCM_INUM (y);
1021 if (yy == 0)
1022 return scm_abs (x);
1023 if (yy < 0)
1024 yy = -yy;
1025 result = mpz_gcd_ui (NULL, SCM_I_BIG_MPZ (x), yy);
1026 scm_remember_upto_here_1 (x);
1027 return (SCM_POSFIXABLE (result)
1028 ? SCM_MAKINUM (result)
1029 : scm_ulong2num (result));
1030 }
1031 else if (SCM_BIGP (y))
1032 {
1033 SCM result = scm_i_mkbig ();
1034 mpz_gcd (SCM_I_BIG_MPZ (result),
1035 SCM_I_BIG_MPZ (x),
1036 SCM_I_BIG_MPZ (y));
1037 scm_remember_upto_here_2 (x, y);
1038 return scm_i_normbig (result);
1039 }
1040 else
1041 SCM_WTA_DISPATCH_2 (g_gcd, x, y, SCM_ARG2, s_gcd);
1042 }
1043 else
1044 SCM_WTA_DISPATCH_2 (g_gcd, x, y, SCM_ARG1, s_gcd);
1045 }
1046
1047 SCM_GPROC1 (s_lcm, "lcm", scm_tc7_asubr, scm_lcm, g_lcm);
1048 /* "Return the least common multiple of the arguments.\n"
1049 * "If called without arguments, 1 is returned."
1050 */
1051 SCM
1052 scm_lcm (SCM n1, SCM n2)
1053 {
1054 if (SCM_UNBNDP (n2))
1055 {
1056 if (SCM_UNBNDP (n1))
1057 return SCM_MAKINUM (1L);
1058 n2 = SCM_MAKINUM (1L);
1059 }
1060
1061 SCM_GASSERT2 (SCM_INUMP (n1) || SCM_BIGP (n1),
1062 g_lcm, n1, n2, SCM_ARG1, s_lcm);
1063 SCM_GASSERT2 (SCM_INUMP (n2) || SCM_BIGP (n2),
1064 g_lcm, n1, n2, SCM_ARGn, s_lcm);
1065
1066 if (SCM_INUMP (n1))
1067 {
1068 if (SCM_INUMP (n2))
1069 {
1070 SCM d = scm_gcd (n1, n2);
1071 if (SCM_EQ_P (d, SCM_INUM0))
1072 return d;
1073 else
1074 return scm_abs (scm_product (n1, scm_quotient (n2, d)));
1075 }
1076 else
1077 {
1078 /* inum n1, big n2 */
1079 inumbig:
1080 {
1081 SCM result = scm_i_mkbig ();
1082 long nn1 = SCM_INUM (n1);
1083 if (nn1 == 0) return SCM_INUM0;
1084 if (nn1 < 0) nn1 = - nn1;
1085 mpz_lcm_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n2), nn1);
1086 scm_remember_upto_here_1 (n2);
1087 return result;
1088 }
1089 }
1090 }
1091 else
1092 {
1093 /* big n1 */
1094 if (SCM_INUMP (n2))
1095 {
1096 SCM_SWAP (n1, n2);
1097 goto inumbig;
1098 }
1099 else
1100 {
1101 SCM result = scm_i_mkbig ();
1102 mpz_lcm(SCM_I_BIG_MPZ (result),
1103 SCM_I_BIG_MPZ (n1),
1104 SCM_I_BIG_MPZ (n2));
1105 scm_remember_upto_here_2(n1, n2);
1106 /* shouldn't need to normalize b/c lcm of 2 bigs should be big */
1107 return result;
1108 }
1109 }
1110 }
1111
1112 #ifndef scm_long2num
1113 #define SCM_LOGOP_RETURN(x) scm_ulong2num(x)
1114 #else
1115 #define SCM_LOGOP_RETURN(x) SCM_MAKINUM(x)
1116 #endif
1117
1118 /* Emulating 2's complement bignums with sign magnitude arithmetic:
1119
1120 Logand:
1121 X Y Result Method:
1122 (len)
1123 + + + x (map digit:logand X Y)
1124 + - + x (map digit:logand X (lognot (+ -1 Y)))
1125 - + + y (map digit:logand (lognot (+ -1 X)) Y)
1126 - - - (+ 1 (map digit:logior (+ -1 X) (+ -1 Y)))
1127
1128 Logior:
1129 X Y Result Method:
1130
1131 + + + (map digit:logior X Y)
1132 + - - y (+ 1 (map digit:logand (lognot X) (+ -1 Y)))
1133 - + - x (+ 1 (map digit:logand (+ -1 X) (lognot Y)))
1134 - - - x (+ 1 (map digit:logand (+ -1 X) (+ -1 Y)))
1135
1136 Logxor:
1137 X Y Result Method:
1138
1139 + + + (map digit:logxor X Y)
1140 + - - (+ 1 (map digit:logxor X (+ -1 Y)))
1141 - + - (+ 1 (map digit:logxor (+ -1 X) Y))
1142 - - + (map digit:logxor (+ -1 X) (+ -1 Y))
1143
1144 Logtest:
1145 X Y Result
1146
1147 + + (any digit:logand X Y)
1148 + - (any digit:logand X (lognot (+ -1 Y)))
1149 - + (any digit:logand (lognot (+ -1 X)) Y)
1150 - - #t
1151
1152 */
1153
1154 SCM_DEFINE1 (scm_logand, "logand", scm_tc7_asubr,
1155 (SCM n1, SCM n2),
1156 "Return the bitwise AND of the integer arguments.\n\n"
1157 "@lisp\n"
1158 "(logand) @result{} -1\n"
1159 "(logand 7) @result{} 7\n"
1160 "(logand #b111 #b011 #\b001) @result{} 1\n"
1161 "@end lisp")
1162 #define FUNC_NAME s_scm_logand
1163 {
1164 long int nn1;
1165
1166 if (SCM_UNBNDP (n2))
1167 {
1168 if (SCM_UNBNDP (n1))
1169 return SCM_MAKINUM (-1);
1170 else if (!SCM_NUMBERP (n1))
1171 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
1172 else if (SCM_NUMBERP (n1))
1173 return n1;
1174 else
1175 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
1176 }
1177
1178 if (SCM_INUMP (n1))
1179 {
1180 nn1 = SCM_INUM (n1);
1181 if (SCM_INUMP (n2))
1182 {
1183 long nn2 = SCM_INUM (n2);
1184 return SCM_MAKINUM (nn1 & nn2);
1185 }
1186 else if SCM_BIGP (n2)
1187 {
1188 intbig:
1189 if (n1 == 0)
1190 return SCM_INUM0;
1191 {
1192 SCM result_z = scm_i_mkbig ();
1193 mpz_t nn1_z;
1194 mpz_init_set_si (nn1_z, nn1);
1195 mpz_and (SCM_I_BIG_MPZ (result_z), nn1_z, SCM_I_BIG_MPZ (n2));
1196 scm_remember_upto_here_1 (n2);
1197 mpz_clear (nn1_z);
1198 return scm_i_normbig (result_z);
1199 }
1200 }
1201 else
1202 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
1203 }
1204 else if (SCM_BIGP (n1))
1205 {
1206 if (SCM_INUMP (n2))
1207 {
1208 SCM_SWAP (n1, n2);
1209 nn1 = SCM_INUM (n1);
1210 goto intbig;
1211 }
1212 else if (SCM_BIGP (n2))
1213 {
1214 SCM result_z = scm_i_mkbig ();
1215 mpz_and (SCM_I_BIG_MPZ (result_z),
1216 SCM_I_BIG_MPZ (n1),
1217 SCM_I_BIG_MPZ (n2));
1218 scm_remember_upto_here_2 (n1, n2);
1219 return scm_i_normbig (result_z);
1220 }
1221 else
1222 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
1223 }
1224 else
1225 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
1226 }
1227 #undef FUNC_NAME
1228
1229
1230 SCM_DEFINE1 (scm_logior, "logior", scm_tc7_asubr,
1231 (SCM n1, SCM n2),
1232 "Return the bitwise OR of the integer arguments.\n\n"
1233 "@lisp\n"
1234 "(logior) @result{} 0\n"
1235 "(logior 7) @result{} 7\n"
1236 "(logior #b000 #b001 #b011) @result{} 3\n"
1237 "@end lisp")
1238 #define FUNC_NAME s_scm_logior
1239 {
1240 long int nn1;
1241
1242 if (SCM_UNBNDP (n2))
1243 {
1244 if (SCM_UNBNDP (n1))
1245 return SCM_INUM0;
1246 else if (SCM_NUMBERP (n1))
1247 return n1;
1248 else
1249 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
1250 }
1251
1252 if (SCM_INUMP (n1))
1253 {
1254 nn1 = SCM_INUM (n1);
1255 if (SCM_INUMP (n2))
1256 {
1257 long nn2 = SCM_INUM (n2);
1258 return SCM_MAKINUM (nn1 | nn2);
1259 }
1260 else if (SCM_BIGP (n2))
1261 {
1262 intbig:
1263 if (nn1 == 0)
1264 return n2;
1265 {
1266 SCM result_z = scm_i_mkbig ();
1267 mpz_t nn1_z;
1268 mpz_init_set_si (nn1_z, nn1);
1269 mpz_ior (SCM_I_BIG_MPZ (result_z), nn1_z, SCM_I_BIG_MPZ (n2));
1270 scm_remember_upto_here_1 (n2);
1271 mpz_clear (nn1_z);
1272 return result_z;
1273 }
1274 }
1275 else
1276 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
1277 }
1278 else if (SCM_BIGP (n1))
1279 {
1280 if (SCM_INUMP (n2))
1281 {
1282 SCM_SWAP (n1, n2);
1283 nn1 = SCM_INUM (n1);
1284 goto intbig;
1285 }
1286 else if (SCM_BIGP (n2))
1287 {
1288 SCM result_z = scm_i_mkbig ();
1289 mpz_ior (SCM_I_BIG_MPZ (result_z),
1290 SCM_I_BIG_MPZ (n1),
1291 SCM_I_BIG_MPZ (n2));
1292 scm_remember_upto_here_2 (n1, n2);
1293 return result_z;
1294 }
1295 else
1296 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
1297 }
1298 else
1299 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
1300 }
1301 #undef FUNC_NAME
1302
1303
1304 SCM_DEFINE1 (scm_logxor, "logxor", scm_tc7_asubr,
1305 (SCM n1, SCM n2),
1306 "Return the bitwise XOR of the integer arguments. A bit is\n"
1307 "set in the result if it is set in an odd number of arguments.\n"
1308 "@lisp\n"
1309 "(logxor) @result{} 0\n"
1310 "(logxor 7) @result{} 7\n"
1311 "(logxor #b000 #b001 #b011) @result{} 2\n"
1312 "(logxor #b000 #b001 #b011 #b011) @result{} 1\n"
1313 "@end lisp")
1314 #define FUNC_NAME s_scm_logxor
1315 {
1316 long int nn1;
1317
1318 if (SCM_UNBNDP (n2))
1319 {
1320 if (SCM_UNBNDP (n1))
1321 return SCM_INUM0;
1322 else if (SCM_NUMBERP (n1))
1323 return n1;
1324 else
1325 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
1326 }
1327
1328 if (SCM_INUMP (n1))
1329 {
1330 nn1 = SCM_INUM (n1);
1331 if (SCM_INUMP (n2))
1332 {
1333 long nn2 = SCM_INUM (n2);
1334 return SCM_MAKINUM (nn1 ^ nn2);
1335 }
1336 else if (SCM_BIGP (n2))
1337 {
1338 intbig:
1339 {
1340 SCM result_z = scm_i_mkbig ();
1341 mpz_t nn1_z;
1342 mpz_init_set_si (nn1_z, nn1);
1343 mpz_xor (SCM_I_BIG_MPZ (result_z), nn1_z, SCM_I_BIG_MPZ (n2));
1344 scm_remember_upto_here_1 (n2);
1345 mpz_clear (nn1_z);
1346 return scm_i_normbig (result_z);
1347 }
1348 }
1349 else
1350 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
1351 }
1352 else if (SCM_BIGP (n1))
1353 {
1354 if (SCM_INUMP (n2))
1355 {
1356 SCM_SWAP (n1, n2);
1357 nn1 = SCM_INUM (n1);
1358 goto intbig;
1359 }
1360 else if (SCM_BIGP (n2))
1361 {
1362 SCM result_z = scm_i_mkbig ();
1363 mpz_xor (SCM_I_BIG_MPZ (result_z),
1364 SCM_I_BIG_MPZ (n1),
1365 SCM_I_BIG_MPZ (n2));
1366 scm_remember_upto_here_2 (n1, n2);
1367 return scm_i_normbig (result_z);
1368 }
1369 else
1370 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
1371 }
1372 else
1373 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
1374 }
1375 #undef FUNC_NAME
1376
1377
1378 SCM_DEFINE (scm_logtest, "logtest", 2, 0, 0,
1379 (SCM j, SCM k),
1380 "@lisp\n"
1381 "(logtest j k) @equiv{} (not (zero? (logand j k)))\n\n"
1382 "(logtest #b0100 #b1011) @result{} #f\n"
1383 "(logtest #b0100 #b0111) @result{} #t\n"
1384 "@end lisp")
1385 #define FUNC_NAME s_scm_logtest
1386 {
1387 long int nj;
1388
1389 if (SCM_INUMP (j))
1390 {
1391 nj = SCM_INUM (j);
1392 if (SCM_INUMP (k))
1393 {
1394 long nk = SCM_INUM (k);
1395 return SCM_BOOL (nj & nk);
1396 }
1397 else if (SCM_BIGP (k))
1398 {
1399 intbig:
1400 if (nj == 0)
1401 return SCM_BOOL_F;
1402 {
1403 SCM result;
1404 mpz_t nj_z;
1405 mpz_init_set_si (nj_z, nj);
1406 mpz_and (nj_z, nj_z, SCM_I_BIG_MPZ (k));
1407 scm_remember_upto_here_1 (k);
1408 result = SCM_BOOL (mpz_sgn (nj_z) != 0);
1409 mpz_clear (nj_z);
1410 return result;
1411 }
1412 }
1413 else
1414 SCM_WRONG_TYPE_ARG (SCM_ARG2, k);
1415 }
1416 else if (SCM_BIGP (j))
1417 {
1418 if (SCM_INUMP (k))
1419 {
1420 SCM_SWAP (j, k);
1421 nj = SCM_INUM (j);
1422 goto intbig;
1423 }
1424 else if (SCM_BIGP (k))
1425 {
1426 SCM result;
1427 mpz_t result_z;
1428 mpz_init (result_z);
1429 mpz_and (result_z,
1430 SCM_I_BIG_MPZ (j),
1431 SCM_I_BIG_MPZ (k));
1432 scm_remember_upto_here_2 (j, k);
1433 result = SCM_BOOL (mpz_sgn (result_z) != 0);
1434 mpz_clear (result_z);
1435 return result;
1436 }
1437 else
1438 SCM_WRONG_TYPE_ARG (SCM_ARG2, k);
1439 }
1440 else
1441 SCM_WRONG_TYPE_ARG (SCM_ARG1, j);
1442 }
1443 #undef FUNC_NAME
1444
1445
1446 SCM_DEFINE (scm_logbit_p, "logbit?", 2, 0, 0,
1447 (SCM index, SCM j),
1448 "@lisp\n"
1449 "(logbit? index j) @equiv{} (logtest (integer-expt 2 index) j)\n\n"
1450 "(logbit? 0 #b1101) @result{} #t\n"
1451 "(logbit? 1 #b1101) @result{} #f\n"
1452 "(logbit? 2 #b1101) @result{} #t\n"
1453 "(logbit? 3 #b1101) @result{} #t\n"
1454 "(logbit? 4 #b1101) @result{} #f\n"
1455 "@end lisp")
1456 #define FUNC_NAME s_scm_logbit_p
1457 {
1458 unsigned long int iindex;
1459
1460 SCM_VALIDATE_INUM_MIN (SCM_ARG1, index, 0);
1461 iindex = (unsigned long int) SCM_INUM (index);
1462
1463 if (SCM_INUMP (j))
1464 return SCM_BOOL ((1L << iindex) & SCM_INUM (j));
1465 else if (SCM_BIGP (j))
1466 {
1467 int val = mpz_tstbit (SCM_I_BIG_MPZ (j), iindex);
1468 scm_remember_upto_here_1 (j);
1469 return SCM_BOOL (val);
1470 }
1471 else
1472 SCM_WRONG_TYPE_ARG (SCM_ARG2, j);
1473 }
1474 #undef FUNC_NAME
1475
1476
1477 SCM_DEFINE (scm_lognot, "lognot", 1, 0, 0,
1478 (SCM n),
1479 "Return the integer which is the ones-complement of the integer\n"
1480 "argument.\n"
1481 "\n"
1482 "@lisp\n"
1483 "(number->string (lognot #b10000000) 2)\n"
1484 " @result{} \"-10000001\"\n"
1485 "(number->string (lognot #b0) 2)\n"
1486 " @result{} \"-1\"\n"
1487 "@end lisp")
1488 #define FUNC_NAME s_scm_lognot
1489 {
1490 if (SCM_INUMP (n)) {
1491 /* No overflow here, just need to toggle all the bits making up the inum.
1492 Enhancement: No need to strip the tag and add it back, could just xor
1493 a block of 1 bits, if that worked with the various debug versions of
1494 the SCM typedef. */
1495 return SCM_MAKINUM (~ SCM_INUM (n));
1496
1497 } else if (SCM_BIGP (n)) {
1498 SCM result = scm_i_mkbig ();
1499 mpz_com (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n));
1500 scm_remember_upto_here_1 (n);
1501 return result;
1502
1503 } else {
1504 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1505 }
1506 }
1507 #undef FUNC_NAME
1508
1509 SCM_DEFINE (scm_integer_expt, "integer-expt", 2, 0, 0,
1510 (SCM n, SCM k),
1511 "Return @var{n} raised to the non-negative integer exponent\n"
1512 "@var{k}.\n"
1513 "\n"
1514 "@lisp\n"
1515 "(integer-expt 2 5)\n"
1516 " @result{} 32\n"
1517 "(integer-expt -3 3)\n"
1518 " @result{} -27\n"
1519 "@end lisp")
1520 #define FUNC_NAME s_scm_integer_expt
1521 {
1522 long i2 = 0;
1523 SCM z_i2 = SCM_BOOL_F;
1524 int i2_is_big = 0;
1525 SCM acc = SCM_MAKINUM (1L);
1526
1527 /* 0^0 == 1 according to R5RS */
1528 if (SCM_EQ_P (n, SCM_INUM0) || SCM_EQ_P (n, acc))
1529 return SCM_FALSEP (scm_zero_p(k)) ? n : acc;
1530 else if (SCM_EQ_P (n, SCM_MAKINUM (-1L)))
1531 return SCM_FALSEP (scm_even_p (k)) ? n : acc;
1532
1533 if (SCM_INUMP (k))
1534 i2 = SCM_INUM (k);
1535 else if (SCM_BIGP (k))
1536 {
1537 z_i2 = scm_i_clonebig (k, 1);
1538 mpz_init_set (SCM_I_BIG_MPZ (z_i2), SCM_I_BIG_MPZ (k));
1539 scm_remember_upto_here_1 (k);
1540 i2_is_big = 1;
1541 }
1542 else if (SCM_REALP (k))
1543 {
1544 double r = SCM_REAL_VALUE (k);
1545 if (floor (r) != r)
1546 SCM_WRONG_TYPE_ARG (2, k);
1547 if ((r > SCM_MOST_POSITIVE_FIXNUM) || (r < SCM_MOST_NEGATIVE_FIXNUM))
1548 {
1549 z_i2 = scm_i_mkbig ();
1550 mpz_init_set_d (SCM_I_BIG_MPZ (z_i2), r);
1551 i2_is_big = 1;
1552 }
1553 else
1554 {
1555 i2 = r;
1556 }
1557 }
1558 else
1559 SCM_WRONG_TYPE_ARG (2, k);
1560
1561 if (i2_is_big)
1562 {
1563 if (mpz_sgn(SCM_I_BIG_MPZ (z_i2)) == -1)
1564 {
1565 mpz_neg (SCM_I_BIG_MPZ (z_i2), SCM_I_BIG_MPZ (z_i2));
1566 n = scm_divide (n, SCM_UNDEFINED);
1567 }
1568 while (1)
1569 {
1570 if (mpz_sgn(SCM_I_BIG_MPZ (z_i2)) == 0)
1571 {
1572 mpz_clear (SCM_I_BIG_MPZ (z_i2));
1573 return acc;
1574 }
1575 if (mpz_cmp_ui(SCM_I_BIG_MPZ (z_i2), 1) == 0)
1576 {
1577 mpz_clear (SCM_I_BIG_MPZ (z_i2));
1578 return scm_product (acc, n);
1579 }
1580 if (mpz_tstbit(SCM_I_BIG_MPZ (z_i2), 0))
1581 acc = scm_product (acc, n);
1582 n = scm_product (n, n);
1583 mpz_fdiv_q_2exp (SCM_I_BIG_MPZ (z_i2), SCM_I_BIG_MPZ (z_i2), 1);
1584 }
1585 }
1586 else
1587 {
1588 if (i2 < 0)
1589 {
1590 i2 = -i2;
1591 n = scm_divide (n, SCM_UNDEFINED);
1592 }
1593 while (1)
1594 {
1595 if (0 == i2)
1596 return acc;
1597 if (1 == i2)
1598 return scm_product (acc, n);
1599 if (i2 & 1)
1600 acc = scm_product (acc, n);
1601 n = scm_product (n, n);
1602 i2 >>= 1;
1603 }
1604 }
1605 }
1606 #undef FUNC_NAME
1607
1608 SCM_DEFINE (scm_ash, "ash", 2, 0, 0,
1609 (SCM n, SCM cnt),
1610 "Return @var{n} shifted left by @var{cnt} bits, or shifted right\n"
1611 "if @var{cnt} is negative. This is an ``arithmetic'' shift.\n"
1612 "\n"
1613 "This is effectively a multiplication by 2^@var{cnt}}, and when\n"
1614 "@var{cnt} is negative it's a division, rounded towards negative\n"
1615 "infinity. (Note that this is not the same rounding as\n"
1616 "@code{quotient} does.)\n"
1617 "\n"
1618 "With @var{n} viewed as an infinite precision twos complement,\n"
1619 "@code{ash} means a left shift introducing zero bits, or a right\n"
1620 "shift dropping bits.\n"
1621 "\n"
1622 "@lisp\n"
1623 "(number->string (ash #b1 3) 2) @result{} \"1000\"\n"
1624 "(number->string (ash #b1010 -1) 2) @result{} \"101\"\n"
1625 "\n"
1626 ";; -23 is bits ...11101001, -6 is bits ...111010\n"
1627 "(ash -23 -2) @result{} -6\n"
1628 "@end lisp")
1629 #define FUNC_NAME s_scm_ash
1630 {
1631 long bits_to_shift;
1632
1633 SCM_VALIDATE_INUM (2, cnt);
1634
1635 bits_to_shift = SCM_INUM (cnt);
1636
1637 if (bits_to_shift < 0)
1638 {
1639 /* Shift right by abs(cnt) bits. This is realized as a division
1640 by div:=2^abs(cnt). However, to guarantee the floor
1641 rounding, negative values require some special treatment.
1642 */
1643 SCM div = scm_integer_expt (SCM_MAKINUM (2),
1644 SCM_MAKINUM (-bits_to_shift));
1645
1646 /* scm_quotient assumes its arguments are integers, but it's legal to (ash 1/2 -1) */
1647 if (SCM_FALSEP (scm_negative_p (n)))
1648 return scm_quotient (n, div);
1649 else
1650 return scm_sum (SCM_MAKINUM (-1L),
1651 scm_quotient (scm_sum (SCM_MAKINUM (1L), n), div));
1652 }
1653 else
1654 /* Shift left is done by multiplication with 2^CNT */
1655 return scm_product (n, scm_integer_expt (SCM_MAKINUM (2), cnt));
1656 }
1657 #undef FUNC_NAME
1658
1659
1660 SCM_DEFINE (scm_bit_extract, "bit-extract", 3, 0, 0,
1661 (SCM n, SCM start, SCM end),
1662 "Return the integer composed of the @var{start} (inclusive)\n"
1663 "through @var{end} (exclusive) bits of @var{n}. The\n"
1664 "@var{start}th bit becomes the 0-th bit in the result.\n"
1665 "\n"
1666 "@lisp\n"
1667 "(number->string (bit-extract #b1101101010 0 4) 2)\n"
1668 " @result{} \"1010\"\n"
1669 "(number->string (bit-extract #b1101101010 4 9) 2)\n"
1670 " @result{} \"10110\"\n"
1671 "@end lisp")
1672 #define FUNC_NAME s_scm_bit_extract
1673 {
1674 unsigned long int istart, iend;
1675 SCM_VALIDATE_INUM_MIN_COPY (2, start,0, istart);
1676 SCM_VALIDATE_INUM_MIN_COPY (3, end, 0, iend);
1677 SCM_ASSERT_RANGE (3, end, (iend >= istart));
1678
1679 if (SCM_INUMP (n))
1680 {
1681 long int in = SCM_INUM (n);
1682 unsigned long int bits = iend - istart;
1683
1684 if (in < 0 && bits >= SCM_I_FIXNUM_BIT)
1685 {
1686 /* Since we emulate two's complement encoded numbers, this
1687 * special case requires us to produce a result that has
1688 * more bits than can be stored in a fixnum. Thus, we fall
1689 * back to the more general algorithm that is used for
1690 * bignums.
1691 */
1692 goto generalcase;
1693 }
1694
1695 if (istart < SCM_I_FIXNUM_BIT)
1696 {
1697 in = in >> istart;
1698 if (bits < SCM_I_FIXNUM_BIT)
1699 return SCM_MAKINUM (in & ((1L << bits) - 1));
1700 else /* we know: in >= 0 */
1701 return SCM_MAKINUM (in);
1702 }
1703 else if (in < 0)
1704 return SCM_MAKINUM (-1L & ((1L << bits) - 1));
1705 else
1706 return SCM_MAKINUM (0);
1707 }
1708 else if (SCM_BIGP (n))
1709 {
1710 generalcase:
1711 {
1712 SCM num1 = SCM_MAKINUM (1L);
1713 SCM num2 = SCM_MAKINUM (2L);
1714 SCM bits = SCM_MAKINUM (iend - istart);
1715 SCM mask = scm_difference (scm_integer_expt (num2, bits), num1);
1716 return scm_logand (mask, scm_ash (n, SCM_MAKINUM (-istart)));
1717 }
1718 }
1719 else
1720 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1721 }
1722 #undef FUNC_NAME
1723
1724 static const char scm_logtab[] = {
1725 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
1726 };
1727
1728 SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
1729 (SCM n),
1730 "Return the number of bits in integer @var{n}. If integer is\n"
1731 "positive, the 1-bits in its binary representation are counted.\n"
1732 "If negative, the 0-bits in its two's-complement binary\n"
1733 "representation are counted. If 0, 0 is returned.\n"
1734 "\n"
1735 "@lisp\n"
1736 "(logcount #b10101010)\n"
1737 " @result{} 4\n"
1738 "(logcount 0)\n"
1739 " @result{} 0\n"
1740 "(logcount -2)\n"
1741 " @result{} 1\n"
1742 "@end lisp")
1743 #define FUNC_NAME s_scm_logcount
1744 {
1745 if (SCM_INUMP (n))
1746 {
1747 unsigned long int c = 0;
1748 long int nn = SCM_INUM (n);
1749 if (nn < 0)
1750 nn = -1 - nn;
1751 while (nn)
1752 {
1753 c += scm_logtab[15 & nn];
1754 nn >>= 4;
1755 }
1756 return SCM_MAKINUM (c);
1757 }
1758 else if (SCM_BIGP (n))
1759 {
1760 unsigned long count;
1761 if (mpz_sgn (SCM_I_BIG_MPZ (n)) >= 0)
1762 count = mpz_popcount (SCM_I_BIG_MPZ (n));
1763 else
1764 count = mpz_hamdist (SCM_I_BIG_MPZ (n), z_negative_one);
1765 scm_remember_upto_here_1 (n);
1766 return SCM_MAKINUM (count);
1767 }
1768 else
1769 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1770 }
1771 #undef FUNC_NAME
1772
1773
1774 static const char scm_ilentab[] = {
1775 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
1776 };
1777
1778
1779 SCM_DEFINE (scm_integer_length, "integer-length", 1, 0, 0,
1780 (SCM n),
1781 "Return the number of bits necessary to represent @var{n}.\n"
1782 "\n"
1783 "@lisp\n"
1784 "(integer-length #b10101010)\n"
1785 " @result{} 8\n"
1786 "(integer-length 0)\n"
1787 " @result{} 0\n"
1788 "(integer-length #b1111)\n"
1789 " @result{} 4\n"
1790 "@end lisp")
1791 #define FUNC_NAME s_scm_integer_length
1792 {
1793 if (SCM_INUMP (n))
1794 {
1795 unsigned long int c = 0;
1796 unsigned int l = 4;
1797 long int nn = SCM_INUM (n);
1798 if (nn < 0)
1799 nn = -1 - nn;
1800 while (nn)
1801 {
1802 c += 4;
1803 l = scm_ilentab [15 & nn];
1804 nn >>= 4;
1805 }
1806 return SCM_MAKINUM (c - 4 + l);
1807 }
1808 else if (SCM_BIGP (n))
1809 {
1810 /* mpz_sizeinbase looks at the absolute value of negatives, whereas we
1811 want a ones-complement. If n is ...111100..00 then mpz_sizeinbase is
1812 1 too big, so check for that and adjust. */
1813 size_t size = mpz_sizeinbase (SCM_I_BIG_MPZ (n), 2);
1814 if (mpz_sgn (SCM_I_BIG_MPZ (n)) < 0
1815 && mpz_scan0 (SCM_I_BIG_MPZ (n), /* no 0 bits above the lowest 1 */
1816 mpz_scan1 (SCM_I_BIG_MPZ (n), 0)) == ULONG_MAX)
1817 size--;
1818 scm_remember_upto_here_1 (n);
1819 return SCM_MAKINUM (size);
1820 }
1821 else
1822 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1823 }
1824 #undef FUNC_NAME
1825
1826 /*** NUMBERS -> STRINGS ***/
1827 int scm_dblprec;
1828 static const double fx[] =
1829 { 0.0, 5e-1, 5e-2, 5e-3, 5e-4, 5e-5,
1830 5e-6, 5e-7, 5e-8, 5e-9, 5e-10,
1831 5e-11, 5e-12, 5e-13, 5e-14, 5e-15,
1832 5e-16, 5e-17, 5e-18, 5e-19, 5e-20};
1833
1834 static size_t
1835 idbl2str (double f, char *a)
1836 {
1837 int efmt, dpt, d, i, wp = scm_dblprec;
1838 size_t ch = 0;
1839 int exp = 0;
1840
1841 if (f == 0.0)
1842 {
1843 #ifdef HAVE_COPYSIGN
1844 double sgn = copysign (1.0, f);
1845
1846 if (sgn < 0.0)
1847 a[ch++] = '-';
1848 #endif
1849
1850 goto zero; /*{a[0]='0'; a[1]='.'; a[2]='0'; return 3;} */
1851 }
1852
1853 if (xisinf (f))
1854 {
1855 if (f < 0)
1856 strcpy (a, "-inf.0");
1857 else
1858 strcpy (a, "+inf.0");
1859 return ch+6;
1860 }
1861 else if (xisnan (f))
1862 {
1863 strcpy (a, "+nan.0");
1864 return ch+6;
1865 }
1866
1867 if (f < 0.0)
1868 {
1869 f = -f;
1870 a[ch++] = '-';
1871 }
1872
1873 #ifdef DBL_MIN_10_EXP /* Prevent unnormalized values, as from
1874 make-uniform-vector, from causing infinite loops. */
1875 while (f < 1.0)
1876 {
1877 f *= 10.0;
1878 if (exp-- < DBL_MIN_10_EXP)
1879 {
1880 a[ch++] = '#';
1881 a[ch++] = '.';
1882 a[ch++] = '#';
1883 return ch;
1884 }
1885 }
1886 while (f > 10.0)
1887 {
1888 f *= 0.10;
1889 if (exp++ > DBL_MAX_10_EXP)
1890 {
1891 a[ch++] = '#';
1892 a[ch++] = '.';
1893 a[ch++] = '#';
1894 return ch;
1895 }
1896 }
1897 #else
1898 while (f < 1.0)
1899 {
1900 f *= 10.0;
1901 exp--;
1902 }
1903 while (f > 10.0)
1904 {
1905 f /= 10.0;
1906 exp++;
1907 }
1908 #endif
1909 if (f + fx[wp] >= 10.0)
1910 {
1911 f = 1.0;
1912 exp++;
1913 }
1914 zero:
1915 #ifdef ENGNOT
1916 dpt = (exp + 9999) % 3;
1917 exp -= dpt++;
1918 efmt = 1;
1919 #else
1920 efmt = (exp < -3) || (exp > wp + 2);
1921 if (!efmt)
1922 {
1923 if (exp < 0)
1924 {
1925 a[ch++] = '0';
1926 a[ch++] = '.';
1927 dpt = exp;
1928 while (++dpt)
1929 a[ch++] = '0';
1930 }
1931 else
1932 dpt = exp + 1;
1933 }
1934 else
1935 dpt = 1;
1936 #endif
1937
1938 do
1939 {
1940 d = f;
1941 f -= d;
1942 a[ch++] = d + '0';
1943 if (f < fx[wp])
1944 break;
1945 if (f + fx[wp] >= 1.0)
1946 {
1947 a[ch - 1]++;
1948 break;
1949 }
1950 f *= 10.0;
1951 if (!(--dpt))
1952 a[ch++] = '.';
1953 }
1954 while (wp--);
1955
1956 if (dpt > 0)
1957 {
1958 #ifndef ENGNOT
1959 if ((dpt > 4) && (exp > 6))
1960 {
1961 d = (a[0] == '-' ? 2 : 1);
1962 for (i = ch++; i > d; i--)
1963 a[i] = a[i - 1];
1964 a[d] = '.';
1965 efmt = 1;
1966 }
1967 else
1968 #endif
1969 {
1970 while (--dpt)
1971 a[ch++] = '0';
1972 a[ch++] = '.';
1973 }
1974 }
1975 if (a[ch - 1] == '.')
1976 a[ch++] = '0'; /* trailing zero */
1977 if (efmt && exp)
1978 {
1979 a[ch++] = 'e';
1980 if (exp < 0)
1981 {
1982 exp = -exp;
1983 a[ch++] = '-';
1984 }
1985 for (i = 10; i <= exp; i *= 10);
1986 for (i /= 10; i; i /= 10)
1987 {
1988 a[ch++] = exp / i + '0';
1989 exp %= i;
1990 }
1991 }
1992 return ch;
1993 }
1994
1995
1996 static size_t
1997 iflo2str (SCM flt, char *str)
1998 {
1999 size_t i;
2000 if (SCM_REALP (flt))
2001 i = idbl2str (SCM_REAL_VALUE (flt), str);
2002 else
2003 {
2004 i = idbl2str (SCM_COMPLEX_REAL (flt), str);
2005 if (SCM_COMPLEX_IMAG (flt) != 0.0)
2006 {
2007 double imag = SCM_COMPLEX_IMAG (flt);
2008 /* Don't output a '+' for negative numbers or for Inf and
2009 NaN. They will provide their own sign. */
2010 if (0 <= imag && !xisinf (imag) && !xisnan (imag))
2011 str[i++] = '+';
2012 i += idbl2str (imag, &str[i]);
2013 str[i++] = 'i';
2014 }
2015 }
2016 return i;
2017 }
2018
2019 /* convert a long to a string (unterminated). returns the number of
2020 characters in the result.
2021 rad is output base
2022 p is destination: worst case (base 2) is SCM_INTBUFLEN */
2023 size_t
2024 scm_iint2str (long num, int rad, char *p)
2025 {
2026 size_t j = 1;
2027 size_t i;
2028 unsigned long n = (num < 0) ? -num : num;
2029
2030 for (n /= rad; n > 0; n /= rad)
2031 j++;
2032
2033 i = j;
2034 if (num < 0)
2035 {
2036 *p++ = '-';
2037 j++;
2038 n = -num;
2039 }
2040 else
2041 n = num;
2042 while (i--)
2043 {
2044 int d = n % rad;
2045
2046 n /= rad;
2047 p[i] = d + ((d < 10) ? '0' : 'a' - 10);
2048 }
2049 return j;
2050 }
2051
2052 SCM_DEFINE (scm_number_to_string, "number->string", 1, 1, 0,
2053 (SCM n, SCM radix),
2054 "Return a string holding the external representation of the\n"
2055 "number @var{n} in the given @var{radix}. If @var{n} is\n"
2056 "inexact, a radix of 10 will be used.")
2057 #define FUNC_NAME s_scm_number_to_string
2058 {
2059 int base;
2060
2061 if (SCM_UNBNDP (radix))
2062 base = 10;
2063 else
2064 {
2065 SCM_VALIDATE_INUM (2, radix);
2066 base = SCM_INUM (radix);
2067 /* FIXME: ask if range limit was OK, and if so, document */
2068 SCM_ASSERT_RANGE (2, radix, (base >= 2) && (base <= 36));
2069 }
2070
2071 if (SCM_INUMP (n))
2072 {
2073 char num_buf [SCM_INTBUFLEN];
2074 size_t length = scm_iint2str (SCM_INUM (n), base, num_buf);
2075 return scm_mem2string (num_buf, length);
2076 }
2077 else if (SCM_BIGP (n))
2078 {
2079 char *str = mpz_get_str (NULL, base, SCM_I_BIG_MPZ (n));
2080 scm_remember_upto_here_1 (n);
2081 return scm_take0str (str);
2082 }
2083 else if (SCM_FRACTIONP (n))
2084 {
2085 scm_i_fraction_reduce (n);
2086 return scm_string_append (scm_list_3 (scm_number_to_string (SCM_FRACTION_NUMERATOR (n), radix),
2087 scm_mem2string ("/", 1),
2088 scm_number_to_string (SCM_FRACTION_DENOMINATOR (n), radix)));
2089 }
2090 else if (SCM_INEXACTP (n))
2091 {
2092 char num_buf [FLOBUFLEN];
2093 return scm_mem2string (num_buf, iflo2str (n, num_buf));
2094 }
2095 else
2096 SCM_WRONG_TYPE_ARG (1, n);
2097 }
2098 #undef FUNC_NAME
2099
2100
2101 /* These print routines used to be stubbed here so that scm_repl.c
2102 wouldn't need SCM_BIGDIG conditionals (pre GMP) */
2103
2104 int
2105 scm_print_real (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
2106 {
2107 char num_buf[FLOBUFLEN];
2108 scm_lfwrite (num_buf, iflo2str (sexp, num_buf), port);
2109 return !0;
2110 }
2111
2112 int
2113 scm_print_complex (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
2114
2115 {
2116 char num_buf[FLOBUFLEN];
2117 scm_lfwrite (num_buf, iflo2str (sexp, num_buf), port);
2118 return !0;
2119 }
2120
2121 int
2122 scm_i_print_fraction (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
2123 {
2124 SCM str;
2125 scm_i_fraction_reduce (sexp);
2126 str = scm_number_to_string (sexp, SCM_UNDEFINED);
2127 scm_lfwrite (SCM_STRING_CHARS (str), SCM_STRING_LENGTH (str), port);
2128 scm_remember_upto_here_1 (str);
2129 return !0;
2130 }
2131
2132 int
2133 scm_bigprint (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
2134 {
2135 char *str = mpz_get_str (NULL, 10, SCM_I_BIG_MPZ (exp));
2136 scm_remember_upto_here_1 (exp);
2137 scm_lfwrite (str, (size_t) strlen (str), port);
2138 free (str);
2139 return !0;
2140 }
2141 /*** END nums->strs ***/
2142
2143
2144 /*** STRINGS -> NUMBERS ***/
2145
2146 /* The following functions implement the conversion from strings to numbers.
2147 * The implementation somehow follows the grammar for numbers as it is given
2148 * in R5RS. Thus, the functions resemble syntactic units (<ureal R>,
2149 * <uinteger R>, ...) that are used to build up numbers in the grammar. Some
2150 * points should be noted about the implementation:
2151 * * Each function keeps a local index variable 'idx' that points at the
2152 * current position within the parsed string. The global index is only
2153 * updated if the function could parse the corresponding syntactic unit
2154 * successfully.
2155 * * Similarly, the functions keep track of indicators of inexactness ('#',
2156 * '.' or exponents) using local variables ('hash_seen', 'x'). Again, the
2157 * global exactness information is only updated after each part has been
2158 * successfully parsed.
2159 * * Sequences of digits are parsed into temporary variables holding fixnums.
2160 * Only if these fixnums would overflow, the result variables are updated
2161 * using the standard functions scm_add, scm_product, scm_divide etc. Then,
2162 * the temporary variables holding the fixnums are cleared, and the process
2163 * starts over again. If for example fixnums were able to store five decimal
2164 * digits, a number 1234567890 would be parsed in two parts 12345 and 67890,
2165 * and the result was computed as 12345 * 100000 + 67890. In other words,
2166 * only every five digits two bignum operations were performed.
2167 */
2168
2169 enum t_exactness {NO_EXACTNESS, INEXACT, EXACT};
2170
2171 /* R5RS, section 7.1.1, lexical structure of numbers: <uinteger R>. */
2172
2173 /* In non ASCII-style encodings the following macro might not work. */
2174 #define XDIGIT2UINT(d) (isdigit (d) ? (d) - '0' : tolower (d) - 'a' + 10)
2175
2176 static SCM
2177 mem2uinteger (const char* mem, size_t len, unsigned int *p_idx,
2178 unsigned int radix, enum t_exactness *p_exactness)
2179 {
2180 unsigned int idx = *p_idx;
2181 unsigned int hash_seen = 0;
2182 scm_t_bits shift = 1;
2183 scm_t_bits add = 0;
2184 unsigned int digit_value;
2185 SCM result;
2186 char c;
2187
2188 if (idx == len)
2189 return SCM_BOOL_F;
2190
2191 c = mem[idx];
2192 if (!isxdigit (c))
2193 return SCM_BOOL_F;
2194 digit_value = XDIGIT2UINT (c);
2195 if (digit_value >= radix)
2196 return SCM_BOOL_F;
2197
2198 idx++;
2199 result = SCM_MAKINUM (digit_value);
2200 while (idx != len)
2201 {
2202 char c = mem[idx];
2203 if (isxdigit (c))
2204 {
2205 if (hash_seen)
2206 break;
2207 digit_value = XDIGIT2UINT (c);
2208 if (digit_value >= radix)
2209 break;
2210 }
2211 else if (c == '#')
2212 {
2213 hash_seen = 1;
2214 digit_value = 0;
2215 }
2216 else
2217 break;
2218
2219 idx++;
2220 if (SCM_MOST_POSITIVE_FIXNUM / radix < shift)
2221 {
2222 result = scm_product (result, SCM_MAKINUM (shift));
2223 if (add > 0)
2224 result = scm_sum (result, SCM_MAKINUM (add));
2225
2226 shift = radix;
2227 add = digit_value;
2228 }
2229 else
2230 {
2231 shift = shift * radix;
2232 add = add * radix + digit_value;
2233 }
2234 };
2235
2236 if (shift > 1)
2237 result = scm_product (result, SCM_MAKINUM (shift));
2238 if (add > 0)
2239 result = scm_sum (result, SCM_MAKINUM (add));
2240
2241 *p_idx = idx;
2242 if (hash_seen)
2243 *p_exactness = INEXACT;
2244
2245 return result;
2246 }
2247
2248
2249 /* R5RS, section 7.1.1, lexical structure of numbers: <decimal 10>. Only
2250 * covers the parts of the rules that start at a potential point. The value
2251 * of the digits up to the point have been parsed by the caller and are given
2252 * in variable result. The content of *p_exactness indicates, whether a hash
2253 * has already been seen in the digits before the point.
2254 */
2255
2256 /* In non ASCII-style encodings the following macro might not work. */
2257 #define DIGIT2UINT(d) ((d) - '0')
2258
2259 static SCM
2260 mem2decimal_from_point (SCM result, const char* mem, size_t len,
2261 unsigned int *p_idx, enum t_exactness *p_exactness)
2262 {
2263 unsigned int idx = *p_idx;
2264 enum t_exactness x = *p_exactness;
2265
2266 if (idx == len)
2267 return result;
2268
2269 if (mem[idx] == '.')
2270 {
2271 scm_t_bits shift = 1;
2272 scm_t_bits add = 0;
2273 unsigned int digit_value;
2274 SCM big_shift = SCM_MAKINUM (1);
2275
2276 idx++;
2277 while (idx != len)
2278 {
2279 char c = mem[idx];
2280 if (isdigit (c))
2281 {
2282 if (x == INEXACT)
2283 return SCM_BOOL_F;
2284 else
2285 digit_value = DIGIT2UINT (c);
2286 }
2287 else if (c == '#')
2288 {
2289 x = INEXACT;
2290 digit_value = 0;
2291 }
2292 else
2293 break;
2294
2295 idx++;
2296 if (SCM_MOST_POSITIVE_FIXNUM / 10 < shift)
2297 {
2298 big_shift = scm_product (big_shift, SCM_MAKINUM (shift));
2299 result = scm_product (result, SCM_MAKINUM (shift));
2300 if (add > 0)
2301 result = scm_sum (result, SCM_MAKINUM (add));
2302
2303 shift = 10;
2304 add = digit_value;
2305 }
2306 else
2307 {
2308 shift = shift * 10;
2309 add = add * 10 + digit_value;
2310 }
2311 };
2312
2313 if (add > 0)
2314 {
2315 big_shift = scm_product (big_shift, SCM_MAKINUM (shift));
2316 result = scm_product (result, SCM_MAKINUM (shift));
2317 result = scm_sum (result, SCM_MAKINUM (add));
2318 }
2319
2320 result = scm_divide (result, big_shift);
2321
2322 /* We've seen a decimal point, thus the value is implicitly inexact. */
2323 x = INEXACT;
2324 }
2325
2326 if (idx != len)
2327 {
2328 int sign = 1;
2329 unsigned int start;
2330 char c;
2331 int exponent;
2332 SCM e;
2333
2334 /* R5RS, section 7.1.1, lexical structure of numbers: <suffix> */
2335
2336 switch (mem[idx])
2337 {
2338 case 'd': case 'D':
2339 case 'e': case 'E':
2340 case 'f': case 'F':
2341 case 'l': case 'L':
2342 case 's': case 'S':
2343 idx++;
2344 start = idx;
2345 c = mem[idx];
2346 if (c == '-')
2347 {
2348 idx++;
2349 sign = -1;
2350 c = mem[idx];
2351 }
2352 else if (c == '+')
2353 {
2354 idx++;
2355 sign = 1;
2356 c = mem[idx];
2357 }
2358 else
2359 sign = 1;
2360
2361 if (!isdigit (c))
2362 return SCM_BOOL_F;
2363
2364 idx++;
2365 exponent = DIGIT2UINT (c);
2366 while (idx != len)
2367 {
2368 char c = mem[idx];
2369 if (isdigit (c))
2370 {
2371 idx++;
2372 if (exponent <= SCM_MAXEXP)
2373 exponent = exponent * 10 + DIGIT2UINT (c);
2374 }
2375 else
2376 break;
2377 }
2378
2379 if (exponent > SCM_MAXEXP)
2380 {
2381 size_t exp_len = idx - start;
2382 SCM exp_string = scm_mem2string (&mem[start], exp_len);
2383 SCM exp_num = scm_string_to_number (exp_string, SCM_UNDEFINED);
2384 scm_out_of_range ("string->number", exp_num);
2385 }
2386
2387 e = scm_integer_expt (SCM_MAKINUM (10), SCM_MAKINUM (exponent));
2388 if (sign == 1)
2389 result = scm_product (result, e);
2390 else
2391 result = scm_divide2real (result, e);
2392
2393 /* We've seen an exponent, thus the value is implicitly inexact. */
2394 x = INEXACT;
2395
2396 break;
2397
2398 default:
2399 break;
2400 }
2401 }
2402
2403 *p_idx = idx;
2404 if (x == INEXACT)
2405 *p_exactness = x;
2406
2407 return result;
2408 }
2409
2410
2411 /* R5RS, section 7.1.1, lexical structure of numbers: <ureal R> */
2412
2413 static SCM
2414 mem2ureal (const char* mem, size_t len, unsigned int *p_idx,
2415 unsigned int radix, enum t_exactness *p_exactness)
2416 {
2417 unsigned int idx = *p_idx;
2418 SCM result;
2419
2420 if (idx == len)
2421 return SCM_BOOL_F;
2422
2423 if (idx+5 <= len && !strncmp (mem+idx, "inf.0", 5))
2424 {
2425 *p_idx = idx+5;
2426 return scm_inf ();
2427 }
2428
2429 if (idx+4 < len && !strncmp (mem+idx, "nan.", 4))
2430 {
2431 enum t_exactness x = EXACT;
2432
2433 /* Cobble up the fractional part. We might want to set the
2434 NaN's mantissa from it. */
2435 idx += 4;
2436 mem2uinteger (mem, len, &idx, 10, &x);
2437 *p_idx = idx;
2438 return scm_nan ();
2439 }
2440
2441 if (mem[idx] == '.')
2442 {
2443 if (radix != 10)
2444 return SCM_BOOL_F;
2445 else if (idx + 1 == len)
2446 return SCM_BOOL_F;
2447 else if (!isdigit (mem[idx + 1]))
2448 return SCM_BOOL_F;
2449 else
2450 result = mem2decimal_from_point (SCM_MAKINUM (0), mem, len,
2451 p_idx, p_exactness);
2452 }
2453 else
2454 {
2455 enum t_exactness x = EXACT;
2456 SCM uinteger;
2457
2458 uinteger = mem2uinteger (mem, len, &idx, radix, &x);
2459 if (SCM_FALSEP (uinteger))
2460 return SCM_BOOL_F;
2461
2462 if (idx == len)
2463 result = uinteger;
2464 else if (mem[idx] == '/')
2465 {
2466 SCM divisor;
2467
2468 idx++;
2469
2470 divisor = mem2uinteger (mem, len, &idx, radix, &x);
2471 if (SCM_FALSEP (divisor))
2472 return SCM_BOOL_F;
2473
2474 /* both are int/big here, I assume */
2475 result = scm_make_ratio (uinteger, divisor);
2476 }
2477 else if (radix == 10)
2478 {
2479 result = mem2decimal_from_point (uinteger, mem, len, &idx, &x);
2480 if (SCM_FALSEP (result))
2481 return SCM_BOOL_F;
2482 }
2483 else
2484 result = uinteger;
2485
2486 *p_idx = idx;
2487 if (x == INEXACT)
2488 *p_exactness = x;
2489 }
2490
2491 /* When returning an inexact zero, make sure it is represented as a
2492 floating point value so that we can change its sign.
2493 */
2494 if (SCM_EQ_P (result, SCM_MAKINUM(0)) && *p_exactness == INEXACT)
2495 result = scm_make_real (0.0);
2496
2497 return result;
2498 }
2499
2500
2501 /* R5RS, section 7.1.1, lexical structure of numbers: <complex R> */
2502
2503 static SCM
2504 mem2complex (const char* mem, size_t len, unsigned int idx,
2505 unsigned int radix, enum t_exactness *p_exactness)
2506 {
2507 char c;
2508 int sign = 0;
2509 SCM ureal;
2510
2511 if (idx == len)
2512 return SCM_BOOL_F;
2513
2514 c = mem[idx];
2515 if (c == '+')
2516 {
2517 idx++;
2518 sign = 1;
2519 }
2520 else if (c == '-')
2521 {
2522 idx++;
2523 sign = -1;
2524 }
2525
2526 if (idx == len)
2527 return SCM_BOOL_F;
2528
2529 ureal = mem2ureal (mem, len, &idx, radix, p_exactness);
2530 if (SCM_FALSEP (ureal))
2531 {
2532 /* input must be either +i or -i */
2533
2534 if (sign == 0)
2535 return SCM_BOOL_F;
2536
2537 if (mem[idx] == 'i' || mem[idx] == 'I')
2538 {
2539 idx++;
2540 if (idx != len)
2541 return SCM_BOOL_F;
2542
2543 return scm_make_rectangular (SCM_MAKINUM (0), SCM_MAKINUM (sign));
2544 }
2545 else
2546 return SCM_BOOL_F;
2547 }
2548 else
2549 {
2550 if (sign == -1 && SCM_FALSEP (scm_nan_p (ureal)))
2551 ureal = scm_difference (ureal, SCM_UNDEFINED);
2552
2553 if (idx == len)
2554 return ureal;
2555
2556 c = mem[idx];
2557 switch (c)
2558 {
2559 case 'i': case 'I':
2560 /* either +<ureal>i or -<ureal>i */
2561
2562 idx++;
2563 if (sign == 0)
2564 return SCM_BOOL_F;
2565 if (idx != len)
2566 return SCM_BOOL_F;
2567 return scm_make_rectangular (SCM_MAKINUM (0), ureal);
2568
2569 case '@':
2570 /* polar input: <real>@<real>. */
2571
2572 idx++;
2573 if (idx == len)
2574 return SCM_BOOL_F;
2575 else
2576 {
2577 int sign;
2578 SCM angle;
2579 SCM result;
2580
2581 c = mem[idx];
2582 if (c == '+')
2583 {
2584 idx++;
2585 sign = 1;
2586 }
2587 else if (c == '-')
2588 {
2589 idx++;
2590 sign = -1;
2591 }
2592 else
2593 sign = 1;
2594
2595 angle = mem2ureal (mem, len, &idx, radix, p_exactness);
2596 if (SCM_FALSEP (angle))
2597 return SCM_BOOL_F;
2598 if (idx != len)
2599 return SCM_BOOL_F;
2600
2601 if (sign == -1 && SCM_FALSEP (scm_nan_p (ureal)))
2602 angle = scm_difference (angle, SCM_UNDEFINED);
2603
2604 result = scm_make_polar (ureal, angle);
2605 return result;
2606 }
2607 case '+':
2608 case '-':
2609 /* expecting input matching <real>[+-]<ureal>?i */
2610
2611 idx++;
2612 if (idx == len)
2613 return SCM_BOOL_F;
2614 else
2615 {
2616 int sign = (c == '+') ? 1 : -1;
2617 SCM imag = mem2ureal (mem, len, &idx, radix, p_exactness);
2618
2619 if (SCM_FALSEP (imag))
2620 imag = SCM_MAKINUM (sign);
2621 else if (sign == -1 && SCM_FALSEP (scm_nan_p (ureal)))
2622 imag = scm_difference (imag, SCM_UNDEFINED);
2623
2624 if (idx == len)
2625 return SCM_BOOL_F;
2626 if (mem[idx] != 'i' && mem[idx] != 'I')
2627 return SCM_BOOL_F;
2628
2629 idx++;
2630 if (idx != len)
2631 return SCM_BOOL_F;
2632
2633 return scm_make_rectangular (ureal, imag);
2634 }
2635 default:
2636 return SCM_BOOL_F;
2637 }
2638 }
2639 }
2640
2641
2642 /* R5RS, section 7.1.1, lexical structure of numbers: <number> */
2643
2644 enum t_radix {NO_RADIX=0, DUAL=2, OCT=8, DEC=10, HEX=16};
2645
2646 SCM
2647 scm_i_mem2number (const char* mem, size_t len, unsigned int default_radix)
2648 {
2649 unsigned int idx = 0;
2650 unsigned int radix = NO_RADIX;
2651 enum t_exactness forced_x = NO_EXACTNESS;
2652 enum t_exactness implicit_x = EXACT;
2653 SCM result;
2654
2655 /* R5RS, section 7.1.1, lexical structure of numbers: <prefix R> */
2656 while (idx + 2 < len && mem[idx] == '#')
2657 {
2658 switch (mem[idx + 1])
2659 {
2660 case 'b': case 'B':
2661 if (radix != NO_RADIX)
2662 return SCM_BOOL_F;
2663 radix = DUAL;
2664 break;
2665 case 'd': case 'D':
2666 if (radix != NO_RADIX)
2667 return SCM_BOOL_F;
2668 radix = DEC;
2669 break;
2670 case 'i': case 'I':
2671 if (forced_x != NO_EXACTNESS)
2672 return SCM_BOOL_F;
2673 forced_x = INEXACT;
2674 break;
2675 case 'e': case 'E':
2676 if (forced_x != NO_EXACTNESS)
2677 return SCM_BOOL_F;
2678 forced_x = EXACT;
2679 break;
2680 case 'o': case 'O':
2681 if (radix != NO_RADIX)
2682 return SCM_BOOL_F;
2683 radix = OCT;
2684 break;
2685 case 'x': case 'X':
2686 if (radix != NO_RADIX)
2687 return SCM_BOOL_F;
2688 radix = HEX;
2689 break;
2690 default:
2691 return SCM_BOOL_F;
2692 }
2693 idx += 2;
2694 }
2695
2696 /* R5RS, section 7.1.1, lexical structure of numbers: <complex R> */
2697 if (radix == NO_RADIX)
2698 result = mem2complex (mem, len, idx, default_radix, &implicit_x);
2699 else
2700 result = mem2complex (mem, len, idx, (unsigned int) radix, &implicit_x);
2701
2702 if (SCM_FALSEP (result))
2703 return SCM_BOOL_F;
2704
2705 switch (forced_x)
2706 {
2707 case EXACT:
2708 if (SCM_INEXACTP (result))
2709 return scm_inexact_to_exact (result);
2710 else
2711 return result;
2712 case INEXACT:
2713 if (SCM_INEXACTP (result))
2714 return result;
2715 else
2716 return scm_exact_to_inexact (result);
2717 case NO_EXACTNESS:
2718 default:
2719 if (implicit_x == INEXACT)
2720 {
2721 if (SCM_INEXACTP (result))
2722 return result;
2723 else
2724 return scm_exact_to_inexact (result);
2725 }
2726 else
2727 return result;
2728 }
2729 }
2730
2731
2732 SCM_DEFINE (scm_string_to_number, "string->number", 1, 1, 0,
2733 (SCM string, SCM radix),
2734 "Return a number of the maximally precise representation\n"
2735 "expressed by the given @var{string}. @var{radix} must be an\n"
2736 "exact integer, either 2, 8, 10, or 16. If supplied, @var{radix}\n"
2737 "is a default radix that may be overridden by an explicit radix\n"
2738 "prefix in @var{string} (e.g. \"#o177\"). If @var{radix} is not\n"
2739 "supplied, then the default radix is 10. If string is not a\n"
2740 "syntactically valid notation for a number, then\n"
2741 "@code{string->number} returns @code{#f}.")
2742 #define FUNC_NAME s_scm_string_to_number
2743 {
2744 SCM answer;
2745 int base;
2746 SCM_VALIDATE_STRING (1, string);
2747 SCM_VALIDATE_INUM_MIN_DEF_COPY (2, radix,2,10, base);
2748 answer = scm_i_mem2number (SCM_STRING_CHARS (string),
2749 SCM_STRING_LENGTH (string),
2750 base);
2751 return scm_return_first (answer, string);
2752 }
2753 #undef FUNC_NAME
2754
2755
2756 /*** END strs->nums ***/
2757
2758
2759 SCM
2760 scm_make_real (double x)
2761 {
2762 SCM z = scm_double_cell (scm_tc16_real, 0, 0, 0);
2763
2764 SCM_REAL_VALUE (z) = x;
2765 return z;
2766 }
2767
2768
2769 SCM
2770 scm_make_complex (double x, double y)
2771 {
2772 if (y == 0.0)
2773 return scm_make_real (x);
2774 else
2775 {
2776 SCM z;
2777 SCM_NEWSMOB (z, scm_tc16_complex, scm_gc_malloc (sizeof (scm_t_complex),
2778 "complex"));
2779 SCM_COMPLEX_REAL (z) = x;
2780 SCM_COMPLEX_IMAG (z) = y;
2781 return z;
2782 }
2783 }
2784
2785
2786 SCM
2787 scm_bigequal (SCM x, SCM y)
2788 {
2789 int result = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2790 scm_remember_upto_here_2 (x, y);
2791 return SCM_BOOL (0 == result);
2792 }
2793
2794 SCM
2795 scm_real_equalp (SCM x, SCM y)
2796 {
2797 return SCM_BOOL (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
2798 }
2799
2800 SCM
2801 scm_complex_equalp (SCM x, SCM y)
2802 {
2803 return SCM_BOOL (SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y)
2804 && SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y));
2805 }
2806
2807 SCM
2808 scm_i_fraction_equalp (SCM x, SCM y)
2809 {
2810 scm_i_fraction_reduce (x);
2811 scm_i_fraction_reduce (y);
2812 if (SCM_FALSEP (scm_equal_p (SCM_FRACTION_NUMERATOR (x),
2813 SCM_FRACTION_NUMERATOR (y)))
2814 || SCM_FALSEP (scm_equal_p (SCM_FRACTION_DENOMINATOR (x),
2815 SCM_FRACTION_DENOMINATOR (y))))
2816 return SCM_BOOL_F;
2817 else
2818 return SCM_BOOL_T;
2819 }
2820
2821
2822 SCM_REGISTER_PROC (s_number_p, "number?", 1, 0, 0, scm_number_p);
2823 /* "Return @code{#t} if @var{x} is a number, @code{#f}\n"
2824 * "else. Note that the sets of complex, real, rational and\n"
2825 * "integer values form subsets of the set of numbers, i. e. the\n"
2826 * "predicate will be fulfilled for any number."
2827 */
2828 SCM_DEFINE (scm_number_p, "complex?", 1, 0, 0,
2829 (SCM x),
2830 "Return @code{#t} if @var{x} is a complex number, @code{#f}\n"
2831 "otherwise. Note that the sets of real, rational and integer\n"
2832 "values form subsets of the set of complex numbers, i. e. the\n"
2833 "predicate will also be fulfilled if @var{x} is a real,\n"
2834 "rational or integer number.")
2835 #define FUNC_NAME s_scm_number_p
2836 {
2837 return SCM_BOOL (SCM_NUMBERP (x));
2838 }
2839 #undef FUNC_NAME
2840
2841
2842 SCM_DEFINE (scm_real_p, "real?", 1, 0, 0,
2843 (SCM x),
2844 "Return @code{#t} if @var{x} is a real number, @code{#f}\n"
2845 "otherwise. Note that the set of integer values forms a subset of\n"
2846 "the set of real numbers, i. e. the predicate will also be\n"
2847 "fulfilled if @var{x} is an integer number.")
2848 #define FUNC_NAME s_scm_real_p
2849 {
2850 /* we can't represent irrational numbers. */
2851 return scm_rational_p (x);
2852 }
2853 #undef FUNC_NAME
2854
2855 SCM_DEFINE (scm_rational_p, "rational?", 1, 0, 0,
2856 (SCM x),
2857 "Return @code{#t} if @var{x} is a rational number, @code{#f}\n"
2858 "otherwise. Note that the set of integer values forms a subset of\n"
2859 "the set of rational numbers, i. e. the predicate will also be\n"
2860 "fulfilled if @var{x} is an integer number.")
2861 #define FUNC_NAME s_scm_rational_p
2862 {
2863 if (SCM_INUMP (x))
2864 return SCM_BOOL_T;
2865 else if (SCM_IMP (x))
2866 return SCM_BOOL_F;
2867 else if (SCM_BIGP (x))
2868 return SCM_BOOL_T;
2869 else if (SCM_FRACTIONP (x))
2870 return SCM_BOOL_T;
2871 else if (SCM_REALP (x))
2872 /* due to their limited precision, all floating point numbers are
2873 rational as well. */
2874 return SCM_BOOL_T;
2875 else
2876 return SCM_BOOL_F;
2877 }
2878 #undef FUNC_NAME
2879
2880
2881 SCM_DEFINE (scm_integer_p, "integer?", 1, 0, 0,
2882 (SCM x),
2883 "Return @code{#t} if @var{x} is an integer number, @code{#f}\n"
2884 "else.")
2885 #define FUNC_NAME s_scm_integer_p
2886 {
2887 double r;
2888 if (SCM_INUMP (x))
2889 return SCM_BOOL_T;
2890 if (SCM_IMP (x))
2891 return SCM_BOOL_F;
2892 if (SCM_BIGP (x))
2893 return SCM_BOOL_T;
2894 if (!SCM_INEXACTP (x))
2895 return SCM_BOOL_F;
2896 if (SCM_COMPLEXP (x))
2897 return SCM_BOOL_F;
2898 r = SCM_REAL_VALUE (x);
2899 if (r == floor (r))
2900 return SCM_BOOL_T;
2901 return SCM_BOOL_F;
2902 }
2903 #undef FUNC_NAME
2904
2905
2906 SCM_DEFINE (scm_inexact_p, "inexact?", 1, 0, 0,
2907 (SCM x),
2908 "Return @code{#t} if @var{x} is an inexact number, @code{#f}\n"
2909 "else.")
2910 #define FUNC_NAME s_scm_inexact_p
2911 {
2912 if (SCM_INEXACTP (x))
2913 return SCM_BOOL_T;
2914 if (SCM_NUMBERP (x))
2915 return SCM_BOOL_F;
2916 SCM_WRONG_TYPE_ARG (1, x);
2917 }
2918 #undef FUNC_NAME
2919
2920
2921 SCM_GPROC1 (s_eq_p, "=", scm_tc7_rpsubr, scm_num_eq_p, g_eq_p);
2922 /* "Return @code{#t} if all parameters are numerically equal." */
2923 SCM
2924 scm_num_eq_p (SCM x, SCM y)
2925 {
2926 if (SCM_INUMP (x))
2927 {
2928 long xx = SCM_INUM (x);
2929 if (SCM_INUMP (y))
2930 {
2931 long yy = SCM_INUM (y);
2932 return SCM_BOOL (xx == yy);
2933 }
2934 else if (SCM_BIGP (y))
2935 return SCM_BOOL_F;
2936 else if (SCM_REALP (y))
2937 return SCM_BOOL ((double) xx == SCM_REAL_VALUE (y));
2938 else if (SCM_COMPLEXP (y))
2939 return SCM_BOOL (((double) xx == SCM_COMPLEX_REAL (y))
2940 && (0.0 == SCM_COMPLEX_IMAG (y)));
2941 else if (SCM_FRACTIONP (y))
2942 return SCM_BOOL_F;
2943 else
2944 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
2945 }
2946 else if (SCM_BIGP (x))
2947 {
2948 if (SCM_INUMP (y))
2949 return SCM_BOOL_F;
2950 else if (SCM_BIGP (y))
2951 {
2952 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2953 scm_remember_upto_here_2 (x, y);
2954 return SCM_BOOL (0 == cmp);
2955 }
2956 else if (SCM_REALP (y))
2957 {
2958 int cmp;
2959 if (xisnan (SCM_REAL_VALUE (y)))
2960 return SCM_BOOL_F;
2961 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
2962 scm_remember_upto_here_1 (x);
2963 return SCM_BOOL (0 == cmp);
2964 }
2965 else if (SCM_COMPLEXP (y))
2966 {
2967 int cmp;
2968 if (0.0 != SCM_COMPLEX_IMAG (y))
2969 return SCM_BOOL_F;
2970 if (xisnan (SCM_COMPLEX_REAL (y)))
2971 return SCM_BOOL_F;
2972 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_COMPLEX_REAL (y));
2973 scm_remember_upto_here_1 (x);
2974 return SCM_BOOL (0 == cmp);
2975 }
2976 else if (SCM_FRACTIONP (y))
2977 return SCM_BOOL_F;
2978 else
2979 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
2980 }
2981 else if (SCM_REALP (x))
2982 {
2983 if (SCM_INUMP (y))
2984 return SCM_BOOL (SCM_REAL_VALUE (x) == (double) SCM_INUM (y));
2985 else if (SCM_BIGP (y))
2986 {
2987 int cmp;
2988 if (xisnan (SCM_REAL_VALUE (x)))
2989 return SCM_BOOL_F;
2990 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
2991 scm_remember_upto_here_1 (y);
2992 return SCM_BOOL (0 == cmp);
2993 }
2994 else if (SCM_REALP (y))
2995 return SCM_BOOL (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
2996 else if (SCM_COMPLEXP (y))
2997 return SCM_BOOL ((SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y))
2998 && (0.0 == SCM_COMPLEX_IMAG (y)));
2999 else if (SCM_FRACTIONP (y))
3000 return SCM_BOOL (SCM_REAL_VALUE (x) == scm_i_fraction2double (y));
3001 else
3002 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
3003 }
3004 else if (SCM_COMPLEXP (x))
3005 {
3006 if (SCM_INUMP (y))
3007 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == (double) SCM_INUM (y))
3008 && (SCM_COMPLEX_IMAG (x) == 0.0));
3009 else if (SCM_BIGP (y))
3010 {
3011 int cmp;
3012 if (0.0 != SCM_COMPLEX_IMAG (x))
3013 return SCM_BOOL_F;
3014 if (xisnan (SCM_COMPLEX_REAL (x)))
3015 return SCM_BOOL_F;
3016 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_COMPLEX_REAL (x));
3017 scm_remember_upto_here_1 (y);
3018 return SCM_BOOL (0 == cmp);
3019 }
3020 else if (SCM_REALP (y))
3021 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y))
3022 && (SCM_COMPLEX_IMAG (x) == 0.0));
3023 else if (SCM_COMPLEXP (y))
3024 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y))
3025 && (SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y)));
3026 else if (SCM_FRACTIONP (y))
3027 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == scm_i_fraction2double (y))
3028 && (SCM_COMPLEX_IMAG (x) == 0.0));
3029 else
3030 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
3031 }
3032 else if (SCM_FRACTIONP (x))
3033 {
3034 if (SCM_INUMP (y))
3035 return SCM_BOOL_F;
3036 else if (SCM_BIGP (y))
3037 return SCM_BOOL_F;
3038 else if (SCM_REALP (y))
3039 return SCM_BOOL (scm_i_fraction2double (x) == SCM_REAL_VALUE (y));
3040 else if (SCM_COMPLEXP (y))
3041 return SCM_BOOL ((scm_i_fraction2double (x) == SCM_COMPLEX_REAL (y))
3042 && (0.0 == SCM_COMPLEX_IMAG (y)));
3043 else if (SCM_FRACTIONP (y))
3044 return scm_i_fraction_equalp (x, y);
3045 else
3046 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
3047 }
3048 else
3049 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARG1, s_eq_p);
3050 }
3051
3052
3053 SCM_GPROC1 (s_less_p, "<", scm_tc7_rpsubr, scm_less_p, g_less_p);
3054 /* "Return @code{#t} if the list of parameters is monotonically\n"
3055 * "increasing."
3056 */
3057 SCM
3058 scm_less_p (SCM x, SCM y)
3059 {
3060 if (SCM_INUMP (x))
3061 {
3062 long xx = SCM_INUM (x);
3063 if (SCM_INUMP (y))
3064 {
3065 long yy = SCM_INUM (y);
3066 return SCM_BOOL (xx < yy);
3067 }
3068 else if (SCM_BIGP (y))
3069 {
3070 int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
3071 scm_remember_upto_here_1 (y);
3072 return SCM_BOOL (sgn > 0);
3073 }
3074 else if (SCM_REALP (y))
3075 return SCM_BOOL ((double) xx < SCM_REAL_VALUE (y));
3076 else if (SCM_FRACTIONP (y))
3077 return SCM_BOOL ((double) xx < scm_i_fraction2double (y));
3078 else
3079 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
3080 }
3081 else if (SCM_BIGP (x))
3082 {
3083 if (SCM_INUMP (y))
3084 {
3085 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
3086 scm_remember_upto_here_1 (x);
3087 return SCM_BOOL (sgn < 0);
3088 }
3089 else if (SCM_BIGP (y))
3090 {
3091 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3092 scm_remember_upto_here_2 (x, y);
3093 return SCM_BOOL (cmp < 0);
3094 }
3095 else if (SCM_REALP (y))
3096 {
3097 int cmp;
3098 if (xisnan (SCM_REAL_VALUE (y)))
3099 return SCM_BOOL_F;
3100 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
3101 scm_remember_upto_here_1 (x);
3102 return SCM_BOOL (cmp < 0);
3103 }
3104 else if (SCM_FRACTIONP (y))
3105 {
3106 int cmp;
3107 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), scm_i_fraction2double (y));
3108 scm_remember_upto_here_1 (x);
3109 return SCM_BOOL (cmp < 0);
3110 }
3111 else
3112 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
3113 }
3114 else if (SCM_REALP (x))
3115 {
3116 if (SCM_INUMP (y))
3117 return SCM_BOOL (SCM_REAL_VALUE (x) < (double) SCM_INUM (y));
3118 else if (SCM_BIGP (y))
3119 {
3120 int cmp;
3121 if (xisnan (SCM_REAL_VALUE (x)))
3122 return SCM_BOOL_F;
3123 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
3124 scm_remember_upto_here_1 (y);
3125 return SCM_BOOL (cmp > 0);
3126 }
3127 else if (SCM_REALP (y))
3128 return SCM_BOOL (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y));
3129 else if (SCM_FRACTIONP (y))
3130 return SCM_BOOL (SCM_REAL_VALUE (x) < scm_i_fraction2double (y));
3131 else
3132 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
3133 }
3134 else if (SCM_FRACTIONP (x))
3135 {
3136 if (SCM_INUMP (y))
3137 return SCM_BOOL (scm_i_fraction2double (x) < (double) SCM_INUM (y));
3138 else if (SCM_BIGP (y))
3139 {
3140 int cmp;
3141 if (xisnan (SCM_REAL_VALUE (x)))
3142 return SCM_BOOL_F;
3143 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), scm_i_fraction2double (x));
3144 scm_remember_upto_here_1 (y);
3145 return SCM_BOOL (cmp > 0);
3146 }
3147 else if (SCM_REALP (y))
3148 return SCM_BOOL (scm_i_fraction2double (x) < SCM_REAL_VALUE (y));
3149 else if (SCM_FRACTIONP (y))
3150 return SCM_BOOL (scm_i_fraction2double (x) < scm_i_fraction2double (y));
3151 else
3152 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
3153 }
3154 else
3155 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARG1, s_less_p);
3156 }
3157
3158
3159 SCM_GPROC1 (s_scm_gr_p, ">", scm_tc7_rpsubr, scm_gr_p, g_gr_p);
3160 /* "Return @code{#t} if the list of parameters is monotonically\n"
3161 * "decreasing."
3162 */
3163 #define FUNC_NAME s_scm_gr_p
3164 SCM
3165 scm_gr_p (SCM x, SCM y)
3166 {
3167 if (!SCM_NUMBERP (x))
3168 SCM_WTA_DISPATCH_2 (g_gr_p, x, y, SCM_ARG1, FUNC_NAME);
3169 else if (!SCM_NUMBERP (y))
3170 SCM_WTA_DISPATCH_2 (g_gr_p, x, y, SCM_ARG2, FUNC_NAME);
3171 else
3172 return scm_less_p (y, x);
3173 }
3174 #undef FUNC_NAME
3175
3176
3177 SCM_GPROC1 (s_scm_leq_p, "<=", scm_tc7_rpsubr, scm_leq_p, g_leq_p);
3178 /* "Return @code{#t} if the list of parameters is monotonically\n"
3179 * "non-decreasing."
3180 */
3181 #define FUNC_NAME s_scm_leq_p
3182 SCM
3183 scm_leq_p (SCM x, SCM y)
3184 {
3185 if (!SCM_NUMBERP (x))
3186 SCM_WTA_DISPATCH_2 (g_leq_p, x, y, SCM_ARG1, FUNC_NAME);
3187 else if (!SCM_NUMBERP (y))
3188 SCM_WTA_DISPATCH_2 (g_leq_p, x, y, SCM_ARG2, FUNC_NAME);
3189 else if (SCM_NFALSEP (scm_nan_p (x)) || SCM_NFALSEP (scm_nan_p (y)))
3190 return SCM_BOOL_F;
3191 else
3192 return SCM_BOOL_NOT (scm_less_p (y, x));
3193 }
3194 #undef FUNC_NAME
3195
3196
3197 SCM_GPROC1 (s_scm_geq_p, ">=", scm_tc7_rpsubr, scm_geq_p, g_geq_p);
3198 /* "Return @code{#t} if the list of parameters is monotonically\n"
3199 * "non-increasing."
3200 */
3201 #define FUNC_NAME s_scm_geq_p
3202 SCM
3203 scm_geq_p (SCM x, SCM y)
3204 {
3205 if (!SCM_NUMBERP (x))
3206 SCM_WTA_DISPATCH_2 (g_geq_p, x, y, SCM_ARG1, FUNC_NAME);
3207 else if (!SCM_NUMBERP (y))
3208 SCM_WTA_DISPATCH_2 (g_geq_p, x, y, SCM_ARG2, FUNC_NAME);
3209 else if (SCM_NFALSEP (scm_nan_p (x)) || SCM_NFALSEP (scm_nan_p (y)))
3210 return SCM_BOOL_F;
3211 else
3212 return SCM_BOOL_NOT (scm_less_p (x, y));
3213 }
3214 #undef FUNC_NAME
3215
3216
3217 SCM_GPROC (s_zero_p, "zero?", 1, 0, 0, scm_zero_p, g_zero_p);
3218 /* "Return @code{#t} if @var{z} is an exact or inexact number equal to\n"
3219 * "zero."
3220 */
3221 SCM
3222 scm_zero_p (SCM z)
3223 {
3224 if (SCM_INUMP (z))
3225 return SCM_BOOL (SCM_EQ_P (z, SCM_INUM0));
3226 else if (SCM_BIGP (z))
3227 return SCM_BOOL_F;
3228 else if (SCM_REALP (z))
3229 return SCM_BOOL (SCM_REAL_VALUE (z) == 0.0);
3230 else if (SCM_COMPLEXP (z))
3231 return SCM_BOOL (SCM_COMPLEX_REAL (z) == 0.0
3232 && SCM_COMPLEX_IMAG (z) == 0.0);
3233 else if (SCM_FRACTIONP (z))
3234 return SCM_BOOL_F;
3235 else
3236 SCM_WTA_DISPATCH_1 (g_zero_p, z, SCM_ARG1, s_zero_p);
3237 }
3238
3239
3240 SCM_GPROC (s_positive_p, "positive?", 1, 0, 0, scm_positive_p, g_positive_p);
3241 /* "Return @code{#t} if @var{x} is an exact or inexact number greater than\n"
3242 * "zero."
3243 */
3244 SCM
3245 scm_positive_p (SCM x)
3246 {
3247 if (SCM_INUMP (x))
3248 return SCM_BOOL (SCM_INUM (x) > 0);
3249 else if (SCM_BIGP (x))
3250 {
3251 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
3252 scm_remember_upto_here_1 (x);
3253 return SCM_BOOL (sgn > 0);
3254 }
3255 else if (SCM_REALP (x))
3256 return SCM_BOOL(SCM_REAL_VALUE (x) > 0.0);
3257 else if (SCM_FRACTIONP (x))
3258 return scm_positive_p (SCM_FRACTION_NUMERATOR (x));
3259 else
3260 SCM_WTA_DISPATCH_1 (g_positive_p, x, SCM_ARG1, s_positive_p);
3261 }
3262
3263
3264 SCM_GPROC (s_negative_p, "negative?", 1, 0, 0, scm_negative_p, g_negative_p);
3265 /* "Return @code{#t} if @var{x} is an exact or inexact number less than\n"
3266 * "zero."
3267 */
3268 SCM
3269 scm_negative_p (SCM x)
3270 {
3271 if (SCM_INUMP (x))
3272 return SCM_BOOL (SCM_INUM (x) < 0);
3273 else if (SCM_BIGP (x))
3274 {
3275 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
3276 scm_remember_upto_here_1 (x);
3277 return SCM_BOOL (sgn < 0);
3278 }
3279 else if (SCM_REALP (x))
3280 return SCM_BOOL(SCM_REAL_VALUE (x) < 0.0);
3281 else if (SCM_FRACTIONP (x))
3282 return scm_negative_p (SCM_FRACTION_NUMERATOR (x));
3283 else
3284 SCM_WTA_DISPATCH_1 (g_negative_p, x, SCM_ARG1, s_negative_p);
3285 }
3286
3287
3288 SCM_GPROC1 (s_max, "max", scm_tc7_asubr, scm_max, g_max);
3289 /* "Return the maximum of all parameter values."
3290 */
3291 SCM
3292 scm_max (SCM x, SCM y)
3293 {
3294 if (SCM_UNBNDP (y))
3295 {
3296 if (SCM_UNBNDP (x))
3297 SCM_WTA_DISPATCH_0 (g_max, s_max);
3298 else if (SCM_NUMBERP (x))
3299 return x;
3300 else
3301 SCM_WTA_DISPATCH_1 (g_max, x, SCM_ARG1, s_max);
3302 }
3303
3304 if (SCM_INUMP (x))
3305 {
3306 long xx = SCM_INUM (x);
3307 if (SCM_INUMP (y))
3308 {
3309 long yy = SCM_INUM (y);
3310 return (xx < yy) ? y : x;
3311 }
3312 else if (SCM_BIGP (y))
3313 {
3314 int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
3315 scm_remember_upto_here_1 (y);
3316 return (sgn < 0) ? x : y;
3317 }
3318 else if (SCM_REALP (y))
3319 {
3320 double z = xx;
3321 /* if y==NaN then ">" is false and we return NaN */
3322 return (z > SCM_REAL_VALUE (y)) ? scm_make_real (z) : y;
3323 }
3324 else if (SCM_FRACTIONP (y))
3325 {
3326 double z = xx;
3327 return (z > scm_i_fraction2double (y)) ? x : y;
3328 }
3329 else
3330 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
3331 }
3332 else if (SCM_BIGP (x))
3333 {
3334 if (SCM_INUMP (y))
3335 {
3336 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
3337 scm_remember_upto_here_1 (x);
3338 return (sgn < 0) ? y : x;
3339 }
3340 else if (SCM_BIGP (y))
3341 {
3342 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3343 scm_remember_upto_here_2 (x, y);
3344 return (cmp > 0) ? x : y;
3345 }
3346 else if (SCM_REALP (y))
3347 {
3348 double yy = SCM_REAL_VALUE (y);
3349 int cmp;
3350 if (xisnan (yy))
3351 return y;
3352 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), yy);
3353 scm_remember_upto_here_1 (x);
3354 return (cmp > 0) ? x : y;
3355 }
3356 else if (SCM_FRACTIONP (y))
3357 {
3358 double yy = scm_i_fraction2double (y);
3359 int cmp;
3360 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), yy);
3361 scm_remember_upto_here_1 (x);
3362 return (cmp > 0) ? x : y;
3363 }
3364 else
3365 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
3366 }
3367 else if (SCM_REALP (x))
3368 {
3369 if (SCM_INUMP (y))
3370 {
3371 double z = SCM_INUM (y);
3372 /* if x==NaN then "<" is false and we return NaN */
3373 return (SCM_REAL_VALUE (x) < z) ? scm_make_real (z) : x;
3374 }
3375 else if (SCM_BIGP (y))
3376 {
3377 double xx = SCM_REAL_VALUE (x);
3378 int cmp;
3379 if (xisnan (xx))
3380 return x;
3381 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), xx);
3382 scm_remember_upto_here_1 (y);
3383 return (cmp < 0) ? x : y;
3384 }
3385 else if (SCM_REALP (y))
3386 {
3387 /* if x==NaN then our explicit check means we return NaN
3388 if y==NaN then ">" is false and we return NaN
3389 calling isnan is unavoidable, since it's the only way to know
3390 which of x or y causes any compares to be false */
3391 double xx = SCM_REAL_VALUE (x);
3392 return (xisnan (xx) || xx > SCM_REAL_VALUE (y)) ? x : y;
3393 }
3394 else if (SCM_FRACTIONP (y))
3395 {
3396 double yy = scm_i_fraction2double (y);
3397 double xx = SCM_REAL_VALUE (x);
3398 return (xx < yy) ? scm_make_real (yy) : x;
3399 }
3400 else
3401 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
3402 }
3403 else if (SCM_FRACTIONP (x))
3404 {
3405 if (SCM_INUMP (y))
3406 {
3407 double z = SCM_INUM (y);
3408 return (scm_i_fraction2double (x) < z) ? y : x;
3409 }
3410 else if (SCM_BIGP (y))
3411 {
3412 double xx = scm_i_fraction2double (x);
3413 int cmp;
3414 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), xx);
3415 scm_remember_upto_here_1 (y);
3416 return (cmp < 0) ? x : y;
3417 }
3418 else if (SCM_REALP (y))
3419 {
3420 double xx = scm_i_fraction2double (x);
3421 return (xx < SCM_REAL_VALUE (y)) ? y : scm_make_real (xx);
3422 }
3423 else if (SCM_FRACTIONP (y))
3424 {
3425 double yy = scm_i_fraction2double (y);
3426 double xx = scm_i_fraction2double (x);
3427 return (xx < yy) ? y : x;
3428 }
3429 else
3430 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
3431 }
3432 else
3433 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARG1, s_max);
3434 }
3435
3436
3437 SCM_GPROC1 (s_min, "min", scm_tc7_asubr, scm_min, g_min);
3438 /* "Return the minium of all parameter values."
3439 */
3440 SCM
3441 scm_min (SCM x, SCM y)
3442 {
3443 if (SCM_UNBNDP (y))
3444 {
3445 if (SCM_UNBNDP (x))
3446 SCM_WTA_DISPATCH_0 (g_min, s_min);
3447 else if (SCM_NUMBERP (x))
3448 return x;
3449 else
3450 SCM_WTA_DISPATCH_1 (g_min, x, SCM_ARG1, s_min);
3451 }
3452
3453 if (SCM_INUMP (x))
3454 {
3455 long xx = SCM_INUM (x);
3456 if (SCM_INUMP (y))
3457 {
3458 long yy = SCM_INUM (y);
3459 return (xx < yy) ? x : y;
3460 }
3461 else if (SCM_BIGP (y))
3462 {
3463 int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
3464 scm_remember_upto_here_1 (y);
3465 return (sgn < 0) ? y : x;
3466 }
3467 else if (SCM_REALP (y))
3468 {
3469 double z = xx;
3470 /* if y==NaN then "<" is false and we return NaN */
3471 return (z < SCM_REAL_VALUE (y)) ? scm_make_real (z) : y;
3472 }
3473 else if (SCM_FRACTIONP (y))
3474 {
3475 double z = xx;
3476 return (z < scm_i_fraction2double (y)) ? x : y;
3477 }
3478 else
3479 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
3480 }
3481 else if (SCM_BIGP (x))
3482 {
3483 if (SCM_INUMP (y))
3484 {
3485 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
3486 scm_remember_upto_here_1 (x);
3487 return (sgn < 0) ? x : y;
3488 }
3489 else if (SCM_BIGP (y))
3490 {
3491 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3492 scm_remember_upto_here_2 (x, y);
3493 return (cmp > 0) ? y : x;
3494 }
3495 else if (SCM_REALP (y))
3496 {
3497 double yy = SCM_REAL_VALUE (y);
3498 int cmp;
3499 if (xisnan (yy))
3500 return y;
3501 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), yy);
3502 scm_remember_upto_here_1 (x);
3503 return (cmp > 0) ? y : x;
3504 }
3505 else if (SCM_FRACTIONP (y))
3506 {
3507 double yy = scm_i_fraction2double (y);
3508 int cmp;
3509 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), yy);
3510 scm_remember_upto_here_1 (x);
3511 return (cmp > 0) ? y : x;
3512 }
3513 else
3514 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
3515 }
3516 else if (SCM_REALP (x))
3517 {
3518 if (SCM_INUMP (y))
3519 {
3520 double z = SCM_INUM (y);
3521 /* if x==NaN then "<" is false and we return NaN */
3522 return (z < SCM_REAL_VALUE (x)) ? scm_make_real (z) : x;
3523 }
3524 else if (SCM_BIGP (y))
3525 {
3526 double xx = SCM_REAL_VALUE (x);
3527 int cmp;
3528 if (xisnan (xx))
3529 return x;
3530 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), xx);
3531 scm_remember_upto_here_1 (y);
3532 return (cmp < 0) ? y : x;
3533 }
3534 else if (SCM_REALP (y))
3535 {
3536 /* if x==NaN then our explicit check means we return NaN
3537 if y==NaN then "<" is false and we return NaN
3538 calling isnan is unavoidable, since it's the only way to know
3539 which of x or y causes any compares to be false */
3540 double xx = SCM_REAL_VALUE (x);
3541 return (xisnan (xx) || xx < SCM_REAL_VALUE (y)) ? x : y;
3542 }
3543 else if (SCM_FRACTIONP (y))
3544 {
3545 double yy = scm_i_fraction2double (y);
3546 double xx = SCM_REAL_VALUE (x);
3547 return (yy < xx) ? scm_make_real (yy) : x;
3548 }
3549 else
3550 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
3551 }
3552 else if (SCM_FRACTIONP (x))
3553 {
3554 if (SCM_INUMP (y))
3555 {
3556 double z = SCM_INUM (y);
3557 return (scm_i_fraction2double (x) < z) ? x : y;
3558 }
3559 else if (SCM_BIGP (y))
3560 {
3561 double xx = scm_i_fraction2double (x);
3562 int cmp;
3563 cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), xx);
3564 scm_remember_upto_here_1 (y);
3565 return (cmp < 0) ? y : x;
3566 }
3567 else if (SCM_REALP (y))
3568 {
3569 double xx = scm_i_fraction2double (x);
3570 return (SCM_REAL_VALUE (y) < xx) ? y : scm_make_real (xx);
3571 }
3572 else if (SCM_FRACTIONP (y))
3573 {
3574 double yy = scm_i_fraction2double (y);
3575 double xx = scm_i_fraction2double (x);
3576 return (xx < yy) ? x : y;
3577 }
3578 else
3579 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
3580 }
3581 else
3582 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARG1, s_min);
3583 }
3584
3585
3586 SCM_GPROC1 (s_sum, "+", scm_tc7_asubr, scm_sum, g_sum);
3587 /* "Return the sum of all parameter values. Return 0 if called without\n"
3588 * "any parameters."
3589 */
3590 SCM
3591 scm_sum (SCM x, SCM y)
3592 {
3593 if (SCM_UNBNDP (y))
3594 {
3595 if (SCM_NUMBERP (x)) return x;
3596 if (SCM_UNBNDP (x)) return SCM_INUM0;
3597 SCM_WTA_DISPATCH_1 (g_sum, x, SCM_ARG1, s_sum);
3598 }
3599
3600 if (SCM_INUMP (x))
3601 {
3602 if (SCM_INUMP (y))
3603 {
3604 long xx = SCM_INUM (x);
3605 long yy = SCM_INUM (y);
3606 long int z = xx + yy;
3607 return SCM_FIXABLE (z) ? SCM_MAKINUM (z) : scm_i_long2big (z);
3608 }
3609 else if (SCM_BIGP (y))
3610 {
3611 SCM_SWAP (x, y);
3612 goto add_big_inum;
3613 }
3614 else if (SCM_REALP (y))
3615 {
3616 long int xx = SCM_INUM (x);
3617 return scm_make_real (xx + SCM_REAL_VALUE (y));
3618 }
3619 else if (SCM_COMPLEXP (y))
3620 {
3621 long int xx = SCM_INUM (x);
3622 return scm_make_complex (xx + SCM_COMPLEX_REAL (y),
3623 SCM_COMPLEX_IMAG (y));
3624 }
3625 else if (SCM_FRACTIONP (y))
3626 return scm_make_ratio (scm_sum (SCM_FRACTION_NUMERATOR (y),
3627 scm_product (x, SCM_FRACTION_DENOMINATOR (y))),
3628 SCM_FRACTION_DENOMINATOR (y));
3629 else
3630 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3631 } else if (SCM_BIGP (x))
3632 {
3633 if (SCM_INUMP (y))
3634 {
3635 long int inum;
3636 int bigsgn;
3637 add_big_inum:
3638 inum = SCM_INUM (y);
3639 if (inum == 0)
3640 return x;
3641 bigsgn = mpz_sgn (SCM_I_BIG_MPZ (x));
3642 if (inum < 0)
3643 {
3644 SCM result = scm_i_mkbig ();
3645 mpz_sub_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), - inum);
3646 scm_remember_upto_here_1 (x);
3647 /* we know the result will have to be a bignum */
3648 if (bigsgn == -1)
3649 return result;
3650 return scm_i_normbig (result);
3651 }
3652 else
3653 {
3654 SCM result = scm_i_mkbig ();
3655 mpz_add_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), inum);
3656 scm_remember_upto_here_1 (x);
3657 /* we know the result will have to be a bignum */
3658 if (bigsgn == 1)
3659 return result;
3660 return scm_i_normbig (result);
3661 }
3662 }
3663 else if (SCM_BIGP (y))
3664 {
3665 SCM result = scm_i_mkbig ();
3666 int sgn_x = mpz_sgn (SCM_I_BIG_MPZ (x));
3667 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
3668 mpz_add (SCM_I_BIG_MPZ (result),
3669 SCM_I_BIG_MPZ (x),
3670 SCM_I_BIG_MPZ (y));
3671 scm_remember_upto_here_2 (x, y);
3672 /* we know the result will have to be a bignum */
3673 if (sgn_x == sgn_y)
3674 return result;
3675 return scm_i_normbig (result);
3676 }
3677 else if (SCM_REALP (y))
3678 {
3679 double result = mpz_get_d (SCM_I_BIG_MPZ (x)) + SCM_REAL_VALUE (y);
3680 scm_remember_upto_here_1 (x);
3681 return scm_make_real (result);
3682 }
3683 else if (SCM_COMPLEXP (y))
3684 {
3685 double real_part = (mpz_get_d (SCM_I_BIG_MPZ (x))
3686 + SCM_COMPLEX_REAL (y));
3687 scm_remember_upto_here_1 (x);
3688 return scm_make_complex (real_part, SCM_COMPLEX_IMAG (y));
3689 }
3690 else if (SCM_FRACTIONP (y))
3691 return scm_make_ratio (scm_sum (SCM_FRACTION_NUMERATOR (y),
3692 scm_product (x, SCM_FRACTION_DENOMINATOR (y))),
3693 SCM_FRACTION_DENOMINATOR (y));
3694 else
3695 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3696 }
3697 else if (SCM_REALP (x))
3698 {
3699 if (SCM_INUMP (y))
3700 return scm_make_real (SCM_REAL_VALUE (x) + SCM_INUM (y));
3701 else if (SCM_BIGP (y))
3702 {
3703 double result = mpz_get_d (SCM_I_BIG_MPZ (y)) + SCM_REAL_VALUE (x);
3704 scm_remember_upto_here_1 (y);
3705 return scm_make_real (result);
3706 }
3707 else if (SCM_REALP (y))
3708 return scm_make_real (SCM_REAL_VALUE (x) + SCM_REAL_VALUE (y));
3709 else if (SCM_COMPLEXP (y))
3710 return scm_make_complex (SCM_REAL_VALUE (x) + SCM_COMPLEX_REAL (y),
3711 SCM_COMPLEX_IMAG (y));
3712 else if (SCM_FRACTIONP (y))
3713 return scm_make_real (SCM_REAL_VALUE (x) + scm_i_fraction2double (y));
3714 else
3715 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3716 }
3717 else if (SCM_COMPLEXP (x))
3718 {
3719 if (SCM_INUMP (y))
3720 return scm_make_complex (SCM_COMPLEX_REAL (x) + SCM_INUM (y),
3721 SCM_COMPLEX_IMAG (x));
3722 else if (SCM_BIGP (y))
3723 {
3724 double real_part = (mpz_get_d (SCM_I_BIG_MPZ (y))
3725 + SCM_COMPLEX_REAL (x));
3726 scm_remember_upto_here_1 (y);
3727 return scm_make_complex (real_part, SCM_COMPLEX_IMAG (x));
3728 }
3729 else if (SCM_REALP (y))
3730 return scm_make_complex (SCM_COMPLEX_REAL (x) + SCM_REAL_VALUE (y),
3731 SCM_COMPLEX_IMAG (x));
3732 else if (SCM_COMPLEXP (y))
3733 return scm_make_complex (SCM_COMPLEX_REAL (x) + SCM_COMPLEX_REAL (y),
3734 SCM_COMPLEX_IMAG (x) + SCM_COMPLEX_IMAG (y));
3735 else if (SCM_FRACTIONP (y))
3736 return scm_make_complex (SCM_COMPLEX_REAL (x) + scm_i_fraction2double (y),
3737 SCM_COMPLEX_IMAG (x));
3738 else
3739 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3740 }
3741 else if (SCM_FRACTIONP (x))
3742 {
3743 if (SCM_INUMP (y))
3744 return scm_make_ratio (scm_sum (SCM_FRACTION_NUMERATOR (x),
3745 scm_product (y, SCM_FRACTION_DENOMINATOR (x))),
3746 SCM_FRACTION_DENOMINATOR (x));
3747 else if (SCM_BIGP (y))
3748 return scm_make_ratio (scm_sum (SCM_FRACTION_NUMERATOR (x),
3749 scm_product (y, SCM_FRACTION_DENOMINATOR (x))),
3750 SCM_FRACTION_DENOMINATOR (x));
3751 else if (SCM_REALP (y))
3752 return scm_make_real (SCM_REAL_VALUE (y) + scm_i_fraction2double (x));
3753 else if (SCM_COMPLEXP (y))
3754 return scm_make_complex (SCM_COMPLEX_REAL (y) + scm_i_fraction2double (x),
3755 SCM_COMPLEX_IMAG (y));
3756 else if (SCM_FRACTIONP (y))
3757 /* a/b + c/d = (ad + bc) / bd */
3758 return scm_make_ratio (scm_sum (scm_product (SCM_FRACTION_NUMERATOR (x), SCM_FRACTION_DENOMINATOR (y)),
3759 scm_product (SCM_FRACTION_NUMERATOR (y), SCM_FRACTION_DENOMINATOR (x))),
3760 scm_product (SCM_FRACTION_DENOMINATOR (x), SCM_FRACTION_DENOMINATOR (y)));
3761 else
3762 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3763 }
3764 else
3765 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARG1, s_sum);
3766 }
3767
3768
3769 SCM_GPROC1 (s_difference, "-", scm_tc7_asubr, scm_difference, g_difference);
3770 /* If called with one argument @var{z1}, -@var{z1} returned. Otherwise
3771 * the sum of all but the first argument are subtracted from the first
3772 * argument. */
3773 #define FUNC_NAME s_difference
3774 SCM
3775 scm_difference (SCM x, SCM y)
3776 {
3777 if (SCM_UNBNDP (y))
3778 {
3779 if (SCM_UNBNDP (x))
3780 SCM_WTA_DISPATCH_0 (g_difference, s_difference);
3781 else
3782 if (SCM_INUMP (x))
3783 {
3784 long xx = -SCM_INUM (x);
3785 if (SCM_FIXABLE (xx))
3786 return SCM_MAKINUM (xx);
3787 else
3788 return scm_i_long2big (xx);
3789 }
3790 else if (SCM_BIGP (x))
3791 /* FIXME: do we really need to normalize here? */
3792 return scm_i_normbig (scm_i_clonebig (x, 0));
3793 else if (SCM_REALP (x))
3794 return scm_make_real (-SCM_REAL_VALUE (x));
3795 else if (SCM_COMPLEXP (x))
3796 return scm_make_complex (-SCM_COMPLEX_REAL (x),
3797 -SCM_COMPLEX_IMAG (x));
3798 else if (SCM_FRACTIONP (x))
3799 return scm_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x), SCM_UNDEFINED),
3800 SCM_FRACTION_DENOMINATOR (x));
3801 else
3802 SCM_WTA_DISPATCH_1 (g_difference, x, SCM_ARG1, s_difference);
3803 }
3804
3805 if (SCM_INUMP (x))
3806 {
3807 if (SCM_INUMP (y))
3808 {
3809 long int xx = SCM_INUM (x);
3810 long int yy = SCM_INUM (y);
3811 long int z = xx - yy;
3812 if (SCM_FIXABLE (z))
3813 return SCM_MAKINUM (z);
3814 else
3815 return scm_i_long2big (z);
3816 }
3817 else if (SCM_BIGP (y))
3818 {
3819 /* inum-x - big-y */
3820 long xx = SCM_INUM (x);
3821
3822 if (xx == 0)
3823 return scm_i_clonebig (y, 0);
3824 else
3825 {
3826 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
3827 SCM result = scm_i_mkbig ();
3828
3829 if (xx >= 0)
3830 mpz_ui_sub (SCM_I_BIG_MPZ (result), xx, SCM_I_BIG_MPZ (y));
3831 else
3832 {
3833 /* x - y == -(y + -x) */
3834 mpz_add_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (y), -xx);
3835 mpz_neg (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result));
3836 }
3837 scm_remember_upto_here_1 (y);
3838
3839 if ((xx < 0 && (sgn_y > 0)) || ((xx > 0) && sgn_y < 0))
3840 /* we know the result will have to be a bignum */
3841 return result;
3842 else
3843 return scm_i_normbig (result);
3844 }
3845 }
3846 else if (SCM_REALP (y))
3847 {
3848 long int xx = SCM_INUM (x);
3849 return scm_make_real (xx - SCM_REAL_VALUE (y));
3850 }
3851 else if (SCM_COMPLEXP (y))
3852 {
3853 long int xx = SCM_INUM (x);
3854 return scm_make_complex (xx - SCM_COMPLEX_REAL (y),
3855 - SCM_COMPLEX_IMAG (y));
3856 }
3857 else if (SCM_FRACTIONP (y))
3858 /* a - b/c = (ac - b) / c */
3859 return scm_make_ratio (scm_difference (scm_product (x, SCM_FRACTION_DENOMINATOR (y)),
3860 SCM_FRACTION_NUMERATOR (y)),
3861 SCM_FRACTION_DENOMINATOR (y));
3862 else
3863 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3864 }
3865 else if (SCM_BIGP (x))
3866 {
3867 if (SCM_INUMP (y))
3868 {
3869 /* big-x - inum-y */
3870 long yy = SCM_INUM (y);
3871 int sgn_x = mpz_sgn (SCM_I_BIG_MPZ (x));
3872
3873 scm_remember_upto_here_1 (x);
3874 if (sgn_x == 0)
3875 return SCM_FIXABLE (-yy) ? SCM_MAKINUM (-yy) : scm_long2num (-yy);
3876 else
3877 {
3878 SCM result = scm_i_mkbig ();
3879
3880 if (yy >= 0)
3881 mpz_sub_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), yy);
3882 else
3883 mpz_add_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), -yy);
3884 scm_remember_upto_here_1 (x);
3885
3886 if ((sgn_x < 0 && (yy > 0)) || ((sgn_x > 0) && yy < 0))
3887 /* we know the result will have to be a bignum */
3888 return result;
3889 else
3890 return scm_i_normbig (result);
3891 }
3892 }
3893 else if (SCM_BIGP (y))
3894 {
3895 int sgn_x = mpz_sgn (SCM_I_BIG_MPZ (x));
3896 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
3897 SCM result = scm_i_mkbig ();
3898 mpz_sub (SCM_I_BIG_MPZ (result),
3899 SCM_I_BIG_MPZ (x),
3900 SCM_I_BIG_MPZ (y));
3901 scm_remember_upto_here_2 (x, y);
3902 /* we know the result will have to be a bignum */
3903 if ((sgn_x == 1) && (sgn_y == -1))
3904 return result;
3905 if ((sgn_x == -1) && (sgn_y == 1))
3906 return result;
3907 return scm_i_normbig (result);
3908 }
3909 else if (SCM_REALP (y))
3910 {
3911 double result = mpz_get_d (SCM_I_BIG_MPZ (x)) - SCM_REAL_VALUE (y);
3912 scm_remember_upto_here_1 (x);
3913 return scm_make_real (result);
3914 }
3915 else if (SCM_COMPLEXP (y))
3916 {
3917 double real_part = (mpz_get_d (SCM_I_BIG_MPZ (x))
3918 - SCM_COMPLEX_REAL (y));
3919 scm_remember_upto_here_1 (x);
3920 return scm_make_complex (real_part, - SCM_COMPLEX_IMAG (y));
3921 }
3922 else if (SCM_FRACTIONP (y))
3923 return scm_make_ratio (scm_difference (scm_product (x, SCM_FRACTION_DENOMINATOR (y)),
3924 SCM_FRACTION_NUMERATOR (y)),
3925 SCM_FRACTION_DENOMINATOR (y));
3926 else SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3927 }
3928 else if (SCM_REALP (x))
3929 {
3930 if (SCM_INUMP (y))
3931 return scm_make_real (SCM_REAL_VALUE (x) - SCM_INUM (y));
3932 else if (SCM_BIGP (y))
3933 {
3934 double result = SCM_REAL_VALUE (x) - mpz_get_d (SCM_I_BIG_MPZ (y));
3935 scm_remember_upto_here_1 (x);
3936 return scm_make_real (result);
3937 }
3938 else if (SCM_REALP (y))
3939 return scm_make_real (SCM_REAL_VALUE (x) - SCM_REAL_VALUE (y));
3940 else if (SCM_COMPLEXP (y))
3941 return scm_make_complex (SCM_REAL_VALUE (x) - SCM_COMPLEX_REAL (y),
3942 -SCM_COMPLEX_IMAG (y));
3943 else if (SCM_FRACTIONP (y))
3944 return scm_make_real (SCM_REAL_VALUE (x) - scm_i_fraction2double (y));
3945 else
3946 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3947 }
3948 else if (SCM_COMPLEXP (x))
3949 {
3950 if (SCM_INUMP (y))
3951 return scm_make_complex (SCM_COMPLEX_REAL (x) - SCM_INUM (y),
3952 SCM_COMPLEX_IMAG (x));
3953 else if (SCM_BIGP (y))
3954 {
3955 double real_part = (SCM_COMPLEX_REAL (x)
3956 - mpz_get_d (SCM_I_BIG_MPZ (y)));
3957 scm_remember_upto_here_1 (x);
3958 return scm_make_complex (real_part, SCM_COMPLEX_IMAG (y));
3959 }
3960 else if (SCM_REALP (y))
3961 return scm_make_complex (SCM_COMPLEX_REAL (x) - SCM_REAL_VALUE (y),
3962 SCM_COMPLEX_IMAG (x));
3963 else if (SCM_COMPLEXP (y))
3964 return scm_make_complex (SCM_COMPLEX_REAL (x) - SCM_COMPLEX_REAL (y),
3965 SCM_COMPLEX_IMAG (x) - SCM_COMPLEX_IMAG (y));
3966 else if (SCM_FRACTIONP (y))
3967 return scm_make_complex (SCM_COMPLEX_REAL (x) - scm_i_fraction2double (y),
3968 SCM_COMPLEX_IMAG (x));
3969 else
3970 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3971 }
3972 else if (SCM_FRACTIONP (x))
3973 {
3974 if (SCM_INUMP (y))
3975 /* a/b - c = (a - cb) / b */
3976 return scm_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x),
3977 scm_product(y, SCM_FRACTION_DENOMINATOR (x))),
3978 SCM_FRACTION_DENOMINATOR (x));
3979 else if (SCM_BIGP (y))
3980 return scm_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (x),
3981 scm_product(y, SCM_FRACTION_DENOMINATOR (x))),
3982 SCM_FRACTION_DENOMINATOR (x));
3983 else if (SCM_REALP (y))
3984 return scm_make_real (scm_i_fraction2double (x) - SCM_REAL_VALUE (y));
3985 else if (SCM_COMPLEXP (y))
3986 return scm_make_complex (scm_i_fraction2double (x) - SCM_COMPLEX_REAL (y),
3987 -SCM_COMPLEX_IMAG (y));
3988 else if (SCM_FRACTIONP (y))
3989 /* a/b - c/d = (ad - bc) / bd */
3990 return scm_make_ratio (scm_difference (scm_product (SCM_FRACTION_NUMERATOR (x), SCM_FRACTION_DENOMINATOR (y)),
3991 scm_product (SCM_FRACTION_NUMERATOR (y), SCM_FRACTION_DENOMINATOR (x))),
3992 scm_product (SCM_FRACTION_DENOMINATOR (x), SCM_FRACTION_DENOMINATOR (y)));
3993 else
3994 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3995 }
3996 else
3997 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARG1, s_difference);
3998 }
3999 #undef FUNC_NAME
4000
4001
4002 SCM_GPROC1 (s_product, "*", scm_tc7_asubr, scm_product, g_product);
4003 /* "Return the product of all arguments. If called without arguments,\n"
4004 * "1 is returned."
4005 */
4006 SCM
4007 scm_product (SCM x, SCM y)
4008 {
4009 if (SCM_UNBNDP (y))
4010 {
4011 if (SCM_UNBNDP (x))
4012 return SCM_MAKINUM (1L);
4013 else if (SCM_NUMBERP (x))
4014 return x;
4015 else
4016 SCM_WTA_DISPATCH_1 (g_product, x, SCM_ARG1, s_product);
4017 }
4018
4019 if (SCM_INUMP (x))
4020 {
4021 long xx;
4022
4023 intbig:
4024 xx = SCM_INUM (x);
4025
4026 switch (xx)
4027 {
4028 case 0: return x; break;
4029 case 1: return y; break;
4030 }
4031
4032 if (SCM_INUMP (y))
4033 {
4034 long yy = SCM_INUM (y);
4035 long kk = xx * yy;
4036 SCM k = SCM_MAKINUM (kk);
4037 if ((kk == SCM_INUM (k)) && (kk / xx == yy))
4038 return k;
4039 else
4040 {
4041 SCM result = scm_i_long2big (xx);
4042 mpz_mul_si (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result), yy);
4043 return scm_i_normbig (result);
4044 }
4045 }
4046 else if (SCM_BIGP (y))
4047 {
4048 SCM result = scm_i_mkbig ();
4049 mpz_mul_si (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (y), xx);
4050 scm_remember_upto_here_1 (y);
4051 return result;
4052 }
4053 else if (SCM_REALP (y))
4054 return scm_make_real (xx * SCM_REAL_VALUE (y));
4055 else if (SCM_COMPLEXP (y))
4056 return scm_make_complex (xx * SCM_COMPLEX_REAL (y),
4057 xx * SCM_COMPLEX_IMAG (y));
4058 else if (SCM_FRACTIONP (y))
4059 return scm_make_ratio (scm_product (x, SCM_FRACTION_NUMERATOR (y)),
4060 SCM_FRACTION_DENOMINATOR (y));
4061 else
4062 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
4063 }
4064 else if (SCM_BIGP (x))
4065 {
4066 if (SCM_INUMP (y))
4067 {
4068 SCM_SWAP (x, y);
4069 goto intbig;
4070 }
4071 else if (SCM_BIGP (y))
4072 {
4073 SCM result = scm_i_mkbig ();
4074 mpz_mul (SCM_I_BIG_MPZ (result),
4075 SCM_I_BIG_MPZ (x),
4076 SCM_I_BIG_MPZ (y));
4077 scm_remember_upto_here_2 (x, y);
4078 return result;
4079 }
4080 else if (SCM_REALP (y))
4081 {
4082 double result = mpz_get_d (SCM_I_BIG_MPZ (x)) * SCM_REAL_VALUE (y);
4083 scm_remember_upto_here_1 (x);
4084 return scm_make_real (result);
4085 }
4086 else if (SCM_COMPLEXP (y))
4087 {
4088 double z = mpz_get_d (SCM_I_BIG_MPZ (x));
4089 scm_remember_upto_here_1 (x);
4090 return scm_make_complex (z * SCM_COMPLEX_REAL (y),
4091 z * SCM_COMPLEX_IMAG (y));
4092 }
4093 else if (SCM_FRACTIONP (y))
4094 return scm_make_ratio (scm_product (x, SCM_FRACTION_NUMERATOR (y)),
4095 SCM_FRACTION_DENOMINATOR (y));
4096 else
4097 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
4098 }
4099 else if (SCM_REALP (x))
4100 {
4101 if (SCM_INUMP (y))
4102 return scm_make_real (SCM_INUM (y) * SCM_REAL_VALUE (x));
4103 else if (SCM_BIGP (y))
4104 {
4105 double result = mpz_get_d (SCM_I_BIG_MPZ (y)) * SCM_REAL_VALUE (x);
4106 scm_remember_upto_here_1 (y);
4107 return scm_make_real (result);
4108 }
4109 else if (SCM_REALP (y))
4110 return scm_make_real (SCM_REAL_VALUE (x) * SCM_REAL_VALUE (y));
4111 else if (SCM_COMPLEXP (y))
4112 return scm_make_complex (SCM_REAL_VALUE (x) * SCM_COMPLEX_REAL (y),
4113 SCM_REAL_VALUE (x) * SCM_COMPLEX_IMAG (y));
4114 else if (SCM_FRACTIONP (y))
4115 return scm_make_real (SCM_REAL_VALUE (x) * scm_i_fraction2double (y));
4116 else
4117 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
4118 }
4119 else if (SCM_COMPLEXP (x))
4120 {
4121 if (SCM_INUMP (y))
4122 return scm_make_complex (SCM_INUM (y) * SCM_COMPLEX_REAL (x),
4123 SCM_INUM (y) * SCM_COMPLEX_IMAG (x));
4124 else if (SCM_BIGP (y))
4125 {
4126 double z = mpz_get_d (SCM_I_BIG_MPZ (y));
4127 scm_remember_upto_here_1 (y);
4128 return scm_make_complex (z * SCM_COMPLEX_REAL (x),
4129 z * SCM_COMPLEX_IMAG (x));
4130 }
4131 else if (SCM_REALP (y))
4132 return scm_make_complex (SCM_REAL_VALUE (y) * SCM_COMPLEX_REAL (x),
4133 SCM_REAL_VALUE (y) * SCM_COMPLEX_IMAG (x));
4134 else if (SCM_COMPLEXP (y))
4135 {
4136 return scm_make_complex (SCM_COMPLEX_REAL (x) * SCM_COMPLEX_REAL (y)
4137 - SCM_COMPLEX_IMAG (x) * SCM_COMPLEX_IMAG (y),
4138 SCM_COMPLEX_REAL (x) * SCM_COMPLEX_IMAG (y)
4139 + SCM_COMPLEX_IMAG (x) * SCM_COMPLEX_REAL (y));
4140 }
4141 else if (SCM_FRACTIONP (y))
4142 {
4143 double yy = scm_i_fraction2double (y);
4144 return scm_make_complex (yy * SCM_COMPLEX_REAL (x),
4145 yy * SCM_COMPLEX_IMAG (x));
4146 }
4147 else
4148 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
4149 }
4150 else if (SCM_FRACTIONP (x))
4151 {
4152 if (SCM_INUMP (y))
4153 return scm_make_ratio (scm_product (y, SCM_FRACTION_NUMERATOR (x)),
4154 SCM_FRACTION_DENOMINATOR (x));
4155 else if (SCM_BIGP (y))
4156 return scm_make_ratio (scm_product (y, SCM_FRACTION_NUMERATOR (x)),
4157 SCM_FRACTION_DENOMINATOR (x));
4158 else if (SCM_REALP (y))
4159 return scm_make_real (scm_i_fraction2double (x) * SCM_REAL_VALUE (y));
4160 else if (SCM_COMPLEXP (y))
4161 {
4162 double xx = scm_i_fraction2double (x);
4163 return scm_make_complex (xx * SCM_COMPLEX_REAL (y),
4164 xx * SCM_COMPLEX_IMAG (y));
4165 }
4166 else if (SCM_FRACTIONP (y))
4167 /* a/b * c/d = ac / bd */
4168 return scm_make_ratio (scm_product (SCM_FRACTION_NUMERATOR (x),
4169 SCM_FRACTION_NUMERATOR (y)),
4170 scm_product (SCM_FRACTION_DENOMINATOR (x),
4171 SCM_FRACTION_DENOMINATOR (y)));
4172 else
4173 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
4174 }
4175 else
4176 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARG1, s_product);
4177 }
4178
4179 double
4180 scm_num2dbl (SCM a, const char *why)
4181 #define FUNC_NAME why
4182 {
4183 if (SCM_INUMP (a))
4184 return (double) SCM_INUM (a);
4185 else if (SCM_BIGP (a))
4186 {
4187 double result = mpz_get_d (SCM_I_BIG_MPZ (a));
4188 scm_remember_upto_here_1 (a);
4189 return result;
4190 }
4191 else if (SCM_REALP (a))
4192 return (SCM_REAL_VALUE (a));
4193 else if (SCM_FRACTIONP (a))
4194 return scm_i_fraction2double (a);
4195 else
4196 SCM_WRONG_TYPE_ARG (SCM_ARGn, a);
4197 }
4198 #undef FUNC_NAME
4199
4200 #if ((defined (HAVE_ISINF) && defined (HAVE_ISNAN)) \
4201 || (defined (HAVE_FINITE) && defined (HAVE_ISNAN)))
4202 #define ALLOW_DIVIDE_BY_ZERO
4203 /* #define ALLOW_DIVIDE_BY_EXACT_ZERO */
4204 #endif
4205
4206 /* The code below for complex division is adapted from the GNU
4207 libstdc++, which adapted it from f2c's libF77, and is subject to
4208 this copyright: */
4209
4210 /****************************************************************
4211 Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories and Bellcore.
4212
4213 Permission to use, copy, modify, and distribute this software
4214 and its documentation for any purpose and without fee is hereby
4215 granted, provided that the above copyright notice appear in all
4216 copies and that both that the copyright notice and this
4217 permission notice and warranty disclaimer appear in supporting
4218 documentation, and that the names of AT&T Bell Laboratories or
4219 Bellcore or any of their entities not be used in advertising or
4220 publicity pertaining to distribution of the software without
4221 specific, written prior permission.
4222
4223 AT&T and Bellcore disclaim all warranties with regard to this
4224 software, including all implied warranties of merchantability
4225 and fitness. In no event shall AT&T or Bellcore be liable for
4226 any special, indirect or consequential damages or any damages
4227 whatsoever resulting from loss of use, data or profits, whether
4228 in an action of contract, negligence or other tortious action,
4229 arising out of or in connection with the use or performance of
4230 this software.
4231 ****************************************************************/
4232
4233 SCM_GPROC1 (s_divide, "/", scm_tc7_asubr, scm_divide, g_divide);
4234 /* Divide the first argument by the product of the remaining
4235 arguments. If called with one argument @var{z1}, 1/@var{z1} is
4236 returned. */
4237 #define FUNC_NAME s_divide
4238 static SCM
4239 scm_i_divide (SCM x, SCM y, int inexact)
4240 {
4241 double a;
4242
4243 if (SCM_UNBNDP (y))
4244 {
4245 if (SCM_UNBNDP (x))
4246 SCM_WTA_DISPATCH_0 (g_divide, s_divide);
4247 else if (SCM_INUMP (x))
4248 {
4249 long xx = SCM_INUM (x);
4250 if (xx == 1 || xx == -1)
4251 return x;
4252 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4253 else if (xx == 0)
4254 scm_num_overflow (s_divide);
4255 #endif
4256 else
4257 {
4258 if (inexact)
4259 return scm_make_real (1.0 / (double) xx);
4260 else return scm_make_ratio (SCM_MAKINUM(1), x);
4261 }
4262 }
4263 else if (SCM_BIGP (x))
4264 {
4265 if (inexact)
4266 return scm_make_real (1.0 / scm_i_big2dbl (x));
4267 else return scm_make_ratio (SCM_MAKINUM(1), x);
4268 }
4269 else if (SCM_REALP (x))
4270 {
4271 double xx = SCM_REAL_VALUE (x);
4272 #ifndef ALLOW_DIVIDE_BY_ZERO
4273 if (xx == 0.0)
4274 scm_num_overflow (s_divide);
4275 else
4276 #endif
4277 return scm_make_real (1.0 / xx);
4278 }
4279 else if (SCM_COMPLEXP (x))
4280 {
4281 double r = SCM_COMPLEX_REAL (x);
4282 double i = SCM_COMPLEX_IMAG (x);
4283 if (r <= i)
4284 {
4285 double t = r / i;
4286 double d = i * (1.0 + t * t);
4287 return scm_make_complex (t / d, -1.0 / d);
4288 }
4289 else
4290 {
4291 double t = i / r;
4292 double d = r * (1.0 + t * t);
4293 return scm_make_complex (1.0 / d, -t / d);
4294 }
4295 }
4296 else if (SCM_FRACTIONP (x))
4297 return scm_make_ratio (SCM_FRACTION_DENOMINATOR (x),
4298 SCM_FRACTION_NUMERATOR (x));
4299 else
4300 SCM_WTA_DISPATCH_1 (g_divide, x, SCM_ARG1, s_divide);
4301 }
4302
4303 if (SCM_INUMP (x))
4304 {
4305 long xx = SCM_INUM (x);
4306 if (SCM_INUMP (y))
4307 {
4308 long yy = SCM_INUM (y);
4309 if (yy == 0)
4310 {
4311 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4312 scm_num_overflow (s_divide);
4313 #else
4314 return scm_make_real ((double) xx / (double) yy);
4315 #endif
4316 }
4317 else if (xx % yy != 0)
4318 {
4319 if (inexact)
4320 return scm_make_real ((double) xx / (double) yy);
4321 else return scm_make_ratio (x, y);
4322 }
4323 else
4324 {
4325 long z = xx / yy;
4326 if (SCM_FIXABLE (z))
4327 return SCM_MAKINUM (z);
4328 else
4329 return scm_i_long2big (z);
4330 }
4331 }
4332 else if (SCM_BIGP (y))
4333 {
4334 if (inexact)
4335 return scm_make_real ((double) xx / scm_i_big2dbl (y));
4336 else return scm_make_ratio (x, y);
4337 }
4338 else if (SCM_REALP (y))
4339 {
4340 double yy = SCM_REAL_VALUE (y);
4341 #ifndef ALLOW_DIVIDE_BY_ZERO
4342 if (yy == 0.0)
4343 scm_num_overflow (s_divide);
4344 else
4345 #endif
4346 return scm_make_real ((double) xx / yy);
4347 }
4348 else if (SCM_COMPLEXP (y))
4349 {
4350 a = xx;
4351 complex_div: /* y _must_ be a complex number */
4352 {
4353 double r = SCM_COMPLEX_REAL (y);
4354 double i = SCM_COMPLEX_IMAG (y);
4355 if (r <= i)
4356 {
4357 double t = r / i;
4358 double d = i * (1.0 + t * t);
4359 return scm_make_complex ((a * t) / d, -a / d);
4360 }
4361 else
4362 {
4363 double t = i / r;
4364 double d = r * (1.0 + t * t);
4365 return scm_make_complex (a / d, -(a * t) / d);
4366 }
4367 }
4368 }
4369 else if (SCM_FRACTIONP (y))
4370 /* a / b/c = ac / b */
4371 return scm_make_ratio (scm_product (x, SCM_FRACTION_DENOMINATOR (y)),
4372 SCM_FRACTION_NUMERATOR (y));
4373 else
4374 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
4375 }
4376 else if (SCM_BIGP (x))
4377 {
4378 if (SCM_INUMP (y))
4379 {
4380 long int yy = SCM_INUM (y);
4381 if (yy == 0)
4382 {
4383 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4384 scm_num_overflow (s_divide);
4385 #else
4386 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
4387 scm_remember_upto_here_1 (x);
4388 return (sgn == 0) ? scm_nan () : scm_inf ();
4389 #endif
4390 }
4391 else if (yy == 1)
4392 return x;
4393 else
4394 {
4395 /* FIXME: HMM, what are the relative performance issues here?
4396 We need to test. Is it faster on average to test
4397 divisible_p, then perform whichever operation, or is it
4398 faster to perform the integer div opportunistically and
4399 switch to real if there's a remainder? For now we take the
4400 middle ground: test, then if divisible, use the faster div
4401 func. */
4402
4403 long abs_yy = yy < 0 ? -yy : yy;
4404 int divisible_p = mpz_divisible_ui_p (SCM_I_BIG_MPZ (x), abs_yy);
4405
4406 if (divisible_p)
4407 {
4408 SCM result = scm_i_mkbig ();
4409 mpz_divexact_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), abs_yy);
4410 scm_remember_upto_here_1 (x);
4411 if (yy < 0)
4412 mpz_neg (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result));
4413 return scm_i_normbig (result);
4414 }
4415 else
4416 {
4417 if (inexact)
4418 return scm_make_real (scm_i_big2dbl (x) / (double) yy);
4419 else return scm_make_ratio (x, y);
4420 }
4421 }
4422 }
4423 else if (SCM_BIGP (y))
4424 {
4425 int y_is_zero = (mpz_sgn (SCM_I_BIG_MPZ (y)) == 0);
4426 if (y_is_zero)
4427 {
4428 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4429 scm_num_overflow (s_divide);
4430 #else
4431 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
4432 scm_remember_upto_here_1 (x);
4433 return (sgn == 0) ? scm_nan () : scm_inf ();
4434 #endif
4435 }
4436 else
4437 {
4438 /* big_x / big_y */
4439 int divisible_p = mpz_divisible_p (SCM_I_BIG_MPZ (x),
4440 SCM_I_BIG_MPZ (y));
4441 if (divisible_p)
4442 {
4443 SCM result = scm_i_mkbig ();
4444 mpz_divexact (SCM_I_BIG_MPZ (result),
4445 SCM_I_BIG_MPZ (x),
4446 SCM_I_BIG_MPZ (y));
4447 scm_remember_upto_here_2 (x, y);
4448 return scm_i_normbig (result);
4449 }
4450 else
4451 {
4452 if (inexact)
4453 {
4454 double dbx = mpz_get_d (SCM_I_BIG_MPZ (x));
4455 double dby = mpz_get_d (SCM_I_BIG_MPZ (y));
4456 scm_remember_upto_here_2 (x, y);
4457 return scm_make_real (dbx / dby);
4458 }
4459 else return scm_make_ratio (x, y);
4460 }
4461 }
4462 }
4463 else if (SCM_REALP (y))
4464 {
4465 double yy = SCM_REAL_VALUE (y);
4466 #ifndef ALLOW_DIVIDE_BY_ZERO
4467 if (yy == 0.0)
4468 scm_num_overflow (s_divide);
4469 else
4470 #endif
4471 return scm_make_real (scm_i_big2dbl (x) / yy);
4472 }
4473 else if (SCM_COMPLEXP (y))
4474 {
4475 a = scm_i_big2dbl (x);
4476 goto complex_div;
4477 }
4478 else if (SCM_FRACTIONP (y))
4479 return scm_make_ratio (scm_product (x, SCM_FRACTION_DENOMINATOR (y)),
4480 SCM_FRACTION_NUMERATOR (y));
4481 else
4482 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
4483 }
4484 else if (SCM_REALP (x))
4485 {
4486 double rx = SCM_REAL_VALUE (x);
4487 if (SCM_INUMP (y))
4488 {
4489 long int yy = SCM_INUM (y);
4490 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4491 if (yy == 0)
4492 scm_num_overflow (s_divide);
4493 else
4494 #endif
4495 return scm_make_real (rx / (double) yy);
4496 }
4497 else if (SCM_BIGP (y))
4498 {
4499 double dby = mpz_get_d (SCM_I_BIG_MPZ (y));
4500 scm_remember_upto_here_1 (y);
4501 return scm_make_real (rx / dby);
4502 }
4503 else if (SCM_REALP (y))
4504 {
4505 double yy = SCM_REAL_VALUE (y);
4506 #ifndef ALLOW_DIVIDE_BY_ZERO
4507 if (yy == 0.0)
4508 scm_num_overflow (s_divide);
4509 else
4510 #endif
4511 return scm_make_real (rx / yy);
4512 }
4513 else if (SCM_COMPLEXP (y))
4514 {
4515 a = rx;
4516 goto complex_div;
4517 }
4518 else if (SCM_FRACTIONP (y))
4519 return scm_make_real (rx / scm_i_fraction2double (y));
4520 else
4521 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
4522 }
4523 else if (SCM_COMPLEXP (x))
4524 {
4525 double rx = SCM_COMPLEX_REAL (x);
4526 double ix = SCM_COMPLEX_IMAG (x);
4527 if (SCM_INUMP (y))
4528 {
4529 long int yy = SCM_INUM (y);
4530 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4531 if (yy == 0)
4532 scm_num_overflow (s_divide);
4533 else
4534 #endif
4535 {
4536 double d = yy;
4537 return scm_make_complex (rx / d, ix / d);
4538 }
4539 }
4540 else if (SCM_BIGP (y))
4541 {
4542 double dby = mpz_get_d (SCM_I_BIG_MPZ (y));
4543 scm_remember_upto_here_1 (y);
4544 return scm_make_complex (rx / dby, ix / dby);
4545 }
4546 else if (SCM_REALP (y))
4547 {
4548 double yy = SCM_REAL_VALUE (y);
4549 #ifndef ALLOW_DIVIDE_BY_ZERO
4550 if (yy == 0.0)
4551 scm_num_overflow (s_divide);
4552 else
4553 #endif
4554 return scm_make_complex (rx / yy, ix / yy);
4555 }
4556 else if (SCM_COMPLEXP (y))
4557 {
4558 double ry = SCM_COMPLEX_REAL (y);
4559 double iy = SCM_COMPLEX_IMAG (y);
4560 if (ry <= iy)
4561 {
4562 double t = ry / iy;
4563 double d = iy * (1.0 + t * t);
4564 return scm_make_complex ((rx * t + ix) / d, (ix * t - rx) / d);
4565 }
4566 else
4567 {
4568 double t = iy / ry;
4569 double d = ry * (1.0 + t * t);
4570 return scm_make_complex ((rx + ix * t) / d, (ix - rx * t) / d);
4571 }
4572 }
4573 else if (SCM_FRACTIONP (y))
4574 {
4575 double yy = scm_i_fraction2double (y);
4576 return scm_make_complex (rx / yy, ix / yy);
4577 }
4578 else
4579 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
4580 }
4581 else if (SCM_FRACTIONP (x))
4582 {
4583 if (SCM_INUMP (y))
4584 {
4585 long int yy = SCM_INUM (y);
4586 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4587 if (yy == 0)
4588 scm_num_overflow (s_divide);
4589 else
4590 #endif
4591 return scm_make_ratio (SCM_FRACTION_NUMERATOR (x),
4592 scm_product (SCM_FRACTION_DENOMINATOR (x), y));
4593 }
4594 else if (SCM_BIGP (y))
4595 {
4596 return scm_make_ratio (SCM_FRACTION_NUMERATOR (x),
4597 scm_product (SCM_FRACTION_DENOMINATOR (x), y));
4598 }
4599 else if (SCM_REALP (y))
4600 {
4601 double yy = SCM_REAL_VALUE (y);
4602 #ifndef ALLOW_DIVIDE_BY_ZERO
4603 if (yy == 0.0)
4604 scm_num_overflow (s_divide);
4605 else
4606 #endif
4607 return scm_make_real (scm_i_fraction2double (x) / yy);
4608 }
4609 else if (SCM_COMPLEXP (y))
4610 {
4611 a = scm_i_fraction2double (x);
4612 goto complex_div;
4613 }
4614 else if (SCM_FRACTIONP (y))
4615 return scm_make_ratio (scm_product (SCM_FRACTION_NUMERATOR (x), SCM_FRACTION_DENOMINATOR (y)),
4616 scm_product (SCM_FRACTION_NUMERATOR (y), SCM_FRACTION_DENOMINATOR (x)));
4617 else
4618 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
4619 }
4620 else
4621 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARG1, s_divide);
4622 }
4623
4624 SCM
4625 scm_divide (SCM x, SCM y)
4626 {
4627 return scm_i_divide (x, y, 0);
4628 }
4629
4630 static SCM scm_divide2real (SCM x, SCM y)
4631 {
4632 return scm_i_divide (x, y, 1);
4633 }
4634 #undef FUNC_NAME
4635
4636
4637 double
4638 scm_asinh (double x)
4639 {
4640 #if HAVE_ASINH
4641 return asinh (x);
4642 #else
4643 #define asinh scm_asinh
4644 return log (x + sqrt (x * x + 1));
4645 #endif
4646 }
4647 SCM_GPROC1 (s_asinh, "$asinh", scm_tc7_dsubr, (SCM (*)()) asinh, g_asinh);
4648 /* "Return the inverse hyperbolic sine of @var{x}."
4649 */
4650
4651
4652 double
4653 scm_acosh (double x)
4654 {
4655 #if HAVE_ACOSH
4656 return acosh (x);
4657 #else
4658 #define acosh scm_acosh
4659 return log (x + sqrt (x * x - 1));
4660 #endif
4661 }
4662 SCM_GPROC1 (s_acosh, "$acosh", scm_tc7_dsubr, (SCM (*)()) acosh, g_acosh);
4663 /* "Return the inverse hyperbolic cosine of @var{x}."
4664 */
4665
4666
4667 double
4668 scm_atanh (double x)
4669 {
4670 #if HAVE_ATANH
4671 return atanh (x);
4672 #else
4673 #define atanh scm_atanh
4674 return 0.5 * log ((1 + x) / (1 - x));
4675 #endif
4676 }
4677 SCM_GPROC1 (s_atanh, "$atanh", scm_tc7_dsubr, (SCM (*)()) atanh, g_atanh);
4678 /* "Return the inverse hyperbolic tangent of @var{x}."
4679 */
4680
4681
4682 /* XXX - eventually, we should remove this definition of scm_round and
4683 rename scm_round_number to scm_round. Likewise for scm_truncate
4684 and scm_truncate_number.
4685 */
4686
4687 double
4688 scm_truncate (double x)
4689 {
4690 #if HAVE_TRUNC
4691 return trunc (x);
4692 #else
4693 #define trunc scm_truncate
4694 if (x < 0.0)
4695 return -floor (-x);
4696 return floor (x);
4697 #endif
4698 }
4699
4700 double
4701 scm_round (double x)
4702 {
4703 double plus_half = x + 0.5;
4704 double result = floor (plus_half);
4705 /* Adjust so that the scm_round is towards even. */
4706 return ((plus_half == result && plus_half / 2 != floor (plus_half / 2))
4707 ? result - 1
4708 : result);
4709 }
4710
4711 SCM_DEFINE (scm_truncate_number, "truncate", 1, 0, 0,
4712 (SCM x),
4713 "Round the number @var{x} towards zero.")
4714 #define FUNC_NAME s_scm_truncate_number
4715 {
4716 if (SCM_FALSEP (scm_negative_p (x)))
4717 return scm_floor (x);
4718 else
4719 return scm_ceiling (x);
4720 }
4721 #undef FUNC_NAME
4722
4723 static SCM exactly_one_half;
4724
4725 SCM_DEFINE (scm_round_number, "round", 1, 0, 0,
4726 (SCM x),
4727 "Round the number @var{x} towards the nearest integer. "
4728 "When it is exactly halfway between two integers, "
4729 "round towards the even one.")
4730 #define FUNC_NAME s_scm_round_number
4731 {
4732 SCM plus_half = scm_sum (x, exactly_one_half);
4733 SCM result = scm_floor (plus_half);
4734 /* Adjust so that the scm_round is towards even. */
4735 if (!SCM_FALSEP (scm_num_eq_p (plus_half, result))
4736 && !SCM_FALSEP (scm_odd_p (result)))
4737 return scm_difference (result, SCM_MAKINUM (1));
4738 else
4739 return result;
4740 }
4741 #undef FUNC_NAME
4742
4743 SCM_PRIMITIVE_GENERIC (scm_floor, "floor", 1, 0, 0,
4744 (SCM x),
4745 "Round the number @var{x} towards minus infinity.")
4746 #define FUNC_NAME s_scm_floor
4747 {
4748 if (SCM_INUMP (x) || SCM_BIGP (x))
4749 return x;
4750 else if (SCM_REALP (x))
4751 return scm_make_real (floor (SCM_REAL_VALUE (x)));
4752 else if (SCM_FRACTIONP (x))
4753 {
4754 SCM q = scm_quotient (SCM_FRACTION_NUMERATOR (x),
4755 SCM_FRACTION_DENOMINATOR (x));
4756 if (SCM_FALSEP (scm_negative_p (x)))
4757 {
4758 /* For positive x, rounding towards zero is correct. */
4759 return q;
4760 }
4761 else
4762 {
4763 /* For negative x, we need to return q-1 unless x is an
4764 integer. But fractions are never integer, per our
4765 assumptions. */
4766 return scm_difference (q, SCM_MAKINUM (1));
4767 }
4768 }
4769 else
4770 SCM_WTA_DISPATCH_1 (g_scm_floor, x, 1, s_scm_floor);
4771 }
4772 #undef FUNC_NAME
4773
4774 SCM_PRIMITIVE_GENERIC (scm_ceiling, "ceiling", 1, 0, 0,
4775 (SCM x),
4776 "Round the number @var{x} towards infinity.")
4777 #define FUNC_NAME s_scm_ceiling
4778 {
4779 if (SCM_INUMP (x) || SCM_BIGP (x))
4780 return x;
4781 else if (SCM_REALP (x))
4782 return scm_make_real (ceil (SCM_REAL_VALUE (x)));
4783 else if (SCM_FRACTIONP (x))
4784 {
4785 SCM q = scm_quotient (SCM_FRACTION_NUMERATOR (x),
4786 SCM_FRACTION_DENOMINATOR (x));
4787 if (SCM_FALSEP (scm_positive_p (x)))
4788 {
4789 /* For negative x, rounding towards zero is correct. */
4790 return q;
4791 }
4792 else
4793 {
4794 /* For positive x, we need to return q+1 unless x is an
4795 integer. But fractions are never integer, per our
4796 assumptions. */
4797 return scm_sum (q, SCM_MAKINUM (1));
4798 }
4799 }
4800 else
4801 SCM_WTA_DISPATCH_1 (g_scm_ceiling, x, 1, s_scm_ceiling);
4802 }
4803 #undef FUNC_NAME
4804
4805 SCM_GPROC1 (s_i_sqrt, "$sqrt", scm_tc7_dsubr, (SCM (*)()) sqrt, g_i_sqrt);
4806 /* "Return the square root of the real number @var{x}."
4807 */
4808 SCM_GPROC1 (s_i_abs, "$abs", scm_tc7_dsubr, (SCM (*)()) fabs, g_i_abs);
4809 /* "Return the absolute value of the real number @var{x}."
4810 */
4811 SCM_GPROC1 (s_i_exp, "$exp", scm_tc7_dsubr, (SCM (*)()) exp, g_i_exp);
4812 /* "Return the @var{x}th power of e."
4813 */
4814 SCM_GPROC1 (s_i_log, "$log", scm_tc7_dsubr, (SCM (*)()) log, g_i_log);
4815 /* "Return the natural logarithm of the real number @var{x}."
4816 */
4817 SCM_GPROC1 (s_i_sin, "$sin", scm_tc7_dsubr, (SCM (*)()) sin, g_i_sin);
4818 /* "Return the sine of the real number @var{x}."
4819 */
4820 SCM_GPROC1 (s_i_cos, "$cos", scm_tc7_dsubr, (SCM (*)()) cos, g_i_cos);
4821 /* "Return the cosine of the real number @var{x}."
4822 */
4823 SCM_GPROC1 (s_i_tan, "$tan", scm_tc7_dsubr, (SCM (*)()) tan, g_i_tan);
4824 /* "Return the tangent of the real number @var{x}."
4825 */
4826 SCM_GPROC1 (s_i_asin, "$asin", scm_tc7_dsubr, (SCM (*)()) asin, g_i_asin);
4827 /* "Return the arc sine of the real number @var{x}."
4828 */
4829 SCM_GPROC1 (s_i_acos, "$acos", scm_tc7_dsubr, (SCM (*)()) acos, g_i_acos);
4830 /* "Return the arc cosine of the real number @var{x}."
4831 */
4832 SCM_GPROC1 (s_i_atan, "$atan", scm_tc7_dsubr, (SCM (*)()) atan, g_i_atan);
4833 /* "Return the arc tangent of the real number @var{x}."
4834 */
4835 SCM_GPROC1 (s_i_sinh, "$sinh", scm_tc7_dsubr, (SCM (*)()) sinh, g_i_sinh);
4836 /* "Return the hyperbolic sine of the real number @var{x}."
4837 */
4838 SCM_GPROC1 (s_i_cosh, "$cosh", scm_tc7_dsubr, (SCM (*)()) cosh, g_i_cosh);
4839 /* "Return the hyperbolic cosine of the real number @var{x}."
4840 */
4841 SCM_GPROC1 (s_i_tanh, "$tanh", scm_tc7_dsubr, (SCM (*)()) tanh, g_i_tanh);
4842 /* "Return the hyperbolic tangent of the real number @var{x}."
4843 */
4844
4845 struct dpair
4846 {
4847 double x, y;
4848 };
4849
4850 static void scm_two_doubles (SCM x,
4851 SCM y,
4852 const char *sstring,
4853 struct dpair * xy);
4854
4855 static void
4856 scm_two_doubles (SCM x, SCM y, const char *sstring, struct dpair *xy)
4857 {
4858 if (SCM_INUMP (x))
4859 xy->x = SCM_INUM (x);
4860 else if (SCM_BIGP (x))
4861 xy->x = scm_i_big2dbl (x);
4862 else if (SCM_REALP (x))
4863 xy->x = SCM_REAL_VALUE (x);
4864 else if (SCM_FRACTIONP (x))
4865 xy->x = scm_i_fraction2double (x);
4866 else
4867 scm_wrong_type_arg (sstring, SCM_ARG1, x);
4868
4869 if (SCM_INUMP (y))
4870 xy->y = SCM_INUM (y);
4871 else if (SCM_BIGP (y))
4872 xy->y = scm_i_big2dbl (y);
4873 else if (SCM_REALP (y))
4874 xy->y = SCM_REAL_VALUE (y);
4875 else if (SCM_FRACTIONP (y))
4876 xy->y = scm_i_fraction2double (y);
4877 else
4878 scm_wrong_type_arg (sstring, SCM_ARG2, y);
4879 }
4880
4881
4882 SCM_DEFINE (scm_sys_expt, "$expt", 2, 0, 0,
4883 (SCM x, SCM y),
4884 "Return @var{x} raised to the power of @var{y}. This\n"
4885 "procedure does not accept complex arguments.")
4886 #define FUNC_NAME s_scm_sys_expt
4887 {
4888 struct dpair xy;
4889 scm_two_doubles (x, y, FUNC_NAME, &xy);
4890 return scm_make_real (pow (xy.x, xy.y));
4891 }
4892 #undef FUNC_NAME
4893
4894
4895 SCM_DEFINE (scm_sys_atan2, "$atan2", 2, 0, 0,
4896 (SCM x, SCM y),
4897 "Return the arc tangent of the two arguments @var{x} and\n"
4898 "@var{y}. This is similar to calculating the arc tangent of\n"
4899 "@var{x} / @var{y}, except that the signs of both arguments\n"
4900 "are used to determine the quadrant of the result. This\n"
4901 "procedure does not accept complex arguments.")
4902 #define FUNC_NAME s_scm_sys_atan2
4903 {
4904 struct dpair xy;
4905 scm_two_doubles (x, y, FUNC_NAME, &xy);
4906 return scm_make_real (atan2 (xy.x, xy.y));
4907 }
4908 #undef FUNC_NAME
4909
4910
4911 SCM_DEFINE (scm_make_rectangular, "make-rectangular", 2, 0, 0,
4912 (SCM real, SCM imaginary),
4913 "Return a complex number constructed of the given @var{real} and\n"
4914 "@var{imaginary} parts.")
4915 #define FUNC_NAME s_scm_make_rectangular
4916 {
4917 struct dpair xy;
4918 scm_two_doubles (real, imaginary, FUNC_NAME, &xy);
4919 return scm_make_complex (xy.x, xy.y);
4920 }
4921 #undef FUNC_NAME
4922
4923
4924
4925 SCM_DEFINE (scm_make_polar, "make-polar", 2, 0, 0,
4926 (SCM x, SCM y),
4927 "Return the complex number @var{x} * e^(i * @var{y}).")
4928 #define FUNC_NAME s_scm_make_polar
4929 {
4930 struct dpair xy;
4931 double s, c;
4932 scm_two_doubles (x, y, FUNC_NAME, &xy);
4933 #if HAVE_SINCOS
4934 sincos (xy.y, &s, &c);
4935 #else
4936 s = sin (xy.y);
4937 c = cos (xy.y);
4938 #endif
4939 return scm_make_complex (xy.x * c, xy.x * s);
4940 }
4941 #undef FUNC_NAME
4942
4943
4944 SCM_GPROC (s_real_part, "real-part", 1, 0, 0, scm_real_part, g_real_part);
4945 /* "Return the real part of the number @var{z}."
4946 */
4947 SCM
4948 scm_real_part (SCM z)
4949 {
4950 if (SCM_INUMP (z))
4951 return z;
4952 else if (SCM_BIGP (z))
4953 return z;
4954 else if (SCM_REALP (z))
4955 return z;
4956 else if (SCM_COMPLEXP (z))
4957 return scm_make_real (SCM_COMPLEX_REAL (z));
4958 else if (SCM_FRACTIONP (z))
4959 return scm_make_real (scm_i_fraction2double (z));
4960 else
4961 SCM_WTA_DISPATCH_1 (g_real_part, z, SCM_ARG1, s_real_part);
4962 }
4963
4964
4965 SCM_GPROC (s_imag_part, "imag-part", 1, 0, 0, scm_imag_part, g_imag_part);
4966 /* "Return the imaginary part of the number @var{z}."
4967 */
4968 SCM
4969 scm_imag_part (SCM z)
4970 {
4971 if (SCM_INUMP (z))
4972 return SCM_INUM0;
4973 else if (SCM_BIGP (z))
4974 return SCM_INUM0;
4975 else if (SCM_REALP (z))
4976 return scm_flo0;
4977 else if (SCM_COMPLEXP (z))
4978 return scm_make_real (SCM_COMPLEX_IMAG (z));
4979 else if (SCM_FRACTIONP (z))
4980 return SCM_INUM0;
4981 else
4982 SCM_WTA_DISPATCH_1 (g_imag_part, z, SCM_ARG1, s_imag_part);
4983 }
4984
4985 SCM_GPROC (s_numerator, "numerator", 1, 0, 0, scm_numerator, g_numerator);
4986 /* "Return the numerator of the number @var{z}."
4987 */
4988 SCM
4989 scm_numerator (SCM z)
4990 {
4991 if (SCM_INUMP (z))
4992 return z;
4993 else if (SCM_BIGP (z))
4994 return z;
4995 else if (SCM_FRACTIONP (z))
4996 {
4997 scm_i_fraction_reduce (z);
4998 return SCM_FRACTION_NUMERATOR (z);
4999 }
5000 else if (SCM_REALP (z))
5001 return scm_exact_to_inexact (scm_numerator (scm_inexact_to_exact (z)));
5002 else
5003 SCM_WTA_DISPATCH_1 (g_numerator, z, SCM_ARG1, s_numerator);
5004 }
5005
5006
5007 SCM_GPROC (s_denominator, "denominator", 1, 0, 0, scm_denominator, g_denominator);
5008 /* "Return the denominator of the number @var{z}."
5009 */
5010 SCM
5011 scm_denominator (SCM z)
5012 {
5013 if (SCM_INUMP (z))
5014 return SCM_MAKINUM (1);
5015 else if (SCM_BIGP (z))
5016 return SCM_MAKINUM (1);
5017 else if (SCM_FRACTIONP (z))
5018 {
5019 scm_i_fraction_reduce (z);
5020 return SCM_FRACTION_DENOMINATOR (z);
5021 }
5022 else if (SCM_REALP (z))
5023 return scm_exact_to_inexact (scm_denominator (scm_inexact_to_exact (z)));
5024 else
5025 SCM_WTA_DISPATCH_1 (g_denominator, z, SCM_ARG1, s_denominator);
5026 }
5027
5028 SCM_GPROC (s_magnitude, "magnitude", 1, 0, 0, scm_magnitude, g_magnitude);
5029 /* "Return the magnitude of the number @var{z}. This is the same as\n"
5030 * "@code{abs} for real arguments, but also allows complex numbers."
5031 */
5032 SCM
5033 scm_magnitude (SCM z)
5034 {
5035 if (SCM_INUMP (z))
5036 {
5037 long int zz = SCM_INUM (z);
5038 if (zz >= 0)
5039 return z;
5040 else if (SCM_POSFIXABLE (-zz))
5041 return SCM_MAKINUM (-zz);
5042 else
5043 return scm_i_long2big (-zz);
5044 }
5045 else if (SCM_BIGP (z))
5046 {
5047 int sgn = mpz_sgn (SCM_I_BIG_MPZ (z));
5048 scm_remember_upto_here_1 (z);
5049 if (sgn < 0)
5050 return scm_i_clonebig (z, 0);
5051 else
5052 return z;
5053 }
5054 else if (SCM_REALP (z))
5055 return scm_make_real (fabs (SCM_REAL_VALUE (z)));
5056 else if (SCM_COMPLEXP (z))
5057 return scm_make_real (hypot (SCM_COMPLEX_REAL (z), SCM_COMPLEX_IMAG (z)));
5058 else if (SCM_FRACTIONP (z))
5059 {
5060 if (SCM_FALSEP (scm_negative_p (SCM_FRACTION_NUMERATOR (z))))
5061 return z;
5062 return scm_make_ratio (scm_difference (SCM_FRACTION_NUMERATOR (z), SCM_UNDEFINED),
5063 SCM_FRACTION_DENOMINATOR (z));
5064 }
5065 else
5066 SCM_WTA_DISPATCH_1 (g_magnitude, z, SCM_ARG1, s_magnitude);
5067 }
5068
5069
5070 SCM_GPROC (s_angle, "angle", 1, 0, 0, scm_angle, g_angle);
5071 /* "Return the angle of the complex number @var{z}."
5072 */
5073 SCM
5074 scm_angle (SCM z)
5075 {
5076 /* atan(0,-1) is pi and it'd be possible to have that as a constant like
5077 scm_flo0 to save allocating a new flonum with scm_make_real each time.
5078 But if atan2 follows the floating point rounding mode, then the value
5079 is not a constant. Maybe it'd be close enough though. */
5080 if (SCM_INUMP (z))
5081 {
5082 if (SCM_INUM (z) >= 0)
5083 return scm_flo0;
5084 else
5085 return scm_make_real (atan2 (0.0, -1.0));
5086 }
5087 else if (SCM_BIGP (z))
5088 {
5089 int sgn = mpz_sgn (SCM_I_BIG_MPZ (z));
5090 scm_remember_upto_here_1 (z);
5091 if (sgn < 0)
5092 return scm_make_real (atan2 (0.0, -1.0));
5093 else
5094 return scm_flo0;
5095 }
5096 else if (SCM_REALP (z))
5097 {
5098 if (SCM_REAL_VALUE (z) >= 0)
5099 return scm_flo0;
5100 else
5101 return scm_make_real (atan2 (0.0, -1.0));
5102 }
5103 else if (SCM_COMPLEXP (z))
5104 return scm_make_real (atan2 (SCM_COMPLEX_IMAG (z), SCM_COMPLEX_REAL (z)));
5105 else if (SCM_FRACTIONP (z))
5106 {
5107 if (SCM_FALSEP (scm_negative_p (SCM_FRACTION_NUMERATOR (z))))
5108 return scm_flo0;
5109 else return scm_make_real (atan2 (0.0, -1.0));
5110 }
5111 else
5112 SCM_WTA_DISPATCH_1 (g_angle, z, SCM_ARG1, s_angle);
5113 }
5114
5115
5116 SCM_GPROC (s_exact_to_inexact, "exact->inexact", 1, 0, 0, scm_exact_to_inexact, g_exact_to_inexact);
5117 /* Convert the number @var{x} to its inexact representation.\n"
5118 */
5119 SCM
5120 scm_exact_to_inexact (SCM z)
5121 {
5122 if (SCM_INUMP (z))
5123 return scm_make_real ((double) SCM_INUM (z));
5124 else if (SCM_BIGP (z))
5125 return scm_make_real (scm_i_big2dbl (z));
5126 else if (SCM_FRACTIONP (z))
5127 return scm_make_real (scm_i_fraction2double (z));
5128 else if (SCM_INEXACTP (z))
5129 return z;
5130 else
5131 SCM_WTA_DISPATCH_1 (g_exact_to_inexact, z, 1, s_exact_to_inexact);
5132 }
5133
5134
5135 SCM_DEFINE (scm_inexact_to_exact, "inexact->exact", 1, 0, 0,
5136 (SCM z),
5137 "Return an exact number that is numerically closest to @var{z}.")
5138 #define FUNC_NAME s_scm_inexact_to_exact
5139 {
5140 if (SCM_INUMP (z))
5141 return z;
5142 else if (SCM_BIGP (z))
5143 return z;
5144 else if (SCM_REALP (z))
5145 {
5146 if (xisinf (SCM_REAL_VALUE (z)) || xisnan (SCM_REAL_VALUE (z)))
5147 SCM_OUT_OF_RANGE (1, z);
5148 else
5149 {
5150 mpq_t frac;
5151 SCM q;
5152
5153 mpq_init (frac);
5154 mpq_set_d (frac, SCM_REAL_VALUE (z));
5155 q = scm_make_ratio (scm_i_mpz2num (mpq_numref (frac)),
5156 scm_i_mpz2num (mpq_denref (frac)));
5157
5158 /* When scm_make_ratio throws, we leak the memory allocated
5159 for frac...
5160 */
5161 mpq_clear (frac);
5162 return q;
5163 }
5164 }
5165 else if (SCM_FRACTIONP (z))
5166 return z;
5167 else
5168 SCM_WRONG_TYPE_ARG (1, z);
5169 }
5170 #undef FUNC_NAME
5171
5172 SCM_DEFINE (scm_rationalize, "rationalize", 2, 0, 0,
5173 (SCM x, SCM err),
5174 "Return an exact number that is within @var{err} of @var{x}.")
5175 #define FUNC_NAME s_scm_rationalize
5176 {
5177 if (SCM_INUMP (x))
5178 return x;
5179 else if (SCM_BIGP (x))
5180 return x;
5181 else if ((SCM_REALP (x)) || SCM_FRACTIONP (x))
5182 {
5183 /* Use continued fractions to find closest ratio. All
5184 arithmetic is done with exact numbers.
5185 */
5186
5187 SCM ex = scm_inexact_to_exact (x);
5188 SCM int_part = scm_floor (ex);
5189 SCM tt = SCM_MAKINUM (1);
5190 SCM a1 = SCM_MAKINUM (0), a2 = SCM_MAKINUM (1), a = SCM_MAKINUM (0);
5191 SCM b1 = SCM_MAKINUM (1), b2 = SCM_MAKINUM (0), b = SCM_MAKINUM (0);
5192 SCM rx;
5193 int i = 0;
5194
5195 if (!SCM_FALSEP (scm_num_eq_p (ex, int_part)))
5196 return ex;
5197
5198 ex = scm_difference (ex, int_part); /* x = x-int_part */
5199 rx = scm_divide (ex, SCM_UNDEFINED); /* rx = 1/x */
5200
5201 /* We stop after a million iterations just to be absolutely sure
5202 that we don't go into an infinite loop. The process normally
5203 converges after less than a dozen iterations.
5204 */
5205
5206 err = scm_abs (err);
5207 while (++i < 1000000)
5208 {
5209 a = scm_sum (scm_product (a1, tt), a2); /* a = a1*tt + a2 */
5210 b = scm_sum (scm_product (b1, tt), b2); /* b = b1*tt + b2 */
5211 if (SCM_FALSEP (scm_zero_p (b)) && /* b != 0 */
5212 SCM_FALSEP
5213 (scm_gr_p (scm_abs (scm_difference (ex, scm_divide (a, b))),
5214 err))) /* abs(x-a/b) <= err */
5215 {
5216 SCM res = scm_sum (int_part, scm_divide (a, b));
5217 if (SCM_FALSEP (scm_exact_p (x))
5218 || SCM_FALSEP (scm_exact_p (err)))
5219 return scm_exact_to_inexact (res);
5220 else
5221 return res;
5222 }
5223 rx = scm_divide (scm_difference (rx, tt), /* rx = 1/(rx - tt) */
5224 SCM_UNDEFINED);
5225 tt = scm_floor (rx); /* tt = floor (rx) */
5226 a2 = a1;
5227 b2 = b1;
5228 a1 = a;
5229 b1 = b;
5230 }
5231 scm_num_overflow (s_scm_rationalize);
5232 }
5233 else
5234 SCM_WRONG_TYPE_ARG (1, x);
5235 }
5236 #undef FUNC_NAME
5237
5238 /* if you need to change this, change test-num2integral.c as well */
5239 #if SCM_SIZEOF_LONG_LONG != 0
5240 # ifndef LLONG_MAX
5241 # define ULLONG_MAX ((unsigned long long) (-1))
5242 # define LLONG_MAX ((long long) (ULLONG_MAX >> 1))
5243 # define LLONG_MIN (~LLONG_MAX)
5244 # endif
5245 #endif
5246
5247 /* Parameters for creating integer conversion routines.
5248
5249 Define the following preprocessor macros before including
5250 "libguile/num2integral.i.c":
5251
5252 NUM2INTEGRAL - the name of the function for converting from a
5253 Scheme object to the integral type. This function will be
5254 defined when including "num2integral.i.c".
5255
5256 INTEGRAL2NUM - the name of the function for converting from the
5257 integral type to a Scheme object. This function will be defined.
5258
5259 INTEGRAL2BIG - the name of an internal function that createas a
5260 bignum from the integral type. This function will be defined.
5261 The name should start with "scm_i_".
5262
5263 ITYPE - the name of the integral type.
5264
5265 UNSIGNED - Define this to 1 when ITYPE is an unsigned type. Define
5266 it to 0 otherwise.
5267
5268 UNSIGNED_ITYPE - the name of the the unsigned variant of the
5269 integral type. If you don't define this, it defaults to
5270 "unsigned ITYPE" for signed types and simply "ITYPE" for unsigned
5271 ones.
5272
5273 SIZEOF_ITYPE - an expression giving the size of the integral type
5274 in bytes. This expression must be computable by the
5275 preprocessor. (SIZEOF_FOO values are calculated by configure.in
5276 for common types).
5277
5278 */
5279
5280 #define NUM2INTEGRAL scm_num2short
5281 #define INTEGRAL2NUM scm_short2num
5282 #define INTEGRAL2BIG scm_i_short2big
5283 #define UNSIGNED 0
5284 #define ITYPE short
5285 #define SIZEOF_ITYPE SIZEOF_SHORT
5286 #include "libguile/num2integral.i.c"
5287
5288 #define NUM2INTEGRAL scm_num2ushort
5289 #define INTEGRAL2NUM scm_ushort2num
5290 #define INTEGRAL2BIG scm_i_ushort2big
5291 #define UNSIGNED 1
5292 #define ITYPE unsigned short
5293 #define SIZEOF_ITYPE SIZEOF_UNSIGNED_SHORT
5294 #include "libguile/num2integral.i.c"
5295
5296 #define NUM2INTEGRAL scm_num2int
5297 #define INTEGRAL2NUM scm_int2num
5298 #define INTEGRAL2BIG scm_i_int2big
5299 #define UNSIGNED 0
5300 #define ITYPE int
5301 #define SIZEOF_ITYPE SIZEOF_INT
5302 #include "libguile/num2integral.i.c"
5303
5304 #define NUM2INTEGRAL scm_num2uint
5305 #define INTEGRAL2NUM scm_uint2num
5306 #define INTEGRAL2BIG scm_i_uint2big
5307 #define UNSIGNED 1
5308 #define ITYPE unsigned int
5309 #define SIZEOF_ITYPE SIZEOF_UNSIGNED_INT
5310 #include "libguile/num2integral.i.c"
5311
5312 #define NUM2INTEGRAL scm_num2long
5313 #define INTEGRAL2NUM scm_long2num
5314 #define INTEGRAL2BIG scm_i_long2big
5315 #define UNSIGNED 0
5316 #define ITYPE long
5317 #define SIZEOF_ITYPE SIZEOF_LONG
5318 #include "libguile/num2integral.i.c"
5319
5320 #define NUM2INTEGRAL scm_num2ulong
5321 #define INTEGRAL2NUM scm_ulong2num
5322 #define INTEGRAL2BIG scm_i_ulong2big
5323 #define UNSIGNED 1
5324 #define ITYPE unsigned long
5325 #define SIZEOF_ITYPE SIZEOF_UNSIGNED_LONG
5326 #include "libguile/num2integral.i.c"
5327
5328 #define NUM2INTEGRAL scm_num2ptrdiff
5329 #define INTEGRAL2NUM scm_ptrdiff2num
5330 #define INTEGRAL2BIG scm_i_ptrdiff2big
5331 #define UNSIGNED 0
5332 #define ITYPE scm_t_ptrdiff
5333 #define UNSIGNED_ITYPE size_t
5334 #define SIZEOF_ITYPE SCM_SIZEOF_SCM_T_PTRDIFF
5335 #include "libguile/num2integral.i.c"
5336
5337 #define NUM2INTEGRAL scm_num2size
5338 #define INTEGRAL2NUM scm_size2num
5339 #define INTEGRAL2BIG scm_i_size2big
5340 #define UNSIGNED 1
5341 #define ITYPE size_t
5342 #define SIZEOF_ITYPE SIZEOF_SIZE_T
5343 #include "libguile/num2integral.i.c"
5344
5345 #if SCM_SIZEOF_LONG_LONG != 0
5346
5347 #ifndef ULONG_LONG_MAX
5348 #define ULONG_LONG_MAX (~0ULL)
5349 #endif
5350
5351 #define NUM2INTEGRAL scm_num2long_long
5352 #define INTEGRAL2NUM scm_long_long2num
5353 #define INTEGRAL2BIG scm_i_long_long2big
5354 #define UNSIGNED 0
5355 #define ITYPE long long
5356 #define SIZEOF_ITYPE SIZEOF_LONG_LONG
5357 #include "libguile/num2integral.i.c"
5358
5359 #define NUM2INTEGRAL scm_num2ulong_long
5360 #define INTEGRAL2NUM scm_ulong_long2num
5361 #define INTEGRAL2BIG scm_i_ulong_long2big
5362 #define UNSIGNED 1
5363 #define ITYPE unsigned long long
5364 #define SIZEOF_ITYPE SIZEOF_UNSIGNED_LONG_LONG
5365 #include "libguile/num2integral.i.c"
5366
5367 #endif /* SCM_SIZEOF_LONG_LONG != 0 */
5368
5369 #define NUM2FLOAT scm_num2float
5370 #define FLOAT2NUM scm_float2num
5371 #define FTYPE float
5372 #include "libguile/num2float.i.c"
5373
5374 #define NUM2FLOAT scm_num2double
5375 #define FLOAT2NUM scm_double2num
5376 #define FTYPE double
5377 #include "libguile/num2float.i.c"
5378
5379 #ifdef GUILE_DEBUG
5380
5381 #ifndef SIZE_MAX
5382 #define SIZE_MAX ((size_t) (-1))
5383 #endif
5384 #ifndef PTRDIFF_MIN
5385 #define PTRDIFF_MIN \
5386 ((scm_t_ptrdiff) ((scm_t_ptrdiff) 1 \
5387 << ((sizeof (scm_t_ptrdiff) * SCM_CHAR_BIT) - 1)))
5388 #endif
5389 #ifndef PTRDIFF_MAX
5390 #define PTRDIFF_MAX (~ PTRDIFF_MIN)
5391 #endif
5392
5393 #define CHECK(type, v) \
5394 do \
5395 { \
5396 if ((v) != scm_num2##type (scm_##type##2num (v), 1, "check_sanity")) \
5397 abort (); \
5398 } \
5399 while (0)
5400
5401 static void
5402 check_sanity ()
5403 {
5404 CHECK (short, 0);
5405 CHECK (ushort, 0U);
5406 CHECK (int, 0);
5407 CHECK (uint, 0U);
5408 CHECK (long, 0L);
5409 CHECK (ulong, 0UL);
5410 CHECK (size, 0);
5411 CHECK (ptrdiff, 0);
5412
5413 CHECK (short, -1);
5414 CHECK (int, -1);
5415 CHECK (long, -1L);
5416 CHECK (ptrdiff, -1);
5417
5418 CHECK (short, SHRT_MAX);
5419 CHECK (short, SHRT_MIN);
5420 CHECK (ushort, USHRT_MAX);
5421 CHECK (int, INT_MAX);
5422 CHECK (int, INT_MIN);
5423 CHECK (uint, UINT_MAX);
5424 CHECK (long, LONG_MAX);
5425 CHECK (long, LONG_MIN);
5426 CHECK (ulong, ULONG_MAX);
5427 CHECK (size, SIZE_MAX);
5428 CHECK (ptrdiff, PTRDIFF_MAX);
5429 CHECK (ptrdiff, PTRDIFF_MIN);
5430
5431 #if SCM_SIZEOF_LONG_LONG != 0
5432 CHECK (long_long, 0LL);
5433 CHECK (ulong_long, 0ULL);
5434 CHECK (long_long, -1LL);
5435 CHECK (long_long, LLONG_MAX);
5436 CHECK (long_long, LLONG_MIN);
5437 CHECK (ulong_long, ULLONG_MAX);
5438 #endif
5439 }
5440
5441 #undef CHECK
5442
5443 #define CHECK \
5444 scm_internal_catch (SCM_BOOL_T, check_body, &data, check_handler, &data); \
5445 if (!SCM_FALSEP (data)) abort();
5446
5447 static SCM
5448 check_body (void *data)
5449 {
5450 SCM num = *(SCM *) data;
5451 scm_num2ulong (num, 1, NULL);
5452
5453 return SCM_UNSPECIFIED;
5454 }
5455
5456 static SCM
5457 check_handler (void *data, SCM tag, SCM throw_args)
5458 {
5459 SCM *num = (SCM *) data;
5460 *num = SCM_BOOL_F;
5461
5462 return SCM_UNSPECIFIED;
5463 }
5464
5465 SCM_DEFINE (scm_sys_check_number_conversions, "%check-number-conversions", 0, 0, 0,
5466 (void),
5467 "Number conversion sanity checking.")
5468 #define FUNC_NAME s_scm_sys_check_number_conversions
5469 {
5470 SCM data = SCM_MAKINUM (-1);
5471 CHECK;
5472 data = scm_int2num (INT_MIN);
5473 CHECK;
5474 data = scm_ulong2num (ULONG_MAX);
5475 data = scm_difference (SCM_INUM0, data);
5476 CHECK;
5477 data = scm_ulong2num (ULONG_MAX);
5478 data = scm_sum (SCM_MAKINUM (1), data); data = scm_difference (SCM_INUM0, data);
5479 CHECK;
5480 data = scm_int2num (-10000); data = scm_product (data, data); data = scm_product (data, data);
5481 CHECK;
5482
5483 return SCM_UNSPECIFIED;
5484 }
5485 #undef FUNC_NAME
5486
5487 #endif
5488
5489 void
5490 scm_init_numbers ()
5491 {
5492 abs_most_negative_fixnum = scm_i_long2big (- SCM_MOST_NEGATIVE_FIXNUM);
5493 scm_permanent_object (abs_most_negative_fixnum);
5494
5495 mpz_init_set_si (z_negative_one, -1);
5496
5497 /* It may be possible to tune the performance of some algorithms by using
5498 * the following constants to avoid the creation of bignums. Please, before
5499 * using these values, remember the two rules of program optimization:
5500 * 1st Rule: Don't do it. 2nd Rule (experts only): Don't do it yet. */
5501 scm_c_define ("most-positive-fixnum",
5502 SCM_MAKINUM (SCM_MOST_POSITIVE_FIXNUM));
5503 scm_c_define ("most-negative-fixnum",
5504 SCM_MAKINUM (SCM_MOST_NEGATIVE_FIXNUM));
5505
5506 scm_add_feature ("complex");
5507 scm_add_feature ("inexact");
5508 scm_flo0 = scm_make_real (0.0);
5509 #ifdef DBL_DIG
5510 scm_dblprec = (DBL_DIG > 20) ? 20 : DBL_DIG;
5511 #else
5512 { /* determine floating point precision */
5513 double f = 0.1;
5514 double fsum = 1.0 + f;
5515 while (fsum != 1.0)
5516 {
5517 if (++scm_dblprec > 20)
5518 fsum = 1.0;
5519 else
5520 {
5521 f /= 10.0;
5522 fsum = f + 1.0;
5523 }
5524 }
5525 scm_dblprec = scm_dblprec - 1;
5526 }
5527 #endif /* DBL_DIG */
5528
5529 #ifdef GUILE_DEBUG
5530 check_sanity ();
5531 #endif
5532
5533 exactly_one_half = scm_permanent_object (scm_divide (SCM_MAKINUM (1),
5534 SCM_MAKINUM (2)));
5535 #include "libguile/numbers.x"
5536 }
5537
5538 /*
5539 Local Variables:
5540 c-file-style: "gnu"
5541 End:
5542 */