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