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