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