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