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