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