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