3fc5126425c76158767f28658cbfbfa38e7c7ec2
[bpt/guile.git] / libguile / numbers.c
1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002, 2003 Free Software Foundation, Inc.
2 *
3 * Portions Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories
4 * and Bellcore. See scm_divide.
5 *
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 \f
23 /* General assumptions:
24 * All objects satisfying SCM_COMPLEXP() have a non-zero complex component.
25 * All objects satisfying SCM_BIGP() are too large to fit in a fixnum.
26 * If an object satisfies integer?, it's either an inum, a bignum, or a real.
27 * If floor (r) == r, r is an int, and mpz_set_d will DTRT.
28 */
29
30 /* TODO:
31
32 - see if special casing bignums and reals in integer-exponent when
33 possible (to use mpz_pow and mpf_pow_ui) is faster.
34
35 - look in to better short-circuiting of common cases in
36 integer-expt and elsewhere.
37
38 - see if direct mpz operations can help in ash and elsewhere.
39
40 */
41
42 #if HAVE_CONFIG_H
43 # include <config.h>
44 #endif
45
46 #include <math.h>
47 #include <ctype.h>
48 #include <string.h>
49 #include <gmp.h>
50 #include "libguile/_scm.h"
51 #include "libguile/feature.h"
52 #include "libguile/ports.h"
53 #include "libguile/root.h"
54 #include "libguile/smob.h"
55 #include "libguile/strings.h"
56
57 #include "libguile/validate.h"
58 #include "libguile/numbers.h"
59 #include "libguile/deprecation.h"
60
61 \f
62
63 /*
64 Wonder if this might be faster for some of our code? A switch on
65 the numtag would jump directly to the right case, and the
66 SCM_I_NUMTAG code might be faster than repeated SCM_FOOP tests...
67
68 #define SCM_I_NUMTAG_NOTNUM 0
69 #define SCM_I_NUMTAG_INUM 1
70 #define SCM_I_NUMTAG_BIG scm_tc16_big
71 #define SCM_I_NUMTAG_REAL scm_tc16_real
72 #define SCM_I_NUMTAG_COMPLEX scm_tc16_complex
73 #define SCM_I_NUMTAG(x) \
74 (SCM_INUMP(x) ? SCM_I_NUMTAG_INUM \
75 : (SCM_IMP(x) ? SCM_I_NUMTAG_NOTNUM \
76 : (((0xfcff & SCM_CELL_TYPE (x)) == scm_tc7_smob) ? SCM_TYP16(x) \
77 : SCM_I_NUMTAG_NOTNUM)))
78 */
79
80
81 #define SCM_SWAP(x, y) do { SCM __t = x; x = y; y = __t; } while (0)
82
83 /* FLOBUFLEN is the maximum number of characters neccessary for the
84 * printed or scm_string representation of an inexact number.
85 */
86 #define FLOBUFLEN (10+2*(sizeof(double)/sizeof(char)*SCM_CHAR_BIT*3+9)/10)
87
88 #if defined (SCO)
89 #if ! defined (HAVE_ISNAN)
90 #define HAVE_ISNAN
91 static int
92 isnan (double x)
93 {
94 return (IsNANorINF (x) && NaN (x) && ! IsINF (x)) ? 1 : 0;
95 }
96 #endif
97 #if ! defined (HAVE_ISINF)
98 #define HAVE_ISINF
99 static int
100 isinf (double x)
101 {
102 return (IsNANorINF (x) && IsINF (x)) ? 1 : 0;
103 }
104
105 #endif
106 #endif
107
108 \f
109
110 static SCM abs_most_negative_fixnum;
111
112 \f
113
114 static const char s_bignum[] = "bignum";
115
116 SCM_C_INLINE SCM
117 scm_i_mkbig ()
118 {
119 /* Return a newly created bignum. */
120 SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
121 mpz_init (SCM_I_BIG_MPZ (z));
122 return z;
123 }
124
125 SCM_C_INLINE static SCM
126 scm_i_clonebig (SCM src_big, int same_sign_p)
127 {
128 /* Copy src_big's value, negate it if same_sign_p is false, and return. */
129 SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
130 mpz_init_set (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (src_big));
131 if (!same_sign_p) mpz_neg (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (z));
132 return z;
133 }
134
135 SCM_C_INLINE int
136 scm_i_bigcmp (SCM x, SCM y)
137 {
138 /* Return neg if x < y, pos if x > y, and 0 if x == y */
139 /* presume we already know x and y are bignums */
140 int result = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
141 scm_remember_upto_here_2 (x, y);
142 return result;
143 }
144
145 SCM_C_INLINE SCM
146 scm_i_dbl2big (double d)
147 {
148 /* results are only defined if d is an integer */
149 SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
150 mpz_init_set_d (SCM_I_BIG_MPZ (z), d);
151 return z;
152 }
153
154 SCM_C_INLINE double
155 scm_i_big2dbl (SCM b)
156 {
157 double result = mpz_get_d (SCM_I_BIG_MPZ (b));
158 scm_remember_upto_here_1 (b);
159 return result;
160 }
161
162 SCM_C_INLINE SCM
163 scm_i_normbig (SCM b)
164 {
165 /* convert a big back to a fixnum if it'll fit */
166 /* presume b is a bignum */
167 if (mpz_fits_slong_p (SCM_I_BIG_MPZ (b)))
168 {
169 long val = mpz_get_si (SCM_I_BIG_MPZ (b));
170 if (SCM_FIXABLE (val))
171 b = SCM_MAKINUM (val);
172 }
173 return b;
174 }
175
176 SCM_DEFINE (scm_exact_p, "exact?", 1, 0, 0,
177 (SCM x),
178 "Return @code{#t} if @var{x} is an exact number, @code{#f}\n"
179 "otherwise.")
180 #define FUNC_NAME s_scm_exact_p
181 {
182 if (SCM_INUMP (x)) return SCM_BOOL_T;
183 if (SCM_BIGP (x)) return SCM_BOOL_T;
184 return SCM_BOOL_F;
185 }
186 #undef FUNC_NAME
187
188
189 SCM_DEFINE (scm_odd_p, "odd?", 1, 0, 0,
190 (SCM n),
191 "Return @code{#t} if @var{n} is an odd number, @code{#f}\n"
192 "otherwise.")
193 #define FUNC_NAME s_scm_odd_p
194 {
195 if (SCM_INUMP (n)) {
196 long val = SCM_INUM (n);
197 return SCM_BOOL ((val & 1L) != 0);
198 } else if (SCM_BIGP (n)) {
199 int odd_p = mpz_odd_p (SCM_I_BIG_MPZ (n));
200 scm_remember_upto_here_1 (n);
201 return SCM_BOOL (odd_p);
202 } else if (scm_inf_p (n)) {
203 return SCM_BOOL_T;
204 } else {
205 SCM_WRONG_TYPE_ARG (1, n);
206 }
207 }
208 #undef FUNC_NAME
209
210
211 SCM_DEFINE (scm_even_p, "even?", 1, 0, 0,
212 (SCM n),
213 "Return @code{#t} if @var{n} is an even number, @code{#f}\n"
214 "otherwise.")
215 #define FUNC_NAME s_scm_even_p
216 {
217 if (SCM_INUMP (n)) {
218 long val = SCM_INUM (n);
219 return SCM_BOOL ((val & 1L) == 0);
220 } else if (SCM_BIGP (n)) {
221 int even_p = mpz_even_p (SCM_I_BIG_MPZ (n));
222 scm_remember_upto_here_1 (n);
223 return SCM_BOOL (even_p);
224 } else if (scm_inf_p (n)) {
225 return SCM_BOOL_T;
226 } else {
227 SCM_WRONG_TYPE_ARG (1, n);
228 }
229 }
230 #undef FUNC_NAME
231
232 static int
233 xisinf (double x)
234 {
235 #if defined (HAVE_ISINF)
236 return isinf (x);
237 #elif defined (HAVE_FINITE) && defined (HAVE_ISNAN)
238 return (! (finite (x) || isnan (x)));
239 #else
240 return 0;
241 #endif
242 }
243
244 static int
245 xisnan (double x)
246 {
247 #if defined (HAVE_ISNAN)
248 return isnan (x);
249 #else
250 return 0;
251 #endif
252 }
253
254 #define isfinite(x) (! xisinf (x))
255
256 SCM_DEFINE (scm_inf_p, "inf?", 1, 0, 0,
257 (SCM n),
258 "Return @code{#t} if @var{n} is infinite, @code{#f}\n"
259 "otherwise.")
260 #define FUNC_NAME s_scm_inf_p
261 {
262 if (SCM_REALP (n)) {
263 return SCM_BOOL (xisinf (SCM_REAL_VALUE (n)));
264 } else if (SCM_COMPLEXP (n)) {
265 return SCM_BOOL (xisinf (SCM_COMPLEX_REAL (n))
266 || xisinf (SCM_COMPLEX_IMAG (n)));
267 } else {
268 return SCM_BOOL_F;
269 }
270 }
271 #undef FUNC_NAME
272
273 SCM_DEFINE (scm_nan_p, "nan?", 1, 0, 0,
274 (SCM n),
275 "Return @code{#t} if @var{n} is a NaN, @code{#f}\n"
276 "otherwise.")
277 #define FUNC_NAME s_scm_nan_p
278 {
279 if (SCM_REALP (n)) {
280 return SCM_BOOL (xisnan (SCM_REAL_VALUE (n)));
281 } else if (SCM_COMPLEXP (n)) {
282 return SCM_BOOL (xisnan (SCM_COMPLEX_REAL (n))
283 || xisnan (SCM_COMPLEX_IMAG (n)));
284 } else {
285 return SCM_BOOL_F;
286 }
287 }
288 #undef FUNC_NAME
289
290 /* Guile's idea of infinity. */
291 static double guile_Inf;
292
293 /* Guile's idea of not a number. */
294 static double guile_NaN;
295
296 static void
297 guile_ieee_init (void)
298 {
299 #if defined (HAVE_ISINF) || defined (HAVE_FINITE)
300
301 /* Some version of gcc on some old version of Linux used to crash when
302 trying to make Inf and NaN. */
303
304 #if defined (SCO)
305 double tmp = 1.0;
306 guile_Inf = 1.0 / (tmp - tmp);
307 #elif defined (__alpha__) && ! defined (linux)
308 extern unsigned int DINFINITY[2];
309 guile_Inf = (*(X_CAST(double *, DINFINITY)));
310 #else
311 double tmp = 1e+10;
312 guile_Inf = tmp;
313 for (;;)
314 {
315 guile_Inf *= 1e+10;
316 if (guile_Inf == tmp)
317 break;
318 tmp = guile_Inf;
319 }
320 #endif
321
322 #endif
323
324 #if defined (HAVE_ISNAN)
325
326 #if defined (__alpha__) && ! defined (linux)
327 extern unsigned int DQNAN[2];
328 guile_NaN = (*(X_CAST(double *, DQNAN)));
329 #else
330 guile_NaN = guile_Inf / guile_Inf;
331 #endif
332
333 #endif
334 }
335
336 SCM_DEFINE (scm_inf, "inf", 0, 0, 0,
337 (void),
338 "Return Inf.")
339 #define FUNC_NAME s_scm_inf
340 {
341 static int initialized = 0;
342 if (! initialized)
343 {
344 guile_ieee_init ();
345 initialized = 1;
346 }
347 return scm_make_real (guile_Inf);
348 }
349 #undef FUNC_NAME
350
351 SCM_DEFINE (scm_nan, "nan", 0, 0, 0,
352 (void),
353 "Return NaN.")
354 #define FUNC_NAME s_scm_nan
355 {
356 static int initialized = 0;
357 if (! initialized)
358 {
359 guile_ieee_init ();
360 initialized = 1;
361 }
362 return scm_make_real (guile_NaN);
363 }
364 #undef FUNC_NAME
365
366
367 SCM_PRIMITIVE_GENERIC (scm_abs, "abs", 1, 0, 0,
368 (SCM x),
369 "Return the absolute value of @var{x}.")
370 #define FUNC_NAME
371 {
372 if (SCM_INUMP (x)) {
373 long int xx = SCM_INUM (x);
374 if (xx >= 0) {
375 return x;
376 } else if (SCM_POSFIXABLE (-xx)) {
377 return SCM_MAKINUM (-xx);
378 } else {
379 return scm_i_long2big (-xx);
380 }
381 } else if (SCM_BIGP (x)) {
382 const int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
383 if (sgn < 0) {
384 return scm_i_clonebig (x, 0);
385 } else {
386 return x;
387 }
388 } else if (SCM_REALP (x)) {
389 return scm_make_real (fabs (SCM_REAL_VALUE (x)));
390 } else {
391 SCM_WTA_DISPATCH_1 (g_scm_abs, x, 1, s_scm_abs);
392 }
393 }
394 #undef FUNC_NAME
395
396
397 SCM_GPROC (s_quotient, "quotient", 2, 0, 0, scm_quotient, g_quotient);
398 /* "Return the quotient of the numbers @var{x} and @var{y}."
399 */
400 SCM
401 scm_quotient (SCM x, SCM y)
402 {
403 if (SCM_INUMP (x)) {
404 long xx = SCM_INUM (x);
405 if (SCM_INUMP (y)) {
406 long yy = SCM_INUM (y);
407 if (yy == 0) {
408 scm_num_overflow (s_quotient);
409 } else {
410 long z = xx / yy;
411 if (SCM_FIXABLE (z)) {
412 return SCM_MAKINUM (z);
413 } else {
414 return scm_i_long2big (z);
415 }
416 }
417 } else if (SCM_BIGP (y)) {
418 if ((SCM_INUM (x) == SCM_MOST_NEGATIVE_FIXNUM)
419 && (scm_i_bigcmp (abs_most_negative_fixnum, y) == 0))
420 {
421 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
422 return SCM_MAKINUM (-1);
423 }
424 else
425 return SCM_MAKINUM (0);
426 } else {
427 SCM_WTA_DISPATCH_2 (g_quotient, x, y, SCM_ARG2, s_quotient);
428 }
429 } else if (SCM_BIGP (x)) {
430 if (SCM_INUMP (y)) {
431 long yy = SCM_INUM (y);
432 if (yy == 0) {
433 scm_num_overflow (s_quotient);
434 } else if (yy == 1) {
435 return x;
436 } else {
437 SCM result = scm_i_mkbig ();
438 if (yy < 0) {
439 mpz_tdiv_q_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), - yy);
440 mpz_neg(SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result));
441 } else {
442 mpz_tdiv_q_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), yy);
443 }
444 scm_remember_upto_here_1 (x);
445 return scm_i_normbig (result);
446 }
447 } else if (SCM_BIGP (y)) {
448 SCM result = scm_i_mkbig ();
449 mpz_tdiv_q(SCM_I_BIG_MPZ (result),
450 SCM_I_BIG_MPZ (x),
451 SCM_I_BIG_MPZ (y));
452 scm_remember_upto_here_2 (x, y);
453 return scm_i_normbig (result);
454 } else {
455 SCM_WTA_DISPATCH_2 (g_quotient, x, y, SCM_ARG2, s_quotient);
456 }
457 } else {
458 SCM_WTA_DISPATCH_2 (g_quotient, x, y, SCM_ARG1, s_quotient);
459 }
460 }
461
462 SCM_GPROC (s_remainder, "remainder", 2, 0, 0, scm_remainder, g_remainder);
463 /* "Return the remainder of the numbers @var{x} and @var{y}.\n"
464 * "@lisp\n"
465 * "(remainder 13 4) @result{} 1\n"
466 * "(remainder -13 4) @result{} -1\n"
467 * "@end lisp"
468 */
469 SCM
470 scm_remainder (SCM x, SCM y)
471 {
472 if (SCM_INUMP (x)) {
473 if (SCM_INUMP (y)) {
474 long yy = SCM_INUM (y);
475 if (yy == 0) {
476 scm_num_overflow (s_remainder);
477 } else {
478 long z = SCM_INUM (x) % yy;
479 return SCM_MAKINUM (z);
480 }
481 } else if (SCM_BIGP (y)) {
482 if ((SCM_INUM (x) == SCM_MOST_NEGATIVE_FIXNUM)
483 && (scm_i_bigcmp (abs_most_negative_fixnum, y) == 0))
484 {
485 /* Special case: x == fixnum-min && y == abs (fixnum-min) */
486 return SCM_MAKINUM (0);
487 }
488 else
489 return x;
490 } else {
491 SCM_WTA_DISPATCH_2 (g_remainder, x, y, SCM_ARG2, s_remainder);
492 }
493 } else if (SCM_BIGP (x)) {
494 if (SCM_INUMP (y)) {
495 long yy = SCM_INUM (y);
496 if (yy == 0) {
497 scm_num_overflow (s_remainder);
498 } else {
499 SCM result = scm_i_mkbig ();
500 if (yy < 0) yy = - yy;
501 mpz_tdiv_r_ui(SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ(x), yy);
502 scm_remember_upto_here_1(x);
503 return scm_i_normbig (result);
504 }
505 } else if (SCM_BIGP (y)) {
506 SCM result = scm_i_mkbig ();
507 mpz_tdiv_r (SCM_I_BIG_MPZ (result),
508 SCM_I_BIG_MPZ (x),
509 SCM_I_BIG_MPZ (y));
510 scm_remember_upto_here_2(x, y);
511 return scm_i_normbig (result);
512 } else {
513 SCM_WTA_DISPATCH_2 (g_remainder, x, y, SCM_ARG2, s_remainder);
514 }
515 } else {
516 SCM_WTA_DISPATCH_2 (g_remainder, x, y, SCM_ARG1, s_remainder);
517 }
518 }
519
520
521 SCM_GPROC (s_modulo, "modulo", 2, 0, 0, scm_modulo, g_modulo);
522 /* "Return the modulo of the numbers @var{x} and @var{y}.\n"
523 * "@lisp\n"
524 * "(modulo 13 4) @result{} 1\n"
525 * "(modulo -13 4) @result{} 3\n"
526 * "@end lisp"
527 */
528 SCM
529 scm_modulo (SCM x, SCM y)
530 {
531 if (SCM_INUMP (x)) {
532 long xx = SCM_INUM (x);
533 if (SCM_INUMP (y)) {
534 long yy = SCM_INUM (y);
535 if (yy == 0) {
536 scm_num_overflow (s_modulo);
537 } else {
538 /* FIXME: I think this may be a bug on some arches -- results
539 of % with negative second arg are undefined... */
540 long z = xx % yy;
541 long result;
542
543 if (yy < 0) {
544 if (z > 0) result = z + yy;
545 else result = z;
546 } else {
547 if (z < 0) result = z + yy;
548 else result = z;
549 }
550 return SCM_MAKINUM (result);
551 }
552 } else if (SCM_BIGP (y)) {
553 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
554
555 if (sgn_y == 0) {
556 scm_num_overflow (s_modulo);
557 } else {
558 mpz_t z_x;
559 SCM result;
560
561 if (sgn_y < 0) {
562 SCM pos_y = scm_i_clonebig (y, 0);
563 /* do this after the last scm_op */
564 mpz_init_set_si (z_x, xx);
565 result = pos_y; /* re-use this bignum */
566 mpz_mod (SCM_I_BIG_MPZ (result), z_x, SCM_I_BIG_MPZ (pos_y));
567 scm_remember_upto_here_1 (pos_y);
568 } else {
569 result = scm_i_mkbig ();
570 /* do this after the last scm_op */
571 mpz_init_set_si (z_x, xx);
572 mpz_mod (SCM_I_BIG_MPZ (result), z_x, SCM_I_BIG_MPZ (y));
573 scm_remember_upto_here_1 (y);
574 }
575
576 if ((sgn_y < 0) && mpz_sgn (SCM_I_BIG_MPZ (result)) != 0) {
577 mpz_add (SCM_I_BIG_MPZ (result),
578 SCM_I_BIG_MPZ (y),
579 SCM_I_BIG_MPZ (result));
580 }
581 scm_remember_upto_here_1 (y);
582 /* and do this before the next one */
583 mpz_clear (z_x);
584 return scm_i_normbig (result);
585 }
586 } else {
587 SCM_WTA_DISPATCH_2 (g_modulo, x, y, SCM_ARG2, s_modulo);
588 }
589 } else if (SCM_BIGP (x)) {
590 if (SCM_INUMP (y)) {
591 long yy = SCM_INUM (y);
592 if (yy == 0) {
593 scm_num_overflow (s_modulo);
594 } else {
595 SCM result = scm_i_mkbig ();
596 mpz_mod_ui (SCM_I_BIG_MPZ (result),
597 SCM_I_BIG_MPZ (x),
598 (yy < 0) ? - yy : yy);
599 scm_remember_upto_here_1 (x);
600 if ((yy < 0) && (mpz_sgn (SCM_I_BIG_MPZ (result)) != 0)) {
601 mpz_sub_ui (SCM_I_BIG_MPZ (result),
602 SCM_I_BIG_MPZ (result),
603 - yy);
604 }
605 return scm_i_normbig (result);
606 }
607 } else if (SCM_BIGP (y)) {
608 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
609 if (sgn_y == 0) {
610 scm_num_overflow (s_modulo);
611 } else {
612 SCM result = scm_i_mkbig ();
613 int y_sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
614 SCM pos_y = scm_i_clonebig (y, y_sgn >= 0);
615 mpz_mod (SCM_I_BIG_MPZ (result),
616 SCM_I_BIG_MPZ (x),
617 SCM_I_BIG_MPZ (pos_y));
618
619 scm_remember_upto_here_1 (x);
620 if ((y_sgn < 0) && (mpz_sgn (SCM_I_BIG_MPZ (result)) != 0)) {
621 mpz_add (SCM_I_BIG_MPZ (result),
622 SCM_I_BIG_MPZ (y),
623 SCM_I_BIG_MPZ (result));
624 }
625 scm_remember_upto_here_2 (y, pos_y);
626 return scm_i_normbig (result);
627 }
628 } else {
629 SCM_WTA_DISPATCH_2 (g_modulo, x, y, SCM_ARG2, s_modulo);
630 }
631 } else {
632 SCM_WTA_DISPATCH_2 (g_modulo, x, y, SCM_ARG1, s_modulo);
633 }
634 }
635
636 SCM_GPROC1 (s_gcd, "gcd", scm_tc7_asubr, scm_gcd, g_gcd);
637 /* "Return the greatest common divisor of all arguments.\n"
638 * "If called without arguments, 0 is returned."
639 */
640 SCM
641 scm_gcd (SCM x, SCM y)
642 {
643 if (SCM_UNBNDP (y))
644 return (SCM_UNBNDP (x)) ? SCM_INUM0 : x;
645
646 if (SCM_INUMP (x))
647 {
648 if (SCM_INUMP (y))
649 {
650 long xx = SCM_INUM (x);
651 long yy = SCM_INUM (y);
652 long u = xx < 0 ? -xx : xx;
653 long v = yy < 0 ? -yy : yy;
654 long result;
655 if (xx == 0) {
656 result = v;
657 } else if (yy == 0) {
658 result = u;
659 } else {
660 long k = 1;
661 long t;
662 /* Determine a common factor 2^k */
663 while (!(1 & (u | v)))
664 {
665 k <<= 1;
666 u >>= 1;
667 v >>= 1;
668 }
669 /* Now, any factor 2^n can be eliminated */
670 if (u & 1)
671 t = -v;
672 else
673 {
674 t = u;
675 b3:
676 t = SCM_SRS (t, 1);
677 }
678 if (!(1 & t))
679 goto b3;
680 if (t > 0)
681 u = t;
682 else
683 v = -t;
684 t = u - v;
685 if (t != 0)
686 goto b3;
687 result = u * k;
688 }
689 return SCM_POSFIXABLE (result) \
690 ? SCM_MAKINUM (result) : scm_i_long2big (result);
691 }
692 else if (SCM_BIGP (y))
693 {
694 SCM result = scm_i_mkbig ();
695 SCM mx = scm_i_mkbig ();
696 mpz_set_si(SCM_I_BIG_MPZ (mx), SCM_INUM (x));
697 scm_remember_upto_here_1 (x);
698 mpz_gcd(SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (mx), SCM_I_BIG_MPZ (y));
699 scm_remember_upto_here_2(mx, y);
700 return scm_i_normbig (result);
701 }
702 else
703 SCM_WTA_DISPATCH_2 (g_gcd, x, y, SCM_ARG2, s_gcd);
704 }
705 else if (SCM_BIGP (x))
706 {
707 if (SCM_INUMP (y))
708 {
709 unsigned long result;
710 long yy = SCM_INUM (y);
711 if (yy < 0) yy = -yy;
712 result = mpz_gcd_ui (NULL, SCM_I_BIG_MPZ (x), yy);
713 scm_remember_upto_here_1 (x);
714 return SCM_POSFIXABLE (result) \
715 ? SCM_MAKINUM (result) : scm_ulong2num (result);
716 }
717 else if (SCM_BIGP (y))
718 {
719 SCM result = scm_i_mkbig ();
720 mpz_gcd(SCM_I_BIG_MPZ (result),
721 SCM_I_BIG_MPZ (x),
722 SCM_I_BIG_MPZ (y));
723 scm_remember_upto_here_2(x, y);
724 return scm_i_normbig (result);
725 }
726 else
727 SCM_WTA_DISPATCH_2 (g_gcd, x, y, SCM_ARG2, s_gcd);
728 }
729 else
730 SCM_WTA_DISPATCH_2 (g_gcd, x, y, SCM_ARG1, s_gcd);
731 }
732
733 SCM_GPROC1 (s_lcm, "lcm", scm_tc7_asubr, scm_lcm, g_lcm);
734 /* "Return the least common multiple of the arguments.\n"
735 * "If called without arguments, 1 is returned."
736 */
737 SCM
738 scm_lcm (SCM n1, SCM n2)
739 {
740 if (SCM_UNBNDP (n2))
741 {
742 if (SCM_UNBNDP (n1))
743 return SCM_MAKINUM (1L);
744 n2 = SCM_MAKINUM (1L);
745 }
746
747 SCM_GASSERT2 (SCM_INUMP (n1) || SCM_BIGP (n1),
748 g_lcm, n1, n2, SCM_ARG1, s_lcm);
749 SCM_GASSERT2 (SCM_INUMP (n2) || SCM_BIGP (n2),
750 g_lcm, n1, n2, SCM_ARGn, s_lcm);
751
752 if (SCM_INUMP (n1))
753 {
754 if (SCM_INUMP (n2))
755 {
756 SCM d = scm_gcd (n1, n2);
757 if (SCM_EQ_P (d, SCM_INUM0))
758 return d;
759 else
760 return scm_abs (scm_product (n1, scm_quotient (n2, d)));
761 }
762 else
763 {
764 /* inum n1, big n2 */
765 inumbig:
766 {
767 SCM result = scm_i_mkbig ();
768 long nn1 = SCM_INUM (n1);
769 if (nn1 == 0) return SCM_INUM0;
770 if (nn1 < 0) nn1 = - nn1;
771 mpz_lcm_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (n2), nn1);
772 scm_remember_upto_here_1 (n2);
773 return result;
774 }
775 }
776 }
777 else
778 {
779 /* big n1 */
780 if (SCM_INUMP (n2))
781 {
782 SCM_SWAP (n1, n2);
783 goto inumbig;
784 }
785 else
786 {
787 SCM result = scm_i_mkbig ();
788 mpz_lcm(SCM_I_BIG_MPZ (result),
789 SCM_I_BIG_MPZ (n1),
790 SCM_I_BIG_MPZ (n2));
791 scm_remember_upto_here_2(n1, n2);
792 /* shouldn't need to normalize b/c lcm of 2 bigs should be big */
793 return result;
794 }
795 }
796 }
797
798 #ifndef scm_long2num
799 #define SCM_LOGOP_RETURN(x) scm_ulong2num(x)
800 #else
801 #define SCM_LOGOP_RETURN(x) SCM_MAKINUM(x)
802 #endif
803
804 /* Emulating 2's complement bignums with sign magnitude arithmetic:
805
806 Logand:
807 X Y Result Method:
808 (len)
809 + + + x (map digit:logand X Y)
810 + - + x (map digit:logand X (lognot (+ -1 Y)))
811 - + + y (map digit:logand (lognot (+ -1 X)) Y)
812 - - - (+ 1 (map digit:logior (+ -1 X) (+ -1 Y)))
813
814 Logior:
815 X Y Result Method:
816
817 + + + (map digit:logior X Y)
818 + - - y (+ 1 (map digit:logand (lognot X) (+ -1 Y)))
819 - + - x (+ 1 (map digit:logand (+ -1 X) (lognot Y)))
820 - - - x (+ 1 (map digit:logand (+ -1 X) (+ -1 Y)))
821
822 Logxor:
823 X Y Result Method:
824
825 + + + (map digit:logxor X Y)
826 + - - (+ 1 (map digit:logxor X (+ -1 Y)))
827 - + - (+ 1 (map digit:logxor (+ -1 X) Y))
828 - - + (map digit:logxor (+ -1 X) (+ -1 Y))
829
830 Logtest:
831 X Y Result
832
833 + + (any digit:logand X Y)
834 + - (any digit:logand X (lognot (+ -1 Y)))
835 - + (any digit:logand (lognot (+ -1 X)) Y)
836 - - #t
837
838 */
839
840 SCM_DEFINE1 (scm_logand, "logand", scm_tc7_asubr,
841 (SCM n1, SCM n2),
842 "Return the bitwise AND of the integer arguments.\n\n"
843 "@lisp\n"
844 "(logand) @result{} -1\n"
845 "(logand 7) @result{} 7\n"
846 "(logand #b111 #b011 #\b001) @result{} 1\n"
847 "@end lisp")
848 #define FUNC_NAME s_scm_logand
849 {
850 long int nn1;
851
852 if (SCM_UNBNDP (n2)) {
853 if (SCM_UNBNDP (n1)) {
854 return SCM_MAKINUM (-1);
855 } else if (!SCM_NUMBERP (n1)) {
856 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
857 } else if (SCM_NUMBERP (n1)) {
858 return n1;
859 } else {
860 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
861 }
862 }
863
864 if (SCM_INUMP (n1)) {
865 nn1 = SCM_INUM (n1);
866 if (SCM_INUMP (n2)) {
867 long nn2 = SCM_INUM (n2);
868 return SCM_MAKINUM (nn1 & nn2);
869 } else if SCM_BIGP (n2) {
870 intbig:
871 if (n1 == 0) return SCM_INUM0;
872 {
873 SCM result_z = scm_i_mkbig ();
874 mpz_t nn1_z;
875 mpz_init_set_si (nn1_z, nn1);
876 mpz_and (SCM_I_BIG_MPZ (result_z), nn1_z, SCM_I_BIG_MPZ (n2));
877 scm_remember_upto_here_1 (n2);
878 mpz_clear (nn1_z);
879 return scm_i_normbig (result_z);
880 }
881 } else {
882 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
883 }
884 } else if (SCM_BIGP (n1)) {
885 if (SCM_INUMP (n2)) {
886 SCM_SWAP (n1, n2);
887 nn1 = SCM_INUM (n1);
888 goto intbig;
889 } else if (SCM_BIGP (n2)) {
890 SCM result_z = scm_i_mkbig ();
891 mpz_and (SCM_I_BIG_MPZ (result_z),
892 SCM_I_BIG_MPZ (n1),
893 SCM_I_BIG_MPZ (n2));
894 scm_remember_upto_here_2 (n1, n2);
895 return scm_i_normbig (result_z);
896 } else {
897 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
898 }
899 } else {
900 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
901 }
902 }
903 #undef FUNC_NAME
904
905
906 SCM_DEFINE1 (scm_logior, "logior", scm_tc7_asubr,
907 (SCM n1, SCM n2),
908 "Return the bitwise OR of the integer arguments.\n\n"
909 "@lisp\n"
910 "(logior) @result{} 0\n"
911 "(logior 7) @result{} 7\n"
912 "(logior #b000 #b001 #b011) @result{} 3\n"
913 "@end lisp")
914 #define FUNC_NAME s_scm_logior
915 {
916 long int nn1;
917
918 if (SCM_UNBNDP (n2)) {
919 if (SCM_UNBNDP (n1)) {
920 return SCM_INUM0;
921 } else if (SCM_NUMBERP (n1)) {
922 return n1;
923 } else {
924 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
925 }
926 }
927
928 if (SCM_INUMP (n1)) {
929 nn1 = SCM_INUM (n1);
930 if (SCM_INUMP (n2)) {
931 long nn2 = SCM_INUM (n2);
932 return SCM_MAKINUM (nn1 | nn2);
933 } else if (SCM_BIGP (n2)) {
934 intbig:
935 if (nn1 == 0) return n2;
936 {
937 SCM result_z = scm_i_mkbig ();
938 mpz_t nn1_z;
939 mpz_init_set_si (nn1_z, nn1);
940 mpz_ior (SCM_I_BIG_MPZ (result_z), nn1_z, SCM_I_BIG_MPZ (n2));
941 scm_remember_upto_here_1 (n2);
942 mpz_clear (nn1_z);
943 return result_z;
944 }
945 } else {
946 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
947 }
948 } else if (SCM_BIGP (n1)) {
949 if (SCM_INUMP (n2)) {
950 SCM_SWAP (n1, n2);
951 nn1 = SCM_INUM (n1);
952 goto intbig;
953 } else if (SCM_BIGP (n2)) {
954 SCM result_z = scm_i_mkbig ();
955 mpz_ior (SCM_I_BIG_MPZ (result_z),
956 SCM_I_BIG_MPZ (n1),
957 SCM_I_BIG_MPZ (n2));
958 scm_remember_upto_here_2 (n1, n2);
959 return result_z;
960 } else {
961 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
962 }
963 } else {
964 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
965 }
966 }
967 #undef FUNC_NAME
968
969
970 SCM_DEFINE1 (scm_logxor, "logxor", scm_tc7_asubr,
971 (SCM n1, SCM n2),
972 "Return the bitwise XOR of the integer arguments. A bit is\n"
973 "set in the result if it is set in an odd number of arguments.\n"
974 "@lisp\n"
975 "(logxor) @result{} 0\n"
976 "(logxor 7) @result{} 7\n"
977 "(logxor #b000 #b001 #b011) @result{} 2\n"
978 "(logxor #b000 #b001 #b011 #b011) @result{} 1\n"
979 "@end lisp")
980 #define FUNC_NAME s_scm_logxor
981 {
982 long int nn1;
983
984 if (SCM_UNBNDP (n2)) {
985 if (SCM_UNBNDP (n1)) {
986 return SCM_INUM0;
987 } else if (SCM_NUMBERP (n1)) {
988 return n1;
989 } else {
990 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
991 }
992 }
993
994 if (SCM_INUMP (n1)) {
995 nn1 = SCM_INUM (n1);
996 if (SCM_INUMP (n2)) {
997 long nn2 = SCM_INUM (n2);
998 return SCM_MAKINUM (nn1 ^ nn2);
999 } else if (SCM_BIGP (n2)) {
1000 intbig:
1001 {
1002 SCM result_z = scm_i_mkbig ();
1003 mpz_t nn1_z;
1004 mpz_init_set_si (nn1_z, nn1);
1005 mpz_xor (SCM_I_BIG_MPZ (result_z), nn1_z, SCM_I_BIG_MPZ (n2));
1006 scm_remember_upto_here_1 (n2);
1007 mpz_clear (nn1_z);
1008 return scm_i_normbig (result_z);
1009 }
1010 } else {
1011 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
1012 }
1013 } else if (SCM_BIGP (n1)) {
1014 if (SCM_INUMP (n2)) {
1015 SCM_SWAP (n1, n2);
1016 nn1 = SCM_INUM (n1);
1017 goto intbig;
1018 } else if (SCM_BIGP (n2)) {
1019 SCM result_z = scm_i_mkbig ();
1020 mpz_xor (SCM_I_BIG_MPZ (result_z),
1021 SCM_I_BIG_MPZ (n1),
1022 SCM_I_BIG_MPZ (n2));
1023 scm_remember_upto_here_2 (n1, n2);
1024 return scm_i_normbig (result_z);
1025 } else {
1026 SCM_WRONG_TYPE_ARG (SCM_ARG2, n2);
1027 }
1028 } else {
1029 SCM_WRONG_TYPE_ARG (SCM_ARG1, n1);
1030 }
1031 }
1032 #undef FUNC_NAME
1033
1034
1035 SCM_DEFINE (scm_logtest, "logtest", 2, 0, 0,
1036 (SCM j, SCM k),
1037 "@lisp\n"
1038 "(logtest j k) @equiv{} (not (zero? (logand j k)))\n\n"
1039 "(logtest #b0100 #b1011) @result{} #f\n"
1040 "(logtest #b0100 #b0111) @result{} #t\n"
1041 "@end lisp")
1042 #define FUNC_NAME s_scm_logtest
1043 {
1044 long int nj;
1045
1046 if (SCM_INUMP (j)) {
1047 nj = SCM_INUM (j);
1048 if (SCM_INUMP (k)) {
1049 long nk = SCM_INUM (k);
1050 return SCM_BOOL (nj & nk);
1051 } else if (SCM_BIGP (k)) {
1052 intbig:
1053 if (nj == 0) return SCM_BOOL_F;
1054 {
1055 SCM result;
1056 mpz_t nj_z;
1057 mpz_init_set_si (nj_z, nj);
1058 mpz_and (nj_z, nj_z, SCM_I_BIG_MPZ (k));
1059 scm_remember_upto_here_1 (k);
1060 result = SCM_BOOL (mpz_sgn (nj_z) != 0);
1061 mpz_clear (nj_z);
1062 return result;
1063 }
1064 } else {
1065 SCM_WRONG_TYPE_ARG (SCM_ARG2, k);
1066 }
1067 } else if (SCM_BIGP (j)) {
1068 if (SCM_INUMP (k)) {
1069 SCM_SWAP (j, k);
1070 nj = SCM_INUM (j);
1071 goto intbig;
1072 } else if (SCM_BIGP (k)) {
1073 SCM result;
1074 mpz_t result_z;
1075 mpz_init (result_z);
1076 mpz_and (result_z,
1077 SCM_I_BIG_MPZ (j),
1078 SCM_I_BIG_MPZ (k));
1079 scm_remember_upto_here_2 (j, k);
1080 result = SCM_BOOL (mpz_sgn (result_z) != 0);
1081 mpz_clear (result_z);
1082 return result;
1083 } else {
1084 SCM_WRONG_TYPE_ARG (SCM_ARG2, k);
1085 }
1086 } else {
1087 SCM_WRONG_TYPE_ARG (SCM_ARG1, j);
1088 }
1089 }
1090 #undef FUNC_NAME
1091
1092
1093 SCM_DEFINE (scm_logbit_p, "logbit?", 2, 0, 0,
1094 (SCM index, SCM j),
1095 "@lisp\n"
1096 "(logbit? index j) @equiv{} (logtest (integer-expt 2 index) j)\n\n"
1097 "(logbit? 0 #b1101) @result{} #t\n"
1098 "(logbit? 1 #b1101) @result{} #f\n"
1099 "(logbit? 2 #b1101) @result{} #t\n"
1100 "(logbit? 3 #b1101) @result{} #t\n"
1101 "(logbit? 4 #b1101) @result{} #f\n"
1102 "@end lisp")
1103 #define FUNC_NAME s_scm_logbit_p
1104 {
1105 unsigned long int iindex;
1106
1107 SCM_VALIDATE_INUM_MIN (SCM_ARG1, index, 0);
1108 iindex = (unsigned long int) SCM_INUM (index);
1109
1110 if (SCM_INUMP (j)) {
1111 return SCM_BOOL ((1L << iindex) & SCM_INUM (j));
1112 } else if (SCM_BIGP (j)) {
1113 int val = mpz_tstbit (SCM_I_BIG_MPZ (j), iindex);
1114 scm_remember_upto_here_1 (j);
1115 return SCM_BOOL (val);
1116 } else {
1117 SCM_WRONG_TYPE_ARG (SCM_ARG2, j);
1118 }
1119 }
1120 #undef FUNC_NAME
1121
1122
1123 SCM_DEFINE (scm_lognot, "lognot", 1, 0, 0,
1124 (SCM n),
1125 "Return the integer which is the 2s-complement of the integer\n"
1126 "argument.\n"
1127 "\n"
1128 "@lisp\n"
1129 "(number->string (lognot #b10000000) 2)\n"
1130 " @result{} \"-10000001\"\n"
1131 "(number->string (lognot #b0) 2)\n"
1132 " @result{} \"-1\"\n"
1133 "@end lisp")
1134 #define FUNC_NAME s_scm_lognot
1135 {
1136 return scm_difference (SCM_MAKINUM (-1L), n);
1137 }
1138 #undef FUNC_NAME
1139
1140 SCM_DEFINE (scm_integer_expt, "integer-expt", 2, 0, 0,
1141 (SCM n, SCM k),
1142 "Return @var{n} raised to the non-negative integer exponent\n"
1143 "@var{k}.\n"
1144 "\n"
1145 "@lisp\n"
1146 "(integer-expt 2 5)\n"
1147 " @result{} 32\n"
1148 "(integer-expt -3 3)\n"
1149 " @result{} -27\n"
1150 "@end lisp")
1151 #define FUNC_NAME s_scm_integer_expt
1152 {
1153 long i2 = 0;
1154 SCM z_i2 = SCM_BOOL_F;
1155 int i2_is_big = 0;
1156 SCM acc = SCM_MAKINUM (1L);
1157
1158 /* 0^0 == 1 according to R5RS */
1159 if (SCM_EQ_P (n, SCM_INUM0) || SCM_EQ_P (n, acc))
1160 return SCM_FALSEP (scm_zero_p(k)) ? n : acc;
1161 else if (SCM_EQ_P (n, SCM_MAKINUM (-1L)))
1162 return SCM_FALSEP (scm_even_p (k)) ? n : acc;
1163
1164 if (SCM_INUMP (k))
1165 i2 = SCM_INUM (k);
1166 else if (SCM_BIGP (k))
1167 {
1168 z_i2 = scm_i_clonebig (k, 1);
1169 mpz_init_set (SCM_I_BIG_MPZ (z_i2), SCM_I_BIG_MPZ (k));
1170 scm_remember_upto_here_1 (k);
1171 i2_is_big = 1;
1172 }
1173 else if (SCM_REALP (k))
1174 {
1175 double r = SCM_REAL_VALUE (k);
1176 if (floor (r) != r)
1177 SCM_WRONG_TYPE_ARG (2, k);
1178 if ((r > SCM_MOST_POSITIVE_FIXNUM) || (r < SCM_MOST_NEGATIVE_FIXNUM))
1179 {
1180 z_i2 = scm_i_mkbig ();
1181 mpz_init_set_d (SCM_I_BIG_MPZ (z_i2), r);
1182 i2_is_big = 1;
1183 }
1184 else
1185 {
1186 i2 = r;
1187 }
1188 }
1189 else
1190 SCM_WRONG_TYPE_ARG (2, k);
1191
1192 if (i2_is_big)
1193 {
1194 if (mpz_sgn(SCM_I_BIG_MPZ (z_i2)) == -1)
1195 {
1196 mpz_neg (SCM_I_BIG_MPZ (z_i2), SCM_I_BIG_MPZ (z_i2));
1197 n = scm_divide (n, SCM_UNDEFINED);
1198 }
1199 while (1)
1200 {
1201 if (mpz_sgn(SCM_I_BIG_MPZ (z_i2)) == 0)
1202 {
1203 mpz_clear (SCM_I_BIG_MPZ (z_i2));
1204 return acc;
1205 }
1206 if (mpz_cmp_ui(SCM_I_BIG_MPZ (z_i2), 1) == 0)
1207 {
1208 mpz_clear (SCM_I_BIG_MPZ (z_i2));
1209 return scm_product (acc, n);
1210 }
1211 if (mpz_tstbit(SCM_I_BIG_MPZ (z_i2), 0))
1212 acc = scm_product (acc, n);
1213 n = scm_product (n, n);
1214 mpz_fdiv_q_2exp (SCM_I_BIG_MPZ (z_i2), SCM_I_BIG_MPZ (z_i2), 1);
1215 }
1216 }
1217 else
1218 {
1219 if (i2 < 0)
1220 {
1221 i2 = -i2;
1222 n = scm_divide (n, SCM_UNDEFINED);
1223 }
1224 while (1)
1225 {
1226 if (0 == i2)
1227 return acc;
1228 if (1 == i2)
1229 return scm_product (acc, n);
1230 if (i2 & 1)
1231 acc = scm_product (acc, n);
1232 n = scm_product (n, n);
1233 i2 >>= 1;
1234 }
1235 }
1236 }
1237 #undef FUNC_NAME
1238
1239 SCM_DEFINE (scm_ash, "ash", 2, 0, 0,
1240 (SCM n, SCM cnt),
1241 "The function ash performs an arithmetic shift left by @var{cnt}\n"
1242 "bits (or shift right, if @var{cnt} is negative). 'Arithmetic'\n"
1243 "means, that the function does not guarantee to keep the bit\n"
1244 "structure of @var{n}, but rather guarantees that the result\n"
1245 "will always be rounded towards minus infinity. Therefore, the\n"
1246 "results of ash and a corresponding bitwise shift will differ if\n"
1247 "@var{n} is negative.\n"
1248 "\n"
1249 "Formally, the function returns an integer equivalent to\n"
1250 "@code{(inexact->exact (floor (* @var{n} (expt 2 @var{cnt}))))}.\n"
1251 "\n"
1252 "@lisp\n"
1253 "(number->string (ash #b1 3) 2) @result{} \"1000\"\n"
1254 "(number->string (ash #b1010 -1) 2) @result{} \"101\"\n"
1255 "@end lisp")
1256 #define FUNC_NAME s_scm_ash
1257 {
1258 long bits_to_shift;
1259
1260 SCM_VALIDATE_INUM (2, cnt);
1261
1262 bits_to_shift = SCM_INUM (cnt);
1263
1264 if (bits_to_shift < 0)
1265 {
1266 /* Shift right by abs(cnt) bits. This is realized as a division
1267 by div:=2^abs(cnt). However, to guarantee the floor
1268 rounding, negative values require some special treatment.
1269 */
1270 SCM div = scm_integer_expt (SCM_MAKINUM (2),
1271 SCM_MAKINUM (-bits_to_shift));
1272 if (SCM_FALSEP (scm_negative_p (n)))
1273 return scm_quotient (n, div);
1274 else
1275 return scm_sum (SCM_MAKINUM (-1L),
1276 scm_quotient (scm_sum (SCM_MAKINUM (1L), n), div));
1277 }
1278 else
1279 /* Shift left is done by multiplication with 2^CNT */
1280 return scm_product (n, scm_integer_expt (SCM_MAKINUM (2), cnt));
1281 }
1282 #undef FUNC_NAME
1283
1284
1285 SCM_DEFINE (scm_bit_extract, "bit-extract", 3, 0, 0,
1286 (SCM n, SCM start, SCM end),
1287 "Return the integer composed of the @var{start} (inclusive)\n"
1288 "through @var{end} (exclusive) bits of @var{n}. The\n"
1289 "@var{start}th bit becomes the 0-th bit in the result.\n"
1290 "\n"
1291 "@lisp\n"
1292 "(number->string (bit-extract #b1101101010 0 4) 2)\n"
1293 " @result{} \"1010\"\n"
1294 "(number->string (bit-extract #b1101101010 4 9) 2)\n"
1295 " @result{} \"10110\"\n"
1296 "@end lisp")
1297 #define FUNC_NAME s_scm_bit_extract
1298 {
1299 unsigned long int istart, iend;
1300 SCM_VALIDATE_INUM_MIN_COPY (2, start,0, istart);
1301 SCM_VALIDATE_INUM_MIN_COPY (3, end, 0, iend);
1302 SCM_ASSERT_RANGE (3, end, (iend >= istart));
1303
1304 if (SCM_INUMP (n)) {
1305 long int in = SCM_INUM (n);
1306 unsigned long int bits = iend - istart;
1307
1308 if (in < 0 && bits >= SCM_I_FIXNUM_BIT)
1309 {
1310 /* Since we emulate two's complement encoded numbers, this special
1311 * case requires us to produce a result that has more bits than can be
1312 * stored in a fixnum. Thus, we fall back to the more general
1313 * algorithm that is used for bignums.
1314 */
1315 goto generalcase;
1316 }
1317
1318 if (istart < SCM_I_FIXNUM_BIT)
1319 {
1320 in = in >> istart;
1321 if (bits < SCM_I_FIXNUM_BIT)
1322 return SCM_MAKINUM (in & ((1L << bits) - 1));
1323 else /* we know: in >= 0 */
1324 return SCM_MAKINUM (in);
1325 }
1326 else if (in < 0)
1327 {
1328 return SCM_MAKINUM (-1L & ((1L << bits) - 1));
1329 }
1330 else
1331 {
1332 return SCM_MAKINUM (0);
1333 }
1334 } else if (SCM_BIGP (n)) {
1335 generalcase:
1336 {
1337 SCM num1 = SCM_MAKINUM (1L);
1338 SCM num2 = SCM_MAKINUM (2L);
1339 SCM bits = SCM_MAKINUM (iend - istart);
1340 SCM mask = scm_difference (scm_integer_expt (num2, bits), num1);
1341 return scm_logand (mask, scm_ash (n, SCM_MAKINUM (-istart)));
1342 }
1343 } else {
1344 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1345 }
1346 }
1347 #undef FUNC_NAME
1348
1349 static const char scm_logtab[] = {
1350 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
1351 };
1352
1353 SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
1354 (SCM n),
1355 "Return the number of bits in integer @var{n}. If integer is\n"
1356 "positive, the 1-bits in its binary representation are counted.\n"
1357 "If negative, the 0-bits in its two's-complement binary\n"
1358 "representation are counted. If 0, 0 is returned.\n"
1359 "\n"
1360 "@lisp\n"
1361 "(logcount #b10101010)\n"
1362 " @result{} 4\n"
1363 "(logcount 0)\n"
1364 " @result{} 0\n"
1365 "(logcount -2)\n"
1366 " @result{} 1\n"
1367 "@end lisp")
1368 #define FUNC_NAME s_scm_logcount
1369 {
1370 if (SCM_INUMP (n))
1371 {
1372 unsigned long int c = 0;
1373 long int nn = SCM_INUM (n);
1374 if (nn < 0)
1375 nn = -1 - nn;
1376 while (nn)
1377 {
1378 c += scm_logtab[15 & nn];
1379 nn >>= 4;
1380 }
1381 return SCM_MAKINUM (c);
1382 }
1383 else if (SCM_BIGP (n))
1384 {
1385 unsigned long count;
1386 if (mpz_sgn (SCM_I_BIG_MPZ (n)) < 0)
1387 {
1388 mpz_t z_n;
1389 mpz_init (z_n);
1390 mpz_com (z_n, SCM_I_BIG_MPZ (n));
1391 scm_remember_upto_here_1 (n);
1392 count = mpz_popcount (z_n);
1393 mpz_clear (z_n);
1394 }
1395 else
1396 {
1397 count = mpz_popcount (SCM_I_BIG_MPZ (n));
1398 scm_remember_upto_here_1 (n);
1399 }
1400 return SCM_MAKINUM (count);
1401 }
1402 else
1403 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1404 }
1405 #undef FUNC_NAME
1406
1407
1408 static const char scm_ilentab[] = {
1409 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
1410 };
1411
1412
1413 SCM_DEFINE (scm_integer_length, "integer-length", 1, 0, 0,
1414 (SCM n),
1415 "Return the number of bits necessary to represent @var{n}.\n"
1416 "\n"
1417 "@lisp\n"
1418 "(integer-length #b10101010)\n"
1419 " @result{} 8\n"
1420 "(integer-length 0)\n"
1421 " @result{} 0\n"
1422 "(integer-length #b1111)\n"
1423 " @result{} 4\n"
1424 "@end lisp")
1425 #define FUNC_NAME s_scm_integer_length
1426 {
1427 if (SCM_INUMP (n)) {
1428 unsigned long int c = 0;
1429 unsigned int l = 4;
1430 long int nn = SCM_INUM (n);
1431 if (nn < 0) {
1432 nn = -1 - nn;
1433 };
1434 while (nn) {
1435 c += 4;
1436 l = scm_ilentab [15 & nn];
1437 nn >>= 4;
1438 };
1439 return SCM_MAKINUM (c - 4 + l);
1440 } else if (SCM_BIGP (n)) {
1441 size_t size = mpz_sizeinbase (SCM_I_BIG_MPZ (n), 2);
1442 scm_remember_upto_here_1 (n);
1443 return SCM_MAKINUM (size);
1444 } else {
1445 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1446 }
1447 }
1448 #undef FUNC_NAME
1449
1450 /*** NUMBERS -> STRINGS ***/
1451 int scm_dblprec;
1452 static const double fx[] =
1453 { 0.0, 5e-1, 5e-2, 5e-3, 5e-4, 5e-5,
1454 5e-6, 5e-7, 5e-8, 5e-9, 5e-10,
1455 5e-11, 5e-12, 5e-13, 5e-14, 5e-15,
1456 5e-16, 5e-17, 5e-18, 5e-19, 5e-20};
1457
1458 static size_t
1459 idbl2str (double f, char *a)
1460 {
1461 int efmt, dpt, d, i, wp = scm_dblprec;
1462 size_t ch = 0;
1463 int exp = 0;
1464
1465 if (f == 0.0)
1466 {
1467 #ifdef HAVE_COPYSIGN
1468 double sgn = copysign (1.0, f);
1469
1470 if (sgn < 0.0)
1471 a[ch++] = '-';
1472 #endif
1473
1474 goto zero; /*{a[0]='0'; a[1]='.'; a[2]='0'; return 3;} */
1475 }
1476
1477 if (xisinf (f))
1478 {
1479 if (f < 0)
1480 strcpy (a, "-inf.0");
1481 else
1482 strcpy (a, "+inf.0");
1483 return ch+6;
1484 }
1485 else if (xisnan (f))
1486 {
1487 strcpy (a, "+nan.0");
1488 return ch+6;
1489 }
1490
1491 if (f < 0.0)
1492 {
1493 f = -f;
1494 a[ch++] = '-';
1495 }
1496
1497 #ifdef DBL_MIN_10_EXP /* Prevent unnormalized values, as from
1498 make-uniform-vector, from causing infinite loops. */
1499 while (f < 1.0)
1500 {
1501 f *= 10.0;
1502 if (exp-- < DBL_MIN_10_EXP)
1503 {
1504 a[ch++] = '#';
1505 a[ch++] = '.';
1506 a[ch++] = '#';
1507 return ch;
1508 }
1509 }
1510 while (f > 10.0)
1511 {
1512 f *= 0.10;
1513 if (exp++ > DBL_MAX_10_EXP)
1514 {
1515 a[ch++] = '#';
1516 a[ch++] = '.';
1517 a[ch++] = '#';
1518 return ch;
1519 }
1520 }
1521 #else
1522 while (f < 1.0)
1523 {
1524 f *= 10.0;
1525 exp--;
1526 }
1527 while (f > 10.0)
1528 {
1529 f /= 10.0;
1530 exp++;
1531 }
1532 #endif
1533 if (f + fx[wp] >= 10.0)
1534 {
1535 f = 1.0;
1536 exp++;
1537 }
1538 zero:
1539 #ifdef ENGNOT
1540 dpt = (exp + 9999) % 3;
1541 exp -= dpt++;
1542 efmt = 1;
1543 #else
1544 efmt = (exp < -3) || (exp > wp + 2);
1545 if (!efmt)
1546 {
1547 if (exp < 0)
1548 {
1549 a[ch++] = '0';
1550 a[ch++] = '.';
1551 dpt = exp;
1552 while (++dpt)
1553 a[ch++] = '0';
1554 }
1555 else
1556 dpt = exp + 1;
1557 }
1558 else
1559 dpt = 1;
1560 #endif
1561
1562 do
1563 {
1564 d = f;
1565 f -= d;
1566 a[ch++] = d + '0';
1567 if (f < fx[wp])
1568 break;
1569 if (f + fx[wp] >= 1.0)
1570 {
1571 a[ch - 1]++;
1572 break;
1573 }
1574 f *= 10.0;
1575 if (!(--dpt))
1576 a[ch++] = '.';
1577 }
1578 while (wp--);
1579
1580 if (dpt > 0)
1581 {
1582 #ifndef ENGNOT
1583 if ((dpt > 4) && (exp > 6))
1584 {
1585 d = (a[0] == '-' ? 2 : 1);
1586 for (i = ch++; i > d; i--)
1587 a[i] = a[i - 1];
1588 a[d] = '.';
1589 efmt = 1;
1590 }
1591 else
1592 #endif
1593 {
1594 while (--dpt)
1595 a[ch++] = '0';
1596 a[ch++] = '.';
1597 }
1598 }
1599 if (a[ch - 1] == '.')
1600 a[ch++] = '0'; /* trailing zero */
1601 if (efmt && exp)
1602 {
1603 a[ch++] = 'e';
1604 if (exp < 0)
1605 {
1606 exp = -exp;
1607 a[ch++] = '-';
1608 }
1609 for (i = 10; i <= exp; i *= 10);
1610 for (i /= 10; i; i /= 10)
1611 {
1612 a[ch++] = exp / i + '0';
1613 exp %= i;
1614 }
1615 }
1616 return ch;
1617 }
1618
1619
1620 static size_t
1621 iflo2str (SCM flt, char *str)
1622 {
1623 size_t i;
1624 if (SCM_REALP (flt))
1625 i = idbl2str (SCM_REAL_VALUE (flt), str);
1626 else
1627 {
1628 i = idbl2str (SCM_COMPLEX_REAL (flt), str);
1629 if (SCM_COMPLEX_IMAG (flt) != 0.0)
1630 {
1631 double imag = SCM_COMPLEX_IMAG (flt);
1632 /* Don't output a '+' for negative numbers or for Inf and
1633 NaN. They will provide their own sign. */
1634 if (0 <= imag && !xisinf (imag) && !xisnan (imag))
1635 str[i++] = '+';
1636 i += idbl2str (imag, &str[i]);
1637 str[i++] = 'i';
1638 }
1639 }
1640 return i;
1641 }
1642
1643 /* convert a long to a string (unterminated). returns the number of
1644 characters in the result.
1645 rad is output base
1646 p is destination: worst case (base 2) is SCM_INTBUFLEN */
1647 size_t
1648 scm_iint2str (long num, int rad, char *p)
1649 {
1650 size_t j = 1;
1651 size_t i;
1652 unsigned long n = (num < 0) ? -num : num;
1653
1654 for (n /= rad; n > 0; n /= rad)
1655 j++;
1656
1657 i = j;
1658 if (num < 0)
1659 {
1660 *p++ = '-';
1661 j++;
1662 n = -num;
1663 }
1664 else
1665 n = num;
1666 while (i--)
1667 {
1668 int d = n % rad;
1669
1670 n /= rad;
1671 p[i] = d + ((d < 10) ? '0' : 'a' - 10);
1672 }
1673 return j;
1674 }
1675
1676
1677 SCM_DEFINE (scm_number_to_string, "number->string", 1, 1, 0,
1678 (SCM n, SCM radix),
1679 "Return a string holding the external representation of the\n"
1680 "number @var{n} in the given @var{radix}. If @var{n} is\n"
1681 "inexact, a radix of 10 will be used.")
1682 #define FUNC_NAME s_scm_number_to_string
1683 {
1684 int base;
1685
1686 if (SCM_UNBNDP (radix)) {
1687 base = 10;
1688 } else {
1689 SCM_VALIDATE_INUM (2, radix);
1690 base = SCM_INUM (radix);
1691 /* FIXME: ask if range limit was OK, and if so, document */
1692 SCM_ASSERT_RANGE (2, radix, (base >= 2) && (base <= 36));
1693 }
1694
1695 if (SCM_INUMP (n)) {
1696 char num_buf [SCM_INTBUFLEN];
1697 size_t length = scm_iint2str (SCM_INUM (n), base, num_buf);
1698 return scm_mem2string (num_buf, length);
1699 } else if (SCM_BIGP (n)) {
1700 char *str = mpz_get_str (NULL, base, SCM_I_BIG_MPZ (n));
1701 scm_remember_upto_here_1 (n);
1702 return scm_take0str (str);
1703 } else if (SCM_INEXACTP (n)) {
1704 char num_buf [FLOBUFLEN];
1705 return scm_mem2string (num_buf, iflo2str (n, num_buf));
1706 } else {
1707 SCM_WRONG_TYPE_ARG (1, n);
1708 }
1709 }
1710 #undef FUNC_NAME
1711
1712
1713 /* These print routines used to be stubbed here so that scm_repl.c
1714 wouldn't need SCM_BIGDIG conditionals (pre GMP) */
1715
1716 int
1717 scm_print_real (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
1718 {
1719 char num_buf[FLOBUFLEN];
1720 scm_lfwrite (num_buf, iflo2str (sexp, num_buf), port);
1721 return !0;
1722 }
1723
1724 int
1725 scm_print_complex (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
1726 {
1727 char num_buf[FLOBUFLEN];
1728 scm_lfwrite (num_buf, iflo2str (sexp, num_buf), port);
1729 return !0;
1730 }
1731
1732 int
1733 scm_bigprint (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
1734 {
1735 char *str = mpz_get_str (NULL, 10, SCM_I_BIG_MPZ (exp));
1736 scm_remember_upto_here_1 (exp);
1737 scm_lfwrite (str, (size_t) strlen (str), port);
1738 free (str);
1739 return !0;
1740 }
1741 /*** END nums->strs ***/
1742
1743
1744 /*** STRINGS -> NUMBERS ***/
1745
1746 /* The following functions implement the conversion from strings to numbers.
1747 * The implementation somehow follows the grammar for numbers as it is given
1748 * in R5RS. Thus, the functions resemble syntactic units (<ureal R>,
1749 * <uinteger R>, ...) that are used to build up numbers in the grammar. Some
1750 * points should be noted about the implementation:
1751 * * Each function keeps a local index variable 'idx' that points at the
1752 * current position within the parsed string. The global index is only
1753 * updated if the function could parse the corresponding syntactic unit
1754 * successfully.
1755 * * Similarly, the functions keep track of indicators of inexactness ('#',
1756 * '.' or exponents) using local variables ('hash_seen', 'x'). Again, the
1757 * global exactness information is only updated after each part has been
1758 * successfully parsed.
1759 * * Sequences of digits are parsed into temporary variables holding fixnums.
1760 * Only if these fixnums would overflow, the result variables are updated
1761 * using the standard functions scm_add, scm_product, scm_divide etc. Then,
1762 * the temporary variables holding the fixnums are cleared, and the process
1763 * starts over again. If for example fixnums were able to store five decimal
1764 * digits, a number 1234567890 would be parsed in two parts 12345 and 67890,
1765 * and the result was computed as 12345 * 100000 + 67890. In other words,
1766 * only every five digits two bignum operations were performed.
1767 */
1768
1769 enum t_exactness {NO_EXACTNESS, INEXACT, EXACT};
1770
1771 /* R5RS, section 7.1.1, lexical structure of numbers: <uinteger R>. */
1772
1773 /* In non ASCII-style encodings the following macro might not work. */
1774 #define XDIGIT2UINT(d) (isdigit (d) ? (d) - '0' : tolower (d) - 'a' + 10)
1775
1776 static SCM
1777 mem2uinteger (const char* mem, size_t len, unsigned int *p_idx,
1778 unsigned int radix, enum t_exactness *p_exactness)
1779 {
1780 unsigned int idx = *p_idx;
1781 unsigned int hash_seen = 0;
1782 scm_t_bits shift = 1;
1783 scm_t_bits add = 0;
1784 unsigned int digit_value;
1785 SCM result;
1786 char c;
1787
1788 if (idx == len)
1789 return SCM_BOOL_F;
1790
1791 c = mem[idx];
1792 if (!isxdigit (c))
1793 return SCM_BOOL_F;
1794 digit_value = XDIGIT2UINT (c);
1795 if (digit_value >= radix)
1796 return SCM_BOOL_F;
1797
1798 idx++;
1799 result = SCM_MAKINUM (digit_value);
1800 while (idx != len)
1801 {
1802 char c = mem[idx];
1803 if (isxdigit (c))
1804 {
1805 if (hash_seen)
1806 break;
1807 digit_value = XDIGIT2UINT (c);
1808 if (digit_value >= radix)
1809 break;
1810 }
1811 else if (c == '#')
1812 {
1813 hash_seen = 1;
1814 digit_value = 0;
1815 }
1816 else
1817 break;
1818
1819 idx++;
1820 if (SCM_MOST_POSITIVE_FIXNUM / radix < shift)
1821 {
1822 result = scm_product (result, SCM_MAKINUM (shift));
1823 if (add > 0)
1824 result = scm_sum (result, SCM_MAKINUM (add));
1825
1826 shift = radix;
1827 add = digit_value;
1828 }
1829 else
1830 {
1831 shift = shift * radix;
1832 add = add * radix + digit_value;
1833 }
1834 };
1835
1836 if (shift > 1)
1837 result = scm_product (result, SCM_MAKINUM (shift));
1838 if (add > 0)
1839 result = scm_sum (result, SCM_MAKINUM (add));
1840
1841 *p_idx = idx;
1842 if (hash_seen)
1843 *p_exactness = INEXACT;
1844
1845 return result;
1846 }
1847
1848
1849 /* R5RS, section 7.1.1, lexical structure of numbers: <decimal 10>. Only
1850 * covers the parts of the rules that start at a potential point. The value
1851 * of the digits up to the point have been parsed by the caller and are given
1852 * in variable result. The content of *p_exactness indicates, whether a hash
1853 * has already been seen in the digits before the point.
1854 */
1855
1856 /* In non ASCII-style encodings the following macro might not work. */
1857 #define DIGIT2UINT(d) ((d) - '0')
1858
1859 static SCM
1860 mem2decimal_from_point (SCM result, const char* mem, size_t len,
1861 unsigned int *p_idx, enum t_exactness *p_exactness)
1862 {
1863 unsigned int idx = *p_idx;
1864 enum t_exactness x = *p_exactness;
1865
1866 if (idx == len)
1867 return result;
1868
1869 if (mem[idx] == '.')
1870 {
1871 scm_t_bits shift = 1;
1872 scm_t_bits add = 0;
1873 unsigned int digit_value;
1874 SCM big_shift = SCM_MAKINUM (1);
1875
1876 idx++;
1877 while (idx != len)
1878 {
1879 char c = mem[idx];
1880 if (isdigit (c))
1881 {
1882 if (x == INEXACT)
1883 return SCM_BOOL_F;
1884 else
1885 digit_value = DIGIT2UINT (c);
1886 }
1887 else if (c == '#')
1888 {
1889 x = INEXACT;
1890 digit_value = 0;
1891 }
1892 else
1893 break;
1894
1895 idx++;
1896 if (SCM_MOST_POSITIVE_FIXNUM / 10 < shift)
1897 {
1898 big_shift = scm_product (big_shift, SCM_MAKINUM (shift));
1899 result = scm_product (result, SCM_MAKINUM (shift));
1900 if (add > 0)
1901 result = scm_sum (result, SCM_MAKINUM (add));
1902
1903 shift = 10;
1904 add = digit_value;
1905 }
1906 else
1907 {
1908 shift = shift * 10;
1909 add = add * 10 + digit_value;
1910 }
1911 };
1912
1913 if (add > 0)
1914 {
1915 big_shift = scm_product (big_shift, SCM_MAKINUM (shift));
1916 result = scm_product (result, SCM_MAKINUM (shift));
1917 result = scm_sum (result, SCM_MAKINUM (add));
1918 }
1919
1920 result = scm_divide (result, big_shift);
1921
1922 /* We've seen a decimal point, thus the value is implicitly inexact. */
1923 x = INEXACT;
1924 }
1925
1926 if (idx != len)
1927 {
1928 int sign = 1;
1929 unsigned int start;
1930 char c;
1931 int exponent;
1932 SCM e;
1933
1934 /* R5RS, section 7.1.1, lexical structure of numbers: <suffix> */
1935
1936 switch (mem[idx])
1937 {
1938 case 'd': case 'D':
1939 case 'e': case 'E':
1940 case 'f': case 'F':
1941 case 'l': case 'L':
1942 case 's': case 'S':
1943 idx++;
1944 start = idx;
1945 c = mem[idx];
1946 if (c == '-')
1947 {
1948 idx++;
1949 sign = -1;
1950 c = mem[idx];
1951 }
1952 else if (c == '+')
1953 {
1954 idx++;
1955 sign = 1;
1956 c = mem[idx];
1957 }
1958 else
1959 sign = 1;
1960
1961 if (!isdigit (c))
1962 return SCM_BOOL_F;
1963
1964 idx++;
1965 exponent = DIGIT2UINT (c);
1966 while (idx != len)
1967 {
1968 char c = mem[idx];
1969 if (isdigit (c))
1970 {
1971 idx++;
1972 if (exponent <= SCM_MAXEXP)
1973 exponent = exponent * 10 + DIGIT2UINT (c);
1974 }
1975 else
1976 break;
1977 }
1978
1979 if (exponent > SCM_MAXEXP)
1980 {
1981 size_t exp_len = idx - start;
1982 SCM exp_string = scm_mem2string (&mem[start], exp_len);
1983 SCM exp_num = scm_string_to_number (exp_string, SCM_UNDEFINED);
1984 scm_out_of_range ("string->number", exp_num);
1985 }
1986
1987 e = scm_integer_expt (SCM_MAKINUM (10), SCM_MAKINUM (exponent));
1988 if (sign == 1)
1989 result = scm_product (result, e);
1990 else
1991 result = scm_divide (result, e);
1992
1993 /* We've seen an exponent, thus the value is implicitly inexact. */
1994 x = INEXACT;
1995
1996 break;
1997
1998 default:
1999 break;
2000 }
2001 }
2002
2003 *p_idx = idx;
2004 if (x == INEXACT)
2005 *p_exactness = x;
2006
2007 return result;
2008 }
2009
2010
2011 /* R5RS, section 7.1.1, lexical structure of numbers: <ureal R> */
2012
2013 static SCM
2014 mem2ureal (const char* mem, size_t len, unsigned int *p_idx,
2015 unsigned int radix, enum t_exactness *p_exactness)
2016 {
2017 unsigned int idx = *p_idx;
2018 SCM result;
2019
2020 if (idx == len)
2021 return SCM_BOOL_F;
2022
2023 if (idx+5 <= len && !strncmp (mem+idx, "inf.0", 5))
2024 {
2025 *p_idx = idx+5;
2026 return scm_inf ();
2027 }
2028
2029 if (idx+4 < len && !strncmp (mem+idx, "nan.", 4))
2030 {
2031 enum t_exactness x = EXACT;
2032
2033 /* Cobble up the fraction. We might want to set the NaN's
2034 mantissa from it. */
2035 idx += 4;
2036 mem2uinteger (mem, len, &idx, 10, &x);
2037 *p_idx = idx;
2038 return scm_nan ();
2039 }
2040
2041 if (mem[idx] == '.')
2042 {
2043 if (radix != 10)
2044 return SCM_BOOL_F;
2045 else if (idx + 1 == len)
2046 return SCM_BOOL_F;
2047 else if (!isdigit (mem[idx + 1]))
2048 return SCM_BOOL_F;
2049 else
2050 result = mem2decimal_from_point (SCM_MAKINUM (0), mem, len,
2051 p_idx, p_exactness);
2052 }
2053 else
2054 {
2055 enum t_exactness x = EXACT;
2056 SCM uinteger;
2057
2058 uinteger = mem2uinteger (mem, len, &idx, radix, &x);
2059 if (SCM_FALSEP (uinteger))
2060 return SCM_BOOL_F;
2061
2062 if (idx == len)
2063 result = uinteger;
2064 else if (mem[idx] == '/')
2065 {
2066 SCM divisor;
2067
2068 idx++;
2069
2070 divisor = mem2uinteger (mem, len, &idx, radix, &x);
2071 if (SCM_FALSEP (divisor))
2072 return SCM_BOOL_F;
2073
2074 result = scm_divide (uinteger, divisor);
2075 }
2076 else if (radix == 10)
2077 {
2078 result = mem2decimal_from_point (uinteger, mem, len, &idx, &x);
2079 if (SCM_FALSEP (result))
2080 return SCM_BOOL_F;
2081 }
2082 else
2083 result = uinteger;
2084
2085 *p_idx = idx;
2086 if (x == INEXACT)
2087 *p_exactness = x;
2088 }
2089
2090 /* When returning an inexact zero, make sure it is represented as a
2091 floating point value so that we can change its sign.
2092 */
2093 if (SCM_EQ_P (result, SCM_MAKINUM(0)) && *p_exactness == INEXACT)
2094 result = scm_make_real (0.0);
2095
2096 return result;
2097 }
2098
2099
2100 /* R5RS, section 7.1.1, lexical structure of numbers: <complex R> */
2101
2102 static SCM
2103 mem2complex (const char* mem, size_t len, unsigned int idx,
2104 unsigned int radix, enum t_exactness *p_exactness)
2105 {
2106 char c;
2107 int sign = 0;
2108 SCM ureal;
2109
2110 if (idx == len)
2111 return SCM_BOOL_F;
2112
2113 c = mem[idx];
2114 if (c == '+')
2115 {
2116 idx++;
2117 sign = 1;
2118 }
2119 else if (c == '-')
2120 {
2121 idx++;
2122 sign = -1;
2123 }
2124
2125 if (idx == len)
2126 return SCM_BOOL_F;
2127
2128 ureal = mem2ureal (mem, len, &idx, radix, p_exactness);
2129 if (SCM_FALSEP (ureal))
2130 {
2131 /* input must be either +i or -i */
2132
2133 if (sign == 0)
2134 return SCM_BOOL_F;
2135
2136 if (mem[idx] == 'i' || mem[idx] == 'I')
2137 {
2138 idx++;
2139 if (idx != len)
2140 return SCM_BOOL_F;
2141
2142 return scm_make_rectangular (SCM_MAKINUM (0), SCM_MAKINUM (sign));
2143 }
2144 else
2145 return SCM_BOOL_F;
2146 }
2147 else
2148 {
2149 if (sign == -1 && SCM_FALSEP (scm_nan_p (ureal)))
2150 ureal = scm_difference (ureal, SCM_UNDEFINED);
2151
2152 if (idx == len)
2153 return ureal;
2154
2155 c = mem[idx];
2156 switch (c)
2157 {
2158 case 'i': case 'I':
2159 /* either +<ureal>i or -<ureal>i */
2160
2161 idx++;
2162 if (sign == 0)
2163 return SCM_BOOL_F;
2164 if (idx != len)
2165 return SCM_BOOL_F;
2166 return scm_make_rectangular (SCM_MAKINUM (0), ureal);
2167
2168 case '@':
2169 /* polar input: <real>@<real>. */
2170
2171 idx++;
2172 if (idx == len)
2173 return SCM_BOOL_F;
2174 else
2175 {
2176 int sign;
2177 SCM angle;
2178 SCM result;
2179
2180 c = mem[idx];
2181 if (c == '+')
2182 {
2183 idx++;
2184 sign = 1;
2185 }
2186 else if (c == '-')
2187 {
2188 idx++;
2189 sign = -1;
2190 }
2191 else
2192 sign = 1;
2193
2194 angle = mem2ureal (mem, len, &idx, radix, p_exactness);
2195 if (SCM_FALSEP (angle))
2196 return SCM_BOOL_F;
2197 if (idx != len)
2198 return SCM_BOOL_F;
2199
2200 if (sign == -1 && SCM_FALSEP (scm_nan_p (ureal)))
2201 angle = scm_difference (angle, SCM_UNDEFINED);
2202
2203 result = scm_make_polar (ureal, angle);
2204 return result;
2205 }
2206 case '+':
2207 case '-':
2208 /* expecting input matching <real>[+-]<ureal>?i */
2209
2210 idx++;
2211 if (idx == len)
2212 return SCM_BOOL_F;
2213 else
2214 {
2215 int sign = (c == '+') ? 1 : -1;
2216 SCM imag = mem2ureal (mem, len, &idx, radix, p_exactness);
2217
2218 if (SCM_FALSEP (imag))
2219 imag = SCM_MAKINUM (sign);
2220 else if (sign == -1 && SCM_FALSEP (scm_nan_p (ureal)))
2221 imag = scm_difference (imag, SCM_UNDEFINED);
2222
2223 if (idx == len)
2224 return SCM_BOOL_F;
2225 if (mem[idx] != 'i' && mem[idx] != 'I')
2226 return SCM_BOOL_F;
2227
2228 idx++;
2229 if (idx != len)
2230 return SCM_BOOL_F;
2231
2232 return scm_make_rectangular (ureal, imag);
2233 }
2234 default:
2235 return SCM_BOOL_F;
2236 }
2237 }
2238 }
2239
2240
2241 /* R5RS, section 7.1.1, lexical structure of numbers: <number> */
2242
2243 enum t_radix {NO_RADIX=0, DUAL=2, OCT=8, DEC=10, HEX=16};
2244
2245 SCM
2246 scm_i_mem2number (const char* mem, size_t len, unsigned int default_radix)
2247 {
2248 unsigned int idx = 0;
2249 unsigned int radix = NO_RADIX;
2250 enum t_exactness forced_x = NO_EXACTNESS;
2251 enum t_exactness implicit_x = EXACT;
2252 SCM result;
2253
2254 /* R5RS, section 7.1.1, lexical structure of numbers: <prefix R> */
2255 while (idx + 2 < len && mem[idx] == '#')
2256 {
2257 switch (mem[idx + 1])
2258 {
2259 case 'b': case 'B':
2260 if (radix != NO_RADIX)
2261 return SCM_BOOL_F;
2262 radix = DUAL;
2263 break;
2264 case 'd': case 'D':
2265 if (radix != NO_RADIX)
2266 return SCM_BOOL_F;
2267 radix = DEC;
2268 break;
2269 case 'i': case 'I':
2270 if (forced_x != NO_EXACTNESS)
2271 return SCM_BOOL_F;
2272 forced_x = INEXACT;
2273 break;
2274 case 'e': case 'E':
2275 if (forced_x != NO_EXACTNESS)
2276 return SCM_BOOL_F;
2277 forced_x = EXACT;
2278 break;
2279 case 'o': case 'O':
2280 if (radix != NO_RADIX)
2281 return SCM_BOOL_F;
2282 radix = OCT;
2283 break;
2284 case 'x': case 'X':
2285 if (radix != NO_RADIX)
2286 return SCM_BOOL_F;
2287 radix = HEX;
2288 break;
2289 default:
2290 return SCM_BOOL_F;
2291 }
2292 idx += 2;
2293 }
2294
2295 /* R5RS, section 7.1.1, lexical structure of numbers: <complex R> */
2296 if (radix == NO_RADIX)
2297 result = mem2complex (mem, len, idx, default_radix, &implicit_x);
2298 else
2299 result = mem2complex (mem, len, idx, (unsigned int) radix, &implicit_x);
2300
2301 if (SCM_FALSEP (result))
2302 return SCM_BOOL_F;
2303
2304 switch (forced_x)
2305 {
2306 case EXACT:
2307 if (SCM_INEXACTP (result))
2308 /* FIXME: This may change the value. */
2309 return scm_inexact_to_exact (result);
2310 else
2311 return result;
2312 case INEXACT:
2313 if (SCM_INEXACTP (result))
2314 return result;
2315 else
2316 return scm_exact_to_inexact (result);
2317 case NO_EXACTNESS:
2318 default:
2319 if (implicit_x == INEXACT)
2320 {
2321 if (SCM_INEXACTP (result))
2322 return result;
2323 else
2324 return scm_exact_to_inexact (result);
2325 }
2326 else
2327 return result;
2328 }
2329 }
2330
2331
2332 SCM_DEFINE (scm_string_to_number, "string->number", 1, 1, 0,
2333 (SCM string, SCM radix),
2334 "Return a number of the maximally precise representation\n"
2335 "expressed by the given @var{string}. @var{radix} must be an\n"
2336 "exact integer, either 2, 8, 10, or 16. If supplied, @var{radix}\n"
2337 "is a default radix that may be overridden by an explicit radix\n"
2338 "prefix in @var{string} (e.g. \"#o177\"). If @var{radix} is not\n"
2339 "supplied, then the default radix is 10. If string is not a\n"
2340 "syntactically valid notation for a number, then\n"
2341 "@code{string->number} returns @code{#f}.")
2342 #define FUNC_NAME s_scm_string_to_number
2343 {
2344 SCM answer;
2345 int base;
2346 SCM_VALIDATE_STRING (1, string);
2347 SCM_VALIDATE_INUM_MIN_DEF_COPY (2, radix,2,10, base);
2348 answer = scm_i_mem2number (SCM_STRING_CHARS (string),
2349 SCM_STRING_LENGTH (string),
2350 base);
2351 return scm_return_first (answer, string);
2352 }
2353 #undef FUNC_NAME
2354
2355
2356 /*** END strs->nums ***/
2357
2358
2359 SCM
2360 scm_make_real (double x)
2361 {
2362 SCM z = scm_double_cell (scm_tc16_real, 0, 0, 0);
2363
2364 SCM_REAL_VALUE (z) = x;
2365 return z;
2366 }
2367
2368
2369 SCM
2370 scm_make_complex (double x, double y)
2371 {
2372 if (y == 0.0) {
2373 return scm_make_real (x);
2374 } else {
2375 SCM z;
2376 SCM_NEWSMOB (z, scm_tc16_complex, scm_gc_malloc (2*sizeof (double),
2377 "complex"));
2378 SCM_COMPLEX_REAL (z) = x;
2379 SCM_COMPLEX_IMAG (z) = y;
2380 return z;
2381 }
2382 }
2383
2384
2385 SCM
2386 scm_bigequal (SCM x, SCM y)
2387 {
2388 int result = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (x));
2389 scm_remember_upto_here_2 (x, y);
2390 return SCM_BOOL (0 == result);
2391 }
2392
2393 SCM
2394 scm_real_equalp (SCM x, SCM y)
2395 {
2396 return SCM_BOOL (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
2397 }
2398
2399 SCM
2400 scm_complex_equalp (SCM x, SCM y)
2401 {
2402 return SCM_BOOL (SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y)
2403 && SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y));
2404 }
2405
2406
2407
2408 SCM_REGISTER_PROC (s_number_p, "number?", 1, 0, 0, scm_number_p);
2409 /* "Return @code{#t} if @var{x} is a number, @code{#f}\n"
2410 * "else. Note that the sets of complex, real, rational and\n"
2411 * "integer values form subsets of the set of numbers, i. e. the\n"
2412 * "predicate will be fulfilled for any number."
2413 */
2414 SCM_DEFINE (scm_number_p, "complex?", 1, 0, 0,
2415 (SCM x),
2416 "Return @code{#t} if @var{x} is a complex number, @code{#f}\n"
2417 "otherwise. Note that the sets of real, rational and integer\n"
2418 "values form subsets of the set of complex numbers, i. e. the\n"
2419 "predicate will also be fulfilled if @var{x} is a real,\n"
2420 "rational or integer number.")
2421 #define FUNC_NAME s_scm_number_p
2422 {
2423 return SCM_BOOL (SCM_NUMBERP (x));
2424 }
2425 #undef FUNC_NAME
2426
2427
2428 SCM_REGISTER_PROC (s_real_p, "real?", 1, 0, 0, scm_real_p);
2429 /* "Return @code{#t} if @var{x} is a real number, @code{#f} else.\n"
2430 * "Note that the sets of integer and rational values form a subset\n"
2431 * "of the set of real numbers, i. e. the predicate will also\n"
2432 * "be fulfilled if @var{x} is an integer or a rational number."
2433 */
2434 SCM_DEFINE (scm_real_p, "rational?", 1, 0, 0,
2435 (SCM x),
2436 "Return @code{#t} if @var{x} is a rational number, @code{#f}\n"
2437 "otherwise. Note that the set of integer values forms a subset of\n"
2438 "the set of rational numbers, i. e. the predicate will also be\n"
2439 "fulfilled if @var{x} is an integer number. Real numbers\n"
2440 "will also satisfy this predicate, because of their limited\n"
2441 "precision.")
2442 #define FUNC_NAME s_scm_real_p
2443 {
2444 if (SCM_INUMP (x)) {
2445 return SCM_BOOL_T;
2446 } else if (SCM_IMP (x)) {
2447 return SCM_BOOL_F;
2448 } else if (SCM_REALP (x)) {
2449 return SCM_BOOL_T;
2450 } else if (SCM_BIGP (x)) {
2451 return SCM_BOOL_T;
2452 } else {
2453 return SCM_BOOL_F;
2454 }
2455 }
2456 #undef FUNC_NAME
2457
2458
2459 SCM_DEFINE (scm_integer_p, "integer?", 1, 0, 0,
2460 (SCM x),
2461 "Return @code{#t} if @var{x} is an integer number, @code{#f}\n"
2462 "else.")
2463 #define FUNC_NAME s_scm_integer_p
2464 {
2465 double r;
2466 if (SCM_INUMP (x))
2467 return SCM_BOOL_T;
2468 if (SCM_IMP (x))
2469 return SCM_BOOL_F;
2470 if (SCM_BIGP (x))
2471 return SCM_BOOL_T;
2472 if (!SCM_INEXACTP (x))
2473 return SCM_BOOL_F;
2474 if (SCM_COMPLEXP (x))
2475 return SCM_BOOL_F;
2476 r = SCM_REAL_VALUE (x);
2477 if (r == floor (r))
2478 return SCM_BOOL_T;
2479 return SCM_BOOL_F;
2480 }
2481 #undef FUNC_NAME
2482
2483
2484 SCM_DEFINE (scm_inexact_p, "inexact?", 1, 0, 0,
2485 (SCM x),
2486 "Return @code{#t} if @var{x} is an inexact number, @code{#f}\n"
2487 "else.")
2488 #define FUNC_NAME s_scm_inexact_p
2489 {
2490 return SCM_BOOL (SCM_INEXACTP (x));
2491 }
2492 #undef FUNC_NAME
2493
2494
2495 SCM_GPROC1 (s_eq_p, "=", scm_tc7_rpsubr, scm_num_eq_p, g_eq_p);
2496 /* "Return @code{#t} if all parameters are numerically equal." */
2497 SCM
2498 scm_num_eq_p (SCM x, SCM y)
2499 {
2500 if (SCM_INUMP (x)) {
2501 long xx = SCM_INUM (x);
2502 if (SCM_INUMP (y)) {
2503 long yy = SCM_INUM (y);
2504 return SCM_BOOL (xx == yy);
2505 } else if (SCM_BIGP (y)) {
2506 return SCM_BOOL_F;
2507 } else if (SCM_REALP (y)) {
2508 return SCM_BOOL ((double) xx == SCM_REAL_VALUE (y));
2509 } else if (SCM_COMPLEXP (y)) {
2510 return SCM_BOOL (((double) xx == SCM_COMPLEX_REAL (y))
2511 && (0.0 == SCM_COMPLEX_IMAG (y)));
2512 } else {
2513 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
2514 }
2515 } else if (SCM_BIGP (x)) {
2516 if (SCM_INUMP (y)) {
2517 return SCM_BOOL_F;
2518 } else if (SCM_BIGP (y)) {
2519 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2520 scm_remember_upto_here_2 (x, y);
2521 return SCM_BOOL (0 == cmp);
2522 } else if (SCM_REALP (y)) {
2523 int cmp;
2524 if (xisnan (SCM_REAL_VALUE (y))) return SCM_BOOL_F;
2525 cmp = mpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
2526 scm_remember_upto_here_1 (x);
2527 return SCM_BOOL (0 == cmp);
2528 } else if (SCM_COMPLEXP (y)) {
2529 int cmp;
2530 if (0.0 != SCM_COMPLEX_IMAG (y)) return SCM_BOOL_F;
2531 if (xisnan (SCM_COMPLEX_REAL (y))) return SCM_BOOL_F;
2532 cmp = mpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_COMPLEX_REAL (y));
2533 scm_remember_upto_here_1 (x);
2534 return SCM_BOOL (0 == cmp);
2535 } else {
2536 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
2537 }
2538 } else if (SCM_REALP (x)) {
2539 if (SCM_INUMP (y)) {
2540 return SCM_BOOL (SCM_REAL_VALUE (x) == (double) SCM_INUM (y));
2541 } else if (SCM_BIGP (y)) {
2542 int cmp;
2543 if (xisnan (SCM_REAL_VALUE (x))) return SCM_BOOL_F;
2544 cmp = mpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
2545 scm_remember_upto_here_1 (y);
2546 return SCM_BOOL (0 == cmp);
2547 } else if (SCM_REALP (y)) {
2548 return SCM_BOOL (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
2549 } else if (SCM_COMPLEXP (y)) {
2550 return SCM_BOOL ((SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y))
2551 && (0.0 == SCM_COMPLEX_IMAG (y)));
2552 } else {
2553 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
2554 }
2555 } else if (SCM_COMPLEXP (x)) {
2556 if (SCM_INUMP (y)) {
2557 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == (double) SCM_INUM (y))
2558 && (SCM_COMPLEX_IMAG (x) == 0.0));
2559 } else if (SCM_BIGP (y)) {
2560 int cmp;
2561 if (0.0 != SCM_COMPLEX_IMAG (x)) return SCM_BOOL_F;
2562 if (xisnan (SCM_COMPLEX_REAL (x))) return SCM_BOOL_F;
2563 cmp = mpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_COMPLEX_REAL (x));
2564 scm_remember_upto_here_1 (y);
2565 return SCM_BOOL (0 == cmp);
2566 } else if (SCM_REALP (y)) {
2567 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y))
2568 && (SCM_COMPLEX_IMAG (x) == 0.0));
2569 } else if (SCM_COMPLEXP (y)) {
2570 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y))
2571 && (SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y)));
2572 } else {
2573 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
2574 }
2575 } else {
2576 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARG1, s_eq_p);
2577 }
2578 }
2579
2580
2581 SCM_GPROC1 (s_less_p, "<", scm_tc7_rpsubr, scm_less_p, g_less_p);
2582 /* "Return @code{#t} if the list of parameters is monotonically\n"
2583 * "increasing."
2584 */
2585 SCM
2586 scm_less_p (SCM x, SCM y)
2587 {
2588 if (SCM_INUMP (x)) {
2589 long xx = SCM_INUM (x);
2590 if (SCM_INUMP (y)) {
2591 long yy = SCM_INUM (y);
2592 return SCM_BOOL (xx < yy);
2593 } else if (SCM_BIGP (y)) {
2594 int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
2595 scm_remember_upto_here_1 (y);
2596 return SCM_BOOL (sgn > 0);
2597 } else if (SCM_REALP (y)) {
2598 return SCM_BOOL ((double) xx < SCM_REAL_VALUE (y));
2599 } else {
2600 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
2601 }
2602 } else if (SCM_BIGP (x)) {
2603 if (SCM_INUMP (y)) {
2604 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
2605 scm_remember_upto_here_1 (x);
2606 return SCM_BOOL (sgn < 0);
2607 } else if (SCM_BIGP (y)) {
2608 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2609 scm_remember_upto_here_2 (x, y);
2610 return SCM_BOOL (cmp < 0);
2611 } else if (SCM_REALP (y)) {
2612 int cmp;
2613 if (xisnan (SCM_REAL_VALUE (y))) return SCM_BOOL_F;
2614 cmp = mpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
2615 scm_remember_upto_here_1 (x);
2616 return SCM_BOOL (cmp < 0);
2617 } else {
2618 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
2619 }
2620 } else if (SCM_REALP (x)) {
2621 if (SCM_INUMP (y)) {
2622 return SCM_BOOL (SCM_REAL_VALUE (x) < (double) SCM_INUM (y));
2623 } else if (SCM_BIGP (y)) {
2624 int cmp;
2625 if (xisnan (SCM_REAL_VALUE (x))) return SCM_BOOL_F;
2626 cmp = mpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
2627 scm_remember_upto_here_1 (y);
2628 return SCM_BOOL (cmp > 0);
2629 } else if (SCM_REALP (y)) {
2630 return SCM_BOOL (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y));
2631 } else {
2632 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
2633 }
2634 } else {
2635 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARG1, s_less_p);
2636 }
2637 }
2638
2639
2640 SCM_GPROC1 (s_scm_gr_p, ">", scm_tc7_rpsubr, scm_gr_p, g_gr_p);
2641 /* "Return @code{#t} if the list of parameters is monotonically\n"
2642 * "decreasing."
2643 */
2644 #define FUNC_NAME s_scm_gr_p
2645 SCM
2646 scm_gr_p (SCM x, SCM y)
2647 {
2648 if (!SCM_NUMBERP (x))
2649 SCM_WTA_DISPATCH_2 (g_gr_p, x, y, SCM_ARG1, FUNC_NAME);
2650 else if (!SCM_NUMBERP (y))
2651 SCM_WTA_DISPATCH_2 (g_gr_p, x, y, SCM_ARG2, FUNC_NAME);
2652 else
2653 return scm_less_p (y, x);
2654 }
2655 #undef FUNC_NAME
2656
2657
2658 SCM_GPROC1 (s_scm_leq_p, "<=", scm_tc7_rpsubr, scm_leq_p, g_leq_p);
2659 /* "Return @code{#t} if the list of parameters is monotonically\n"
2660 * "non-decreasing."
2661 */
2662 #define FUNC_NAME s_scm_leq_p
2663 SCM
2664 scm_leq_p (SCM x, SCM y)
2665 {
2666 if (!SCM_NUMBERP (x))
2667 SCM_WTA_DISPATCH_2 (g_leq_p, x, y, SCM_ARG1, FUNC_NAME);
2668 else if (!SCM_NUMBERP (y))
2669 SCM_WTA_DISPATCH_2 (g_leq_p, x, y, SCM_ARG2, FUNC_NAME);
2670 else if (SCM_NFALSEP (scm_nan_p (x)) || SCM_NFALSEP (scm_nan_p (y)))
2671 return SCM_BOOL_F;
2672 else
2673 return SCM_BOOL_NOT (scm_less_p (y, x));
2674 }
2675 #undef FUNC_NAME
2676
2677
2678 SCM_GPROC1 (s_scm_geq_p, ">=", scm_tc7_rpsubr, scm_geq_p, g_geq_p);
2679 /* "Return @code{#t} if the list of parameters is monotonically\n"
2680 * "non-increasing."
2681 */
2682 #define FUNC_NAME s_scm_geq_p
2683 SCM
2684 scm_geq_p (SCM x, SCM y)
2685 {
2686 if (!SCM_NUMBERP (x))
2687 SCM_WTA_DISPATCH_2 (g_geq_p, x, y, SCM_ARG1, FUNC_NAME);
2688 else if (!SCM_NUMBERP (y))
2689 SCM_WTA_DISPATCH_2 (g_geq_p, x, y, SCM_ARG2, FUNC_NAME);
2690 else if (SCM_NFALSEP (scm_nan_p (x)) || SCM_NFALSEP (scm_nan_p (y)))
2691 return SCM_BOOL_F;
2692 else
2693 return SCM_BOOL_NOT (scm_less_p (x, y));
2694 }
2695 #undef FUNC_NAME
2696
2697
2698 SCM_GPROC (s_zero_p, "zero?", 1, 0, 0, scm_zero_p, g_zero_p);
2699 /* "Return @code{#t} if @var{z} is an exact or inexact number equal to\n"
2700 * "zero."
2701 */
2702 SCM
2703 scm_zero_p (SCM z)
2704 {
2705 if (SCM_INUMP (z)) {
2706 return SCM_BOOL (SCM_EQ_P (z, SCM_INUM0));
2707 } else if (SCM_BIGP (z)) {
2708 return SCM_BOOL_F;
2709 } else if (SCM_REALP (z)) {
2710 return SCM_BOOL (SCM_REAL_VALUE (z) == 0.0);
2711 } else if (SCM_COMPLEXP (z)) {
2712 return SCM_BOOL (SCM_COMPLEX_REAL (z) == 0.0
2713 && SCM_COMPLEX_IMAG (z) == 0.0);
2714 } else {
2715 SCM_WTA_DISPATCH_1 (g_zero_p, z, SCM_ARG1, s_zero_p);
2716 }
2717 }
2718
2719
2720 SCM_GPROC (s_positive_p, "positive?", 1, 0, 0, scm_positive_p, g_positive_p);
2721 /* "Return @code{#t} if @var{x} is an exact or inexact number greater than\n"
2722 * "zero."
2723 */
2724 SCM
2725 scm_positive_p (SCM x)
2726 {
2727 if (SCM_INUMP (x)) {
2728 return SCM_BOOL (SCM_INUM (x) > 0);
2729 } else if (SCM_BIGP (x)) {
2730 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
2731 scm_remember_upto_here_1 (x);
2732 return SCM_BOOL (sgn > 0);
2733 } else if (SCM_REALP (x)) {
2734 return SCM_BOOL(SCM_REAL_VALUE (x) > 0.0);
2735 } else {
2736 SCM_WTA_DISPATCH_1 (g_positive_p, x, SCM_ARG1, s_positive_p);
2737 }
2738 }
2739
2740
2741 SCM_GPROC (s_negative_p, "negative?", 1, 0, 0, scm_negative_p, g_negative_p);
2742 /* "Return @code{#t} if @var{x} is an exact or inexact number less than\n"
2743 * "zero."
2744 */
2745 SCM
2746 scm_negative_p (SCM x)
2747 {
2748 if (SCM_INUMP (x)) {
2749 return SCM_BOOL (SCM_INUM (x) < 0);
2750 } else if (SCM_BIGP (x)) {
2751 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
2752 scm_remember_upto_here_1 (x);
2753 return SCM_BOOL (sgn < 0);
2754 } else if (SCM_REALP (x)) {
2755 return SCM_BOOL(SCM_REAL_VALUE (x) < 0.0);
2756 } else {
2757 SCM_WTA_DISPATCH_1 (g_negative_p, x, SCM_ARG1, s_negative_p);
2758 }
2759 }
2760
2761
2762 SCM_GPROC1 (s_max, "max", scm_tc7_asubr, scm_max, g_max);
2763 /* "Return the maximum of all parameter values."
2764 */
2765 SCM
2766 scm_max (SCM x, SCM y)
2767 {
2768 if (SCM_UNBNDP (y)) {
2769 if (SCM_UNBNDP (x)) {
2770 SCM_WTA_DISPATCH_0 (g_max, s_max);
2771 } else if (SCM_NUMBERP (x)) {
2772 return x;
2773 } else {
2774 SCM_WTA_DISPATCH_1 (g_max, x, SCM_ARG1, s_max);
2775 }
2776 }
2777
2778 if (SCM_INUMP (x)) {
2779 long xx = SCM_INUM (x);
2780 if (SCM_INUMP (y)) {
2781 long yy = SCM_INUM (y);
2782 return (xx < yy) ? y : x;
2783 } else if (SCM_BIGP (y)) {
2784 int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
2785 scm_remember_upto_here_1 (y);
2786 return (sgn < 0) ? x : y;
2787 } else if (SCM_REALP (y)) {
2788 double z = xx;
2789 return (z <= SCM_REAL_VALUE (y)) ? y : scm_make_real (z);
2790 } else {
2791 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
2792 }
2793 } else if (SCM_BIGP (x)) {
2794 if (SCM_INUMP (y)) {
2795 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
2796 scm_remember_upto_here_1 (x);
2797 return (sgn < 0) ? y : x;
2798 } else if (SCM_BIGP (y)) {
2799 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2800 scm_remember_upto_here_2 (x, y);
2801 return (cmp > 0) ? x : y;
2802 } else if (SCM_REALP (y)) {
2803 int cmp = mpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
2804 scm_remember_upto_here_1 (x);
2805 return (cmp > 0) ? x : y;
2806 } else {
2807 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
2808 }
2809 } else if (SCM_REALP (x)) {
2810 if (SCM_INUMP (y)) {
2811 double z = SCM_INUM (y);
2812 return (SCM_REAL_VALUE (x) < z) ? scm_make_real (z) : x;
2813 } else if (SCM_BIGP (y)) {
2814 int cmp = mpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
2815 scm_remember_upto_here_1 (y);
2816 return (cmp < 0) ? x : y;
2817 } else if (SCM_REALP (y)) {
2818 return (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y)) ? y : x;
2819 } else {
2820 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
2821 }
2822 } else {
2823 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARG1, s_max);
2824 }
2825 }
2826
2827
2828 SCM_GPROC1 (s_min, "min", scm_tc7_asubr, scm_min, g_min);
2829 /* "Return the minium of all parameter values."
2830 */
2831 SCM
2832 scm_min (SCM x, SCM y)
2833 {
2834 if (SCM_UNBNDP (y)) {
2835 if (SCM_UNBNDP (x)) {
2836 SCM_WTA_DISPATCH_0 (g_min, s_min);
2837 } else if (SCM_NUMBERP (x)) {
2838 return x;
2839 } else {
2840 SCM_WTA_DISPATCH_1 (g_min, x, SCM_ARG1, s_min);
2841 }
2842 }
2843
2844 if (SCM_INUMP (x)) {
2845 long xx = SCM_INUM (x);
2846 if (SCM_INUMP (y)) {
2847 long yy = SCM_INUM (y);
2848 return (xx < yy) ? x : y;
2849 } else if (SCM_BIGP (y)) {
2850 int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
2851 scm_remember_upto_here_1 (y);
2852 return (sgn < 0) ? y : x;
2853 } else if (SCM_REALP (y)) {
2854 double z = xx;
2855 return (z < SCM_REAL_VALUE (y)) ? scm_make_real (z) : y;
2856 } else {
2857 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
2858 }
2859 } else if (SCM_BIGP (x)) {
2860 if (SCM_INUMP (y)) {
2861 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
2862 scm_remember_upto_here_1 (x);
2863 return (sgn < 0) ? x : y;
2864 } else if (SCM_BIGP (y)) {
2865 int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2866 scm_remember_upto_here_2 (x, y);
2867 return (cmp > 0) ? y : x;
2868 } else if (SCM_REALP (y)) {
2869 int cmp = mpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
2870 scm_remember_upto_here_1 (x);
2871 return (cmp > 0) ? y : x;
2872 } else {
2873 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
2874 }
2875 } else if (SCM_REALP (x)) {
2876 if (SCM_INUMP (y)) {
2877 double z = SCM_INUM (y);
2878 return (SCM_REAL_VALUE (x) <= z) ? x : scm_make_real (z);
2879 } else if (SCM_BIGP (y)) {
2880 int cmp = mpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
2881 scm_remember_upto_here_1 (y);
2882 return (cmp < 0) ? y : x;
2883 } else if (SCM_REALP (y)) {
2884 return (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y)) ? x : y;
2885 } else {
2886 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
2887 }
2888 } else {
2889 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARG1, s_min);
2890 }
2891 }
2892
2893
2894 SCM_GPROC1 (s_sum, "+", scm_tc7_asubr, scm_sum, g_sum);
2895 /* "Return the sum of all parameter values. Return 0 if called without\n"
2896 * "any parameters."
2897 */
2898 SCM
2899 scm_sum (SCM x, SCM y)
2900 {
2901 if (SCM_UNBNDP (y))
2902 {
2903 if (SCM_NUMBERP (x)) return x;
2904 if (SCM_UNBNDP (x)) return SCM_INUM0;
2905 SCM_WTA_DISPATCH_1 (g_sum, x, SCM_ARG1, s_sum);
2906 }
2907
2908 if (SCM_INUMP (x))
2909 {
2910 if (SCM_INUMP (y))
2911 {
2912 long xx = SCM_INUM (x);
2913 long yy = SCM_INUM (y);
2914 long int z = xx + yy;
2915 return SCM_FIXABLE (z) ? SCM_MAKINUM (z) : scm_i_long2big (z);
2916 }
2917 else if (SCM_BIGP (y))
2918 {
2919 SCM_SWAP (x, y);
2920 goto add_big_inum;
2921 }
2922 else if (SCM_REALP (y))
2923 {
2924 long int xx = SCM_INUM (x);
2925 return scm_make_real (xx + SCM_REAL_VALUE (y));
2926 }
2927 else if (SCM_COMPLEXP (y))
2928 {
2929 long int xx = SCM_INUM (x);
2930 return scm_make_complex (xx + SCM_COMPLEX_REAL (y),
2931 SCM_COMPLEX_IMAG (y));
2932 }
2933 else
2934 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
2935 } else if (SCM_BIGP (x)) {
2936 if (SCM_INUMP (y)) {
2937 long int inum;
2938 int bigsgn;
2939 add_big_inum:
2940 inum = SCM_INUM (y);
2941 if (inum == 0) return x;
2942 bigsgn = mpz_sgn (SCM_I_BIG_MPZ (x));
2943 if (inum < 0) {
2944 SCM result = scm_i_mkbig ();
2945 mpz_sub_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), - inum);
2946 scm_remember_upto_here_1 (x);
2947 /* we know the result will have to be a bignum */
2948 if (bigsgn == -1) return result;
2949 return scm_i_normbig (result);
2950 } else {
2951 SCM result = scm_i_mkbig ();
2952 mpz_add_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), inum);
2953 scm_remember_upto_here_1 (x);
2954 /* we know the result will have to be a bignum */
2955 if (bigsgn == 1) return result;
2956 return result;
2957 return scm_i_normbig (result);
2958 }
2959 }
2960 else if (SCM_BIGP (y)) {
2961 SCM result = scm_i_mkbig ();
2962 int sgn_x = mpz_sgn (SCM_I_BIG_MPZ (x));
2963 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
2964 mpz_add (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
2965 scm_remember_upto_here_2 (x, y);
2966 /* we know the result will have to be a bignum */
2967 if (sgn_x == sgn_y) return result;
2968 return scm_i_normbig (result);
2969 }
2970 else if (SCM_REALP (y)) {
2971 double result = mpz_get_d (SCM_I_BIG_MPZ (x)) + SCM_REAL_VALUE (y);
2972 scm_remember_upto_here_1 (x);
2973 return scm_make_real (result);
2974 }
2975 else if (SCM_COMPLEXP (y)) {
2976 double real_part = mpz_get_d (SCM_I_BIG_MPZ (x)) + SCM_COMPLEX_REAL (y);
2977 scm_remember_upto_here_1 (x);
2978 return scm_make_complex (real_part, SCM_COMPLEX_IMAG (y));
2979 }
2980 else SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
2981 } else if (SCM_REALP (x)) {
2982 if (SCM_INUMP (y)) {
2983 return scm_make_real (SCM_REAL_VALUE (x) + SCM_INUM (y));
2984 } else if (SCM_BIGP (y)) {
2985 double result = mpz_get_d (SCM_I_BIG_MPZ (y)) + SCM_REAL_VALUE (x);
2986 scm_remember_upto_here_1 (y);
2987 return scm_make_real (result);
2988 } else if (SCM_REALP (y)) {
2989 return scm_make_real (SCM_REAL_VALUE (x) + SCM_REAL_VALUE (y));
2990 } else if (SCM_COMPLEXP (y)) {
2991 return scm_make_complex (SCM_REAL_VALUE (x) + SCM_COMPLEX_REAL (y),
2992 SCM_COMPLEX_IMAG (y));
2993 } else {
2994 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
2995 }
2996 } else if (SCM_COMPLEXP (x)) {
2997 if (SCM_INUMP (y)) {
2998 return scm_make_complex (SCM_COMPLEX_REAL (x) + SCM_INUM (y),
2999 SCM_COMPLEX_IMAG (x));
3000 } else if (SCM_BIGP (y)) {
3001 double real_part = mpz_get_d (SCM_I_BIG_MPZ (y)) + SCM_COMPLEX_REAL (x);
3002 scm_remember_upto_here_1 (y);
3003 return scm_make_complex (real_part, SCM_COMPLEX_IMAG (x));
3004 } else if (SCM_REALP (y)) {
3005 return scm_make_complex (SCM_COMPLEX_REAL (x) + SCM_REAL_VALUE (y),
3006 SCM_COMPLEX_IMAG (x));
3007 } else if (SCM_COMPLEXP (y)) {
3008 return scm_make_complex (SCM_COMPLEX_REAL (x) + SCM_COMPLEX_REAL (y),
3009 SCM_COMPLEX_IMAG (x) + SCM_COMPLEX_IMAG (y));
3010 } else {
3011 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3012 }
3013 } else {
3014 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARG1, s_sum);
3015 }
3016 }
3017
3018
3019 SCM_GPROC1 (s_difference, "-", scm_tc7_asubr, scm_difference, g_difference);
3020 /* If called with one argument @var{z1}, -@var{z1} returned. Otherwise
3021 * the sum of all but the first argument are subtracted from the first
3022 * argument. */
3023 #define FUNC_NAME s_difference
3024 SCM
3025 scm_difference (SCM x, SCM y)
3026 {
3027 if (SCM_UNBNDP (y))
3028 {
3029 if (SCM_UNBNDP (x))
3030 SCM_WTA_DISPATCH_0 (g_difference, s_difference);
3031 else
3032 if (SCM_INUMP (x))
3033 {
3034 long xx = -SCM_INUM (x);
3035 if (SCM_FIXABLE (xx))
3036 return SCM_MAKINUM (xx);
3037 else
3038 return scm_i_long2big (xx);
3039 }
3040 else if (SCM_BIGP (x))
3041 /* FIXME: do we really need to normalize here? */
3042 return scm_i_normbig (scm_i_clonebig (x, 0));
3043 else if (SCM_REALP (x))
3044 return scm_make_real (-SCM_REAL_VALUE (x));
3045 else if (SCM_COMPLEXP (x))
3046 return scm_make_complex (-SCM_COMPLEX_REAL (x),
3047 -SCM_COMPLEX_IMAG (x));
3048 else
3049 SCM_WTA_DISPATCH_1 (g_difference, x, SCM_ARG1, s_difference);
3050 }
3051
3052 if (SCM_INUMP (x)) {
3053 if (SCM_INUMP (y)) {
3054 long int xx = SCM_INUM (x);
3055 long int yy = SCM_INUM (y);
3056 long int z = xx - yy;
3057 if (SCM_FIXABLE (z)) {
3058 return SCM_MAKINUM (z);
3059 } else {
3060 return scm_i_long2big (z);
3061 }
3062 } else if (SCM_BIGP (y)) {
3063 /* inum-x - big-y */
3064 long xx = SCM_INUM (x);
3065
3066 if (xx == 0)
3067 return scm_i_clonebig (y, 0);
3068 else
3069 {
3070 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
3071 SCM result = scm_i_mkbig ();
3072
3073 if (xx >= 0)
3074 mpz_ui_sub (SCM_I_BIG_MPZ (result), xx, SCM_I_BIG_MPZ (y));
3075 else
3076 {
3077 /* x - y == -(y + -x) */
3078 mpz_add_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (y), -xx);
3079 mpz_neg (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result));
3080 }
3081 scm_remember_upto_here_1 (y);
3082
3083 if ((xx < 0 && (sgn_y > 0)) || ((xx > 0) && sgn_y < 0))
3084 /* we know the result will have to be a bignum */
3085 return result;
3086 else
3087 return scm_i_normbig (result);
3088 }
3089 } else if (SCM_REALP (y)) {
3090 long int xx = SCM_INUM (x);
3091 return scm_make_real (xx - SCM_REAL_VALUE (y));
3092 } else if (SCM_COMPLEXP (y)) {
3093 long int xx = SCM_INUM (x);
3094 return scm_make_complex (xx - SCM_COMPLEX_REAL (y),
3095 -SCM_COMPLEX_IMAG (y));
3096 } else {
3097 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3098 }
3099 } else if (SCM_BIGP (x)) {
3100 if (SCM_INUMP (y)) {
3101 /* big-x - inum-y */
3102 long yy = SCM_INUM (y);
3103 int sgn_x = mpz_sgn (SCM_I_BIG_MPZ (x));
3104
3105 scm_remember_upto_here_1 (x);
3106 if (sgn_x == 0)
3107 return SCM_FIXABLE (-yy) ? SCM_MAKINUM (-yy) : scm_long2num (-yy);
3108 else
3109 {
3110 SCM result = scm_i_mkbig ();
3111
3112 mpz_sub_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), yy);
3113 scm_remember_upto_here_1 (x);
3114
3115 if ((sgn_x < 0 && (yy > 0)) || ((sgn_x > 0) && yy < 0))
3116 /* we know the result will have to be a bignum */
3117 return result;
3118 else
3119 return scm_i_normbig (result);
3120 }
3121 }
3122 else if (SCM_BIGP (y))
3123 {
3124 int sgn_x = mpz_sgn (SCM_I_BIG_MPZ (x));
3125 int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
3126 SCM result = scm_i_mkbig ();
3127 mpz_sub (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3128 scm_remember_upto_here_2 (x, y);
3129 /* we know the result will have to be a bignum */
3130 if ((sgn_x == 1) && (sgn_y == -1)) return result;
3131 if ((sgn_x == -1) && (sgn_y == 1)) return result;
3132 return scm_i_normbig (result);
3133 }
3134 else if (SCM_REALP (y)) {
3135 double result = mpz_get_d (SCM_I_BIG_MPZ (x)) - SCM_REAL_VALUE (y);
3136 scm_remember_upto_here_1 (x);
3137 return scm_make_real (result);
3138 }
3139 else if (SCM_COMPLEXP (y)) {
3140 double real_part = mpz_get_d (SCM_I_BIG_MPZ (x)) - SCM_COMPLEX_REAL (y);
3141 scm_remember_upto_here_1 (x);
3142 return scm_make_complex (real_part, - SCM_COMPLEX_IMAG (y));
3143 }
3144 else SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3145 } else if (SCM_REALP (x)) {
3146 if (SCM_INUMP (y)) {
3147 return scm_make_real (SCM_REAL_VALUE (x) - SCM_INUM (y));
3148 } else if (SCM_BIGP (y)) {
3149 double result = SCM_REAL_VALUE (x) - mpz_get_d (SCM_I_BIG_MPZ (y));
3150 scm_remember_upto_here_1 (x);
3151 return scm_make_real (result);
3152 } else if (SCM_REALP (y)) {
3153 return scm_make_real (SCM_REAL_VALUE (x) - SCM_REAL_VALUE (y));
3154 } else if (SCM_COMPLEXP (y)) {
3155 return scm_make_complex (SCM_REAL_VALUE (x) - SCM_COMPLEX_REAL (y),
3156 -SCM_COMPLEX_IMAG (y));
3157 } else {
3158 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3159 }
3160 } else if (SCM_COMPLEXP (x)) {
3161 if (SCM_INUMP (y)) {
3162 return scm_make_complex (SCM_COMPLEX_REAL (x) - SCM_INUM (y),
3163 SCM_COMPLEX_IMAG (x));
3164 } else if (SCM_BIGP (y)) {
3165 double real_part = SCM_COMPLEX_REAL (x) - mpz_get_d (SCM_I_BIG_MPZ (y));
3166 scm_remember_upto_here_1 (x);
3167 return scm_make_complex (real_part, SCM_COMPLEX_IMAG (y));
3168 } else if (SCM_REALP (y)) {
3169 return scm_make_complex (SCM_COMPLEX_REAL (x) - SCM_REAL_VALUE (y),
3170 SCM_COMPLEX_IMAG (x));
3171 } else if (SCM_COMPLEXP (y)) {
3172 return scm_make_complex (SCM_COMPLEX_REAL (x) - SCM_COMPLEX_REAL (y),
3173 SCM_COMPLEX_IMAG (x) - SCM_COMPLEX_IMAG (y));
3174 } else {
3175 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3176 }
3177 } else {
3178 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARG1, s_difference);
3179 }
3180 }
3181 #undef FUNC_NAME
3182
3183
3184 SCM_GPROC1 (s_product, "*", scm_tc7_asubr, scm_product, g_product);
3185 /* "Return the product of all arguments. If called without arguments,\n"
3186 * "1 is returned."
3187 */
3188 SCM
3189 scm_product (SCM x, SCM y)
3190 {
3191 if (SCM_UNBNDP (y)) {
3192 if (SCM_UNBNDP (x)) {
3193 return SCM_MAKINUM (1L);
3194 } else if (SCM_NUMBERP (x)) {
3195 return x;
3196 } else {
3197 SCM_WTA_DISPATCH_1 (g_product, x, SCM_ARG1, s_product);
3198 }
3199 }
3200
3201 if (SCM_INUMP (x)) {
3202 long xx;
3203
3204 intbig:
3205 xx = SCM_INUM (x);
3206
3207 switch (xx)
3208 {
3209 case 0: return x; break;
3210 case 1: return y; break;
3211 }
3212
3213 if (SCM_INUMP (y)) {
3214 long yy = SCM_INUM (y);
3215 long kk = xx * yy;
3216 SCM k = SCM_MAKINUM (kk);
3217 if ((kk == SCM_INUM (k)) && (kk / xx == yy)) {
3218 return k;
3219 } else {
3220 SCM result = scm_i_long2big (xx);
3221 mpz_mul_si (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result), yy);
3222 return scm_i_normbig (result);
3223 }
3224 } else if (SCM_BIGP (y)) {
3225 SCM result = scm_i_mkbig ();
3226 mpz_mul_si (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (y), xx);
3227 scm_remember_upto_here_1 (y);
3228 return result;
3229 } else if (SCM_REALP (y)) {
3230 return scm_make_real (xx * SCM_REAL_VALUE (y));
3231 } else if (SCM_COMPLEXP (y)) {
3232 return scm_make_complex (xx * SCM_COMPLEX_REAL (y),
3233 xx * SCM_COMPLEX_IMAG (y));
3234 } else {
3235 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
3236 }
3237 } else if (SCM_BIGP (x)) {
3238 if (SCM_INUMP (y)) {
3239 SCM_SWAP (x, y);
3240 goto intbig;
3241 } else if (SCM_BIGP (y)) {
3242 SCM result = scm_i_mkbig ();
3243 mpz_mul (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
3244 scm_remember_upto_here_2 (x, y);
3245 return result;
3246 } else if (SCM_REALP (y)) {
3247 double result = mpz_get_d (SCM_I_BIG_MPZ (x)) * SCM_REAL_VALUE (y);
3248 scm_remember_upto_here_1 (x);
3249 return scm_make_real (result);
3250 } else if (SCM_COMPLEXP (y)) {
3251 double z = mpz_get_d (SCM_I_BIG_MPZ (x));
3252 scm_remember_upto_here_1 (x);
3253 return scm_make_complex (z * SCM_COMPLEX_REAL (y),
3254 z * SCM_COMPLEX_IMAG (y));
3255 } else {
3256 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
3257 }
3258 } else if (SCM_REALP (x)) {
3259 if (SCM_INUMP (y)) {
3260 return scm_make_real (SCM_INUM (y) * SCM_REAL_VALUE (x));
3261 } else if (SCM_BIGP (y)) {
3262 double result = mpz_get_d (SCM_I_BIG_MPZ (y)) * SCM_REAL_VALUE (x);
3263 scm_remember_upto_here_1 (y);
3264 return scm_make_real (result);
3265 } else if (SCM_REALP (y)) {
3266 return scm_make_real (SCM_REAL_VALUE (x) * SCM_REAL_VALUE (y));
3267 } else if (SCM_COMPLEXP (y)) {
3268 return scm_make_complex (SCM_REAL_VALUE (x) * SCM_COMPLEX_REAL (y),
3269 SCM_REAL_VALUE (x) * SCM_COMPLEX_IMAG (y));
3270 } else {
3271 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
3272 }
3273 } else if (SCM_COMPLEXP (x)) {
3274 if (SCM_INUMP (y)) {
3275 return scm_make_complex (SCM_INUM (y) * SCM_COMPLEX_REAL (x),
3276 SCM_INUM (y) * SCM_COMPLEX_IMAG (x));
3277 } else if (SCM_BIGP (y)) {
3278 double z = mpz_get_d (SCM_I_BIG_MPZ (y));
3279 scm_remember_upto_here_1 (y);
3280 return scm_make_complex (z * SCM_COMPLEX_REAL (y),
3281 z * SCM_COMPLEX_IMAG (y));
3282 } else if (SCM_REALP (y)) {
3283 return scm_make_complex (SCM_REAL_VALUE (y) * SCM_COMPLEX_REAL (x),
3284 SCM_REAL_VALUE (y) * SCM_COMPLEX_IMAG (x));
3285 } else if (SCM_COMPLEXP (y)) {
3286 return scm_make_complex (SCM_COMPLEX_REAL (x) * SCM_COMPLEX_REAL (y)
3287 - SCM_COMPLEX_IMAG (x) * SCM_COMPLEX_IMAG (y),
3288 SCM_COMPLEX_REAL (x) * SCM_COMPLEX_IMAG (y)
3289 + SCM_COMPLEX_IMAG (x) * SCM_COMPLEX_REAL (y));
3290 } else {
3291 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
3292 }
3293 } else {
3294 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARG1, s_product);
3295 }
3296 }
3297
3298 double
3299 scm_num2dbl (SCM a, const char *why)
3300 #define FUNC_NAME why
3301 {
3302 if (SCM_INUMP (a)) {
3303 return (double) SCM_INUM (a);
3304 } else if (SCM_BIGP (a)) {
3305 double result = mpz_get_d (SCM_I_BIG_MPZ (a));
3306 scm_remember_upto_here_1 (a);
3307 return result;
3308 } else if (SCM_REALP (a)) {
3309 return (SCM_REAL_VALUE (a));
3310 } else {
3311 SCM_WRONG_TYPE_ARG (SCM_ARGn, a);
3312 }
3313 }
3314 #undef FUNC_NAME
3315
3316 #if ((defined (HAVE_ISINF) && defined (HAVE_ISNAN)) \
3317 || (defined (HAVE_FINITE) && defined (HAVE_ISNAN)))
3318 #define ALLOW_DIVIDE_BY_ZERO
3319 /* #define ALLOW_DIVIDE_BY_EXACT_ZERO */
3320 #endif
3321
3322 /* The code below for complex division is adapted from the GNU
3323 libstdc++, which adapted it from f2c's libF77, and is subject to
3324 this copyright: */
3325
3326 /****************************************************************
3327 Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories and Bellcore.
3328
3329 Permission to use, copy, modify, and distribute this software
3330 and its documentation for any purpose and without fee is hereby
3331 granted, provided that the above copyright notice appear in all
3332 copies and that both that the copyright notice and this
3333 permission notice and warranty disclaimer appear in supporting
3334 documentation, and that the names of AT&T Bell Laboratories or
3335 Bellcore or any of their entities not be used in advertising or
3336 publicity pertaining to distribution of the software without
3337 specific, written prior permission.
3338
3339 AT&T and Bellcore disclaim all warranties with regard to this
3340 software, including all implied warranties of merchantability
3341 and fitness. In no event shall AT&T or Bellcore be liable for
3342 any special, indirect or consequential damages or any damages
3343 whatsoever resulting from loss of use, data or profits, whether
3344 in an action of contract, negligence or other tortious action,
3345 arising out of or in connection with the use or performance of
3346 this software.
3347 ****************************************************************/
3348
3349 SCM_GPROC1 (s_divide, "/", scm_tc7_asubr, scm_divide, g_divide);
3350 /* Divide the first argument by the product of the remaining
3351 arguments. If called with one argument @var{z1}, 1/@var{z1} is
3352 returned. */
3353 #define FUNC_NAME s_divide
3354 SCM
3355 scm_divide (SCM x, SCM y)
3356 {
3357 double a;
3358
3359 if (SCM_UNBNDP (y)) {
3360 if (SCM_UNBNDP (x)) {
3361 SCM_WTA_DISPATCH_0 (g_divide, s_divide);
3362 } else if (SCM_INUMP (x)) {
3363 long xx = SCM_INUM (x);
3364 if (xx == 1 || xx == -1) {
3365 return x;
3366 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
3367 } else if (xx == 0) {
3368 scm_num_overflow (s_divide);
3369 #endif
3370 } else {
3371 return scm_make_real (1.0 / (double) xx);
3372 }
3373 } else if (SCM_BIGP (x)) {
3374 return scm_make_real (1.0 / scm_i_big2dbl (x));
3375 } else if (SCM_REALP (x)) {
3376 double xx = SCM_REAL_VALUE (x);
3377 #ifndef ALLOW_DIVIDE_BY_ZERO
3378 if (xx == 0.0)
3379 scm_num_overflow (s_divide);
3380 else
3381 #endif
3382 return scm_make_real (1.0 / xx);
3383 } else if (SCM_COMPLEXP (x)) {
3384 double r = SCM_COMPLEX_REAL (x);
3385 double i = SCM_COMPLEX_IMAG (x);
3386 if (r <= i) {
3387 double t = r / i;
3388 double d = i * (1.0 + t * t);
3389 return scm_make_complex (t / d, -1.0 / d);
3390 } else {
3391 double t = i / r;
3392 double d = r * (1.0 + t * t);
3393 return scm_make_complex (1.0 / d, -t / d);
3394 }
3395 } else {
3396 SCM_WTA_DISPATCH_1 (g_divide, x, SCM_ARG1, s_divide);
3397 }
3398 }
3399
3400 if (SCM_INUMP (x)) {
3401 long xx = SCM_INUM (x);
3402 if (SCM_INUMP (y)) {
3403 long yy = SCM_INUM (y);
3404 if (yy == 0) {
3405 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
3406 scm_num_overflow (s_divide);
3407 #else
3408 return scm_make_real ((double) xx / (double) yy);
3409 #endif
3410 } else if (xx % yy != 0) {
3411 return scm_make_real ((double) xx / (double) yy);
3412 } else {
3413 long z = xx / yy;
3414 if (SCM_FIXABLE (z)) {
3415 return SCM_MAKINUM (z);
3416 } else {
3417 return scm_i_long2big (z);
3418 }
3419 }
3420 } else if (SCM_BIGP (y)) {
3421 return scm_make_real ((double) xx / scm_i_big2dbl (y));
3422 } else if (SCM_REALP (y)) {
3423 double yy = SCM_REAL_VALUE (y);
3424 #ifndef ALLOW_DIVIDE_BY_ZERO
3425 if (yy == 0.0)
3426 scm_num_overflow (s_divide);
3427 else
3428 #endif
3429 return scm_make_real ((double) xx / yy);
3430 } else if (SCM_COMPLEXP (y)) {
3431 a = xx;
3432 complex_div: /* y _must_ be a complex number */
3433 {
3434 double r = SCM_COMPLEX_REAL (y);
3435 double i = SCM_COMPLEX_IMAG (y);
3436 if (r <= i) {
3437 double t = r / i;
3438 double d = i * (1.0 + t * t);
3439 return scm_make_complex ((a * t) / d, -a / d);
3440 } else {
3441 double t = i / r;
3442 double d = r * (1.0 + t * t);
3443 return scm_make_complex (a / d, -(a * t) / d);
3444 }
3445 }
3446 } else {
3447 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
3448 }
3449 } else if (SCM_BIGP (x)) {
3450 if (SCM_INUMP (y)) {
3451 long int yy = SCM_INUM (y);
3452 if (yy == 0) {
3453 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
3454 scm_num_overflow (s_divide);
3455 #else
3456 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
3457 scm_remember_upto_here_1 (x);
3458 return (sgn == 0) ? scm_nan () : scm_inf ();
3459 #endif
3460 } else if (yy == 1) {
3461 return x;
3462 } else {
3463 /* FIXME: HMM, what are the relative performance issues here?
3464 We need to test. Is it faster on average to test
3465 divisible_p, then perform whichever operation, or is it
3466 faster to perform the integer div opportunistically and
3467 switch to real if there's a remainder? For now we take the
3468 middle ground: test, then if divisible, use the faster div
3469 func. */
3470
3471 long abs_yy = yy < 0 ? -yy : yy;
3472 int divisible_p = mpz_divisible_ui_p (SCM_I_BIG_MPZ (x), abs_yy);
3473
3474 if (divisible_p) {
3475 SCM result = scm_i_mkbig ();
3476 mpz_divexact_ui (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (x), abs_yy);
3477 scm_remember_upto_here_1 (x);
3478 if (yy < 0)
3479 mpz_neg (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (result));
3480 return scm_i_normbig (result);
3481 }
3482 else {
3483 return scm_make_real (scm_i_big2dbl (x) / (double) yy);
3484 }
3485 }
3486 } else if (SCM_BIGP (y)) {
3487 int y_is_zero = (mpz_sgn (SCM_I_BIG_MPZ (y)) == 0);
3488 if (y_is_zero) {
3489 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
3490 scm_num_overflow (s_divide);
3491 #else
3492 int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
3493 scm_remember_upto_here_1 (x);
3494 return (sgn == 0) ? scm_nan () : scm_inf ();
3495 #endif
3496 } else {
3497 /* big_x / big_y */
3498 int divisible_p = mpz_divisible_p (SCM_I_BIG_MPZ (x),
3499 SCM_I_BIG_MPZ (y));
3500 if (divisible_p) {
3501 SCM result = scm_i_mkbig ();
3502 mpz_divexact (SCM_I_BIG_MPZ (result),
3503 SCM_I_BIG_MPZ (x),
3504 SCM_I_BIG_MPZ (y));
3505 scm_remember_upto_here_2 (x, y);
3506 return scm_i_normbig (result);
3507 }
3508 else {
3509 double dbx = mpz_get_d (SCM_I_BIG_MPZ (x));
3510 double dby = mpz_get_d (SCM_I_BIG_MPZ (y));
3511 scm_remember_upto_here_2 (x, y);
3512 return scm_make_real (dbx / dby);
3513 }
3514 }
3515 } else if (SCM_REALP (y)) {
3516 double yy = SCM_REAL_VALUE (y);
3517 #ifndef ALLOW_DIVIDE_BY_ZERO
3518 if (yy == 0.0)
3519 scm_num_overflow (s_divide);
3520 else
3521 #endif
3522 return scm_make_real (scm_i_big2dbl (x) / yy);
3523 } else if (SCM_COMPLEXP (y)) {
3524 a = scm_i_big2dbl (x);
3525 goto complex_div;
3526 } else {
3527 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
3528 }
3529 } else if (SCM_REALP (x)) {
3530 double rx = SCM_REAL_VALUE (x);
3531 if (SCM_INUMP (y)) {
3532 long int yy = SCM_INUM (y);
3533 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
3534 if (yy == 0)
3535 scm_num_overflow (s_divide);
3536 else
3537 #endif
3538 return scm_make_real (rx / (double) yy);
3539 } else if (SCM_BIGP (y)) {
3540 double dby = mpz_get_d (SCM_I_BIG_MPZ (y));
3541 scm_remember_upto_here_1 (y);
3542 return scm_make_real (rx / dby);
3543 } else if (SCM_REALP (y)) {
3544 double yy = SCM_REAL_VALUE (y);
3545 #ifndef ALLOW_DIVIDE_BY_ZERO
3546 if (yy == 0.0)
3547 scm_num_overflow (s_divide);
3548 else
3549 #endif
3550 return scm_make_real (rx / yy);
3551 } else if (SCM_COMPLEXP (y)) {
3552 a = rx;
3553 goto complex_div;
3554 } else {
3555 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
3556 }
3557 } else if (SCM_COMPLEXP (x)) {
3558 double rx = SCM_COMPLEX_REAL (x);
3559 double ix = SCM_COMPLEX_IMAG (x);
3560 if (SCM_INUMP (y)) {
3561 long int yy = SCM_INUM (y);
3562 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
3563 if (yy == 0)
3564 scm_num_overflow (s_divide);
3565 else
3566 #endif
3567 {
3568 double d = yy;
3569 return scm_make_complex (rx / d, ix / d);
3570 }
3571 } else if (SCM_BIGP (y)) {
3572 double dby = mpz_get_d (SCM_I_BIG_MPZ (y));
3573 scm_remember_upto_here_1 (y);
3574 return scm_make_complex (rx / dby, ix / dby);
3575 } else if (SCM_REALP (y)) {
3576 double yy = SCM_REAL_VALUE (y);
3577 #ifndef ALLOW_DIVIDE_BY_ZERO
3578 if (yy == 0.0)
3579 scm_num_overflow (s_divide);
3580 else
3581 #endif
3582 return scm_make_complex (rx / yy, ix / yy);
3583 } else if (SCM_COMPLEXP (y)) {
3584 double ry = SCM_COMPLEX_REAL (y);
3585 double iy = SCM_COMPLEX_IMAG (y);
3586 if (ry <= iy) {
3587 double t = ry / iy;
3588 double d = iy * (1.0 + t * t);
3589 return scm_make_complex ((rx * t + ix) / d, (ix * t - rx) / d);
3590 } else {
3591 double t = iy / ry;
3592 double d = ry * (1.0 + t * t);
3593 return scm_make_complex ((rx + ix * t) / d, (ix - rx * t) / d);
3594 }
3595 } else {
3596 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
3597 }
3598 } else {
3599 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARG1, s_divide);
3600 }
3601 }
3602 #undef FUNC_NAME
3603
3604 SCM_GPROC1 (s_asinh, "$asinh", scm_tc7_cxr, (SCM (*)()) scm_asinh, g_asinh);
3605 /* "Return the inverse hyperbolic sine of @var{x}."
3606 */
3607 double
3608 scm_asinh (double x)
3609 {
3610 return log (x + sqrt (x * x + 1));
3611 }
3612
3613
3614 SCM_GPROC1 (s_acosh, "$acosh", scm_tc7_cxr, (SCM (*)()) scm_acosh, g_acosh);
3615 /* "Return the inverse hyperbolic cosine of @var{x}."
3616 */
3617 double
3618 scm_acosh (double x)
3619 {
3620 return log (x + sqrt (x * x - 1));
3621 }
3622
3623
3624 SCM_GPROC1 (s_atanh, "$atanh", scm_tc7_cxr, (SCM (*)()) scm_atanh, g_atanh);
3625 /* "Return the inverse hyperbolic tangent of @var{x}."
3626 */
3627 double
3628 scm_atanh (double x)
3629 {
3630 return 0.5 * log ((1 + x) / (1 - x));
3631 }
3632
3633
3634 SCM_GPROC1 (s_truncate, "truncate", scm_tc7_cxr, (SCM (*)()) scm_truncate, g_truncate);
3635 /* "Round the inexact number @var{x} towards zero."
3636 */
3637 double
3638 scm_truncate (double x)
3639 {
3640 if (x < 0.0)
3641 return -floor (-x);
3642 return floor (x);
3643 }
3644
3645
3646 SCM_GPROC1 (s_round, "round", scm_tc7_cxr, (SCM (*)()) scm_round, g_round);
3647 /* "Round the inexact number @var{x}. If @var{x} is halfway between two\n"
3648 * "numbers, round towards even."
3649 */
3650 double
3651 scm_round (double x)
3652 {
3653 double plus_half = x + 0.5;
3654 double result = floor (plus_half);
3655 /* Adjust so that the scm_round is towards even. */
3656 return (plus_half == result && plus_half / 2 != floor (plus_half / 2))
3657 ? result - 1 : result;
3658 }
3659
3660
3661 SCM_GPROC1 (s_i_floor, "floor", scm_tc7_cxr, (SCM (*)()) floor, g_i_floor);
3662 /* "Round the number @var{x} towards minus infinity."
3663 */
3664 SCM_GPROC1 (s_i_ceil, "ceiling", scm_tc7_cxr, (SCM (*)()) ceil, g_i_ceil);
3665 /* "Round the number @var{x} towards infinity."
3666 */
3667 SCM_GPROC1 (s_i_sqrt, "$sqrt", scm_tc7_cxr, (SCM (*)()) sqrt, g_i_sqrt);
3668 /* "Return the square root of the real number @var{x}."
3669 */
3670 SCM_GPROC1 (s_i_abs, "$abs", scm_tc7_cxr, (SCM (*)()) fabs, g_i_abs);
3671 /* "Return the absolute value of the real number @var{x}."
3672 */
3673 SCM_GPROC1 (s_i_exp, "$exp", scm_tc7_cxr, (SCM (*)()) exp, g_i_exp);
3674 /* "Return the @var{x}th power of e."
3675 */
3676 SCM_GPROC1 (s_i_log, "$log", scm_tc7_cxr, (SCM (*)()) log, g_i_log);
3677 /* "Return the natural logarithm of the real number @var{x}."
3678 */
3679 SCM_GPROC1 (s_i_sin, "$sin", scm_tc7_cxr, (SCM (*)()) sin, g_i_sin);
3680 /* "Return the sine of the real number @var{x}."
3681 */
3682 SCM_GPROC1 (s_i_cos, "$cos", scm_tc7_cxr, (SCM (*)()) cos, g_i_cos);
3683 /* "Return the cosine of the real number @var{x}."
3684 */
3685 SCM_GPROC1 (s_i_tan, "$tan", scm_tc7_cxr, (SCM (*)()) tan, g_i_tan);
3686 /* "Return the tangent of the real number @var{x}."
3687 */
3688 SCM_GPROC1 (s_i_asin, "$asin", scm_tc7_cxr, (SCM (*)()) asin, g_i_asin);
3689 /* "Return the arc sine of the real number @var{x}."
3690 */
3691 SCM_GPROC1 (s_i_acos, "$acos", scm_tc7_cxr, (SCM (*)()) acos, g_i_acos);
3692 /* "Return the arc cosine of the real number @var{x}."
3693 */
3694 SCM_GPROC1 (s_i_atan, "$atan", scm_tc7_cxr, (SCM (*)()) atan, g_i_atan);
3695 /* "Return the arc tangent of the real number @var{x}."
3696 */
3697 SCM_GPROC1 (s_i_sinh, "$sinh", scm_tc7_cxr, (SCM (*)()) sinh, g_i_sinh);
3698 /* "Return the hyperbolic sine of the real number @var{x}."
3699 */
3700 SCM_GPROC1 (s_i_cosh, "$cosh", scm_tc7_cxr, (SCM (*)()) cosh, g_i_cosh);
3701 /* "Return the hyperbolic cosine of the real number @var{x}."
3702 */
3703 SCM_GPROC1 (s_i_tanh, "$tanh", scm_tc7_cxr, (SCM (*)()) tanh, g_i_tanh);
3704 /* "Return the hyperbolic tangent of the real number @var{x}."
3705 */
3706
3707 struct dpair
3708 {
3709 double x, y;
3710 };
3711
3712 static void scm_two_doubles (SCM x,
3713 SCM y,
3714 const char *sstring,
3715 struct dpair * xy);
3716
3717 static void
3718 scm_two_doubles (SCM x, SCM y, const char *sstring, struct dpair *xy)
3719 {
3720 if (SCM_INUMP (x)) {
3721 xy->x = SCM_INUM (x);
3722 } else if (SCM_BIGP (x)) {
3723 xy->x = scm_i_big2dbl (x);
3724 } else if (SCM_REALP (x)) {
3725 xy->x = SCM_REAL_VALUE (x);
3726 } else {
3727 scm_wrong_type_arg (sstring, SCM_ARG1, x);
3728 }
3729
3730 if (SCM_INUMP (y)) {
3731 xy->y = SCM_INUM (y);
3732 } else if (SCM_BIGP (y)) {
3733 xy->y = scm_i_big2dbl (y);
3734 } else if (SCM_REALP (y)) {
3735 xy->y = SCM_REAL_VALUE (y);
3736 } else {
3737 scm_wrong_type_arg (sstring, SCM_ARG2, y);
3738 }
3739 }
3740
3741
3742 SCM_DEFINE (scm_sys_expt, "$expt", 2, 0, 0,
3743 (SCM x, SCM y),
3744 "Return @var{x} raised to the power of @var{y}. This\n"
3745 "procedure does not accept complex arguments.")
3746 #define FUNC_NAME s_scm_sys_expt
3747 {
3748 struct dpair xy;
3749 scm_two_doubles (x, y, FUNC_NAME, &xy);
3750 return scm_make_real (pow (xy.x, xy.y));
3751 }
3752 #undef FUNC_NAME
3753
3754
3755 SCM_DEFINE (scm_sys_atan2, "$atan2", 2, 0, 0,
3756 (SCM x, SCM y),
3757 "Return the arc tangent of the two arguments @var{x} and\n"
3758 "@var{y}. This is similar to calculating the arc tangent of\n"
3759 "@var{x} / @var{y}, except that the signs of both arguments\n"
3760 "are used to determine the quadrant of the result. This\n"
3761 "procedure does not accept complex arguments.")
3762 #define FUNC_NAME s_scm_sys_atan2
3763 {
3764 struct dpair xy;
3765 scm_two_doubles (x, y, FUNC_NAME, &xy);
3766 return scm_make_real (atan2 (xy.x, xy.y));
3767 }
3768 #undef FUNC_NAME
3769
3770
3771 SCM_DEFINE (scm_make_rectangular, "make-rectangular", 2, 0, 0,
3772 (SCM real, SCM imaginary),
3773 "Return a complex number constructed of the given @var{real} and\n"
3774 "@var{imaginary} parts.")
3775 #define FUNC_NAME s_scm_make_rectangular
3776 {
3777 struct dpair xy;
3778 scm_two_doubles (real, imaginary, FUNC_NAME, &xy);
3779 return scm_make_complex (xy.x, xy.y);
3780 }
3781 #undef FUNC_NAME
3782
3783
3784
3785 SCM_DEFINE (scm_make_polar, "make-polar", 2, 0, 0,
3786 (SCM x, SCM y),
3787 "Return the complex number @var{x} * e^(i * @var{y}).")
3788 #define FUNC_NAME s_scm_make_polar
3789 {
3790 struct dpair xy;
3791 scm_two_doubles (x, y, FUNC_NAME, &xy);
3792 return scm_make_complex (xy.x * cos (xy.y), xy.x * sin (xy.y));
3793 }
3794 #undef FUNC_NAME
3795
3796
3797 SCM_GPROC (s_real_part, "real-part", 1, 0, 0, scm_real_part, g_real_part);
3798 /* "Return the real part of the number @var{z}."
3799 */
3800 SCM
3801 scm_real_part (SCM z)
3802 {
3803 if (SCM_INUMP (z)) {
3804 return z;
3805 } else if (SCM_BIGP (z)) {
3806 return z;
3807 } else if (SCM_REALP (z)) {
3808 return z;
3809 } else if (SCM_COMPLEXP (z)) {
3810 return scm_make_real (SCM_COMPLEX_REAL (z));
3811 } else {
3812 SCM_WTA_DISPATCH_1 (g_real_part, z, SCM_ARG1, s_real_part);
3813 }
3814 }
3815
3816
3817 SCM_GPROC (s_imag_part, "imag-part", 1, 0, 0, scm_imag_part, g_imag_part);
3818 /* "Return the imaginary part of the number @var{z}."
3819 */
3820 SCM
3821 scm_imag_part (SCM z)
3822 {
3823 if (SCM_INUMP (z)) {
3824 return SCM_INUM0;
3825 } else if (SCM_BIGP (z)) {
3826 return SCM_INUM0;
3827 } else if (SCM_REALP (z)) {
3828 return scm_flo0;
3829 } else if (SCM_COMPLEXP (z)) {
3830 return scm_make_real (SCM_COMPLEX_IMAG (z));
3831 } else {
3832 SCM_WTA_DISPATCH_1 (g_imag_part, z, SCM_ARG1, s_imag_part);
3833 }
3834 }
3835
3836
3837 SCM_GPROC (s_magnitude, "magnitude", 1, 0, 0, scm_magnitude, g_magnitude);
3838 /* "Return the magnitude of the number @var{z}. This is the same as\n"
3839 * "@code{abs} for real arguments, but also allows complex numbers."
3840 */
3841 SCM
3842 scm_magnitude (SCM z)
3843 {
3844 if (SCM_INUMP (z)) {
3845 long int zz = SCM_INUM (z);
3846 if (zz >= 0) {
3847 return z;
3848 } else if (SCM_POSFIXABLE (-zz)) {
3849 return SCM_MAKINUM (-zz);
3850 } else {
3851 return scm_i_long2big (-zz);
3852 }
3853 } else if (SCM_BIGP (z)) {
3854 int sgn = mpz_sgn (SCM_I_BIG_MPZ (z));
3855 scm_remember_upto_here_1 (z);
3856 if (sgn < 0) {
3857 return scm_i_clonebig (z, 0);
3858 } else {
3859 return z;
3860 }
3861 } else if (SCM_REALP (z)) {
3862 return scm_make_real (fabs (SCM_REAL_VALUE (z)));
3863 } else if (SCM_COMPLEXP (z)) {
3864 double r = SCM_COMPLEX_REAL (z);
3865 double i = SCM_COMPLEX_IMAG (z);
3866 return scm_make_real (sqrt (i * i + r * r));
3867 } else {
3868 SCM_WTA_DISPATCH_1 (g_magnitude, z, SCM_ARG1, s_magnitude);
3869 }
3870 }
3871
3872
3873 SCM_GPROC (s_angle, "angle", 1, 0, 0, scm_angle, g_angle);
3874 /* "Return the angle of the complex number @var{z}."
3875 */
3876 SCM
3877 scm_angle (SCM z)
3878 {
3879 if (SCM_INUMP (z)) {
3880 if (SCM_INUM (z) >= 0) {
3881 return scm_make_real (atan2 (0.0, 1.0));
3882 } else {
3883 return scm_make_real (atan2 (0.0, -1.0));
3884 }
3885 } else if (SCM_BIGP (z)) {
3886 int sgn = mpz_sgn (SCM_I_BIG_MPZ (z));
3887 scm_remember_upto_here_1 (z);
3888 if (sgn < 0) {
3889 return scm_make_real (atan2 (0.0, -1.0));
3890 } else {
3891 return scm_make_real (atan2 (0.0, 1.0));
3892 }
3893 } else if (SCM_REALP (z)) {
3894 return scm_make_real (atan2 (0.0, SCM_REAL_VALUE (z)));
3895 } else if (SCM_COMPLEXP (z)) {
3896 return scm_make_real (atan2 (SCM_COMPLEX_IMAG (z), SCM_COMPLEX_REAL (z)));
3897 } else {
3898 SCM_WTA_DISPATCH_1 (g_angle, z, SCM_ARG1, s_angle);
3899 }
3900 }
3901
3902
3903 SCM_GPROC (s_exact_to_inexact, "exact->inexact", 1, 0, 0, scm_exact_to_inexact, g_exact_to_inexact);
3904 /* Convert the number @var{x} to its inexact representation.\n"
3905 */
3906 SCM
3907 scm_exact_to_inexact (SCM z)
3908 {
3909 if (SCM_INUMP (z))
3910 return scm_make_real ((double) SCM_INUM (z));
3911 else if (SCM_BIGP (z))
3912 return scm_make_real (scm_i_big2dbl (z));
3913 else if (SCM_INEXACTP (z))
3914 return z;
3915 else
3916 SCM_WTA_DISPATCH_1 (g_exact_to_inexact, z, 1, s_exact_to_inexact);
3917 }
3918
3919
3920 SCM_DEFINE (scm_inexact_to_exact, "inexact->exact", 1, 0, 0,
3921 (SCM z),
3922 "Return an exact number that is numerically closest to @var{z}.")
3923 #define FUNC_NAME s_scm_inexact_to_exact
3924 {
3925 if (SCM_INUMP (z)) {
3926 return z;
3927 } else if (SCM_BIGP (z)) {
3928 return z;
3929 } else if (SCM_REALP (z)) {
3930 double u = floor (SCM_REAL_VALUE (z) + 0.5);
3931 long lu = (long) u;
3932 if (SCM_FIXABLE (lu)) {
3933 return SCM_MAKINUM (lu);
3934 } else if (isfinite (u) && !xisnan (u)) {
3935 return scm_i_dbl2big (u);
3936 } else {
3937 scm_num_overflow (s_scm_inexact_to_exact);
3938 }
3939 } else {
3940 SCM_WRONG_TYPE_ARG (1, z);
3941 }
3942 }
3943 #undef FUNC_NAME
3944
3945 /* if you need to change this, change test-num2integral.c as well */
3946 #if SCM_SIZEOF_LONG_LONG != 0
3947 # ifndef LLONG_MAX
3948 # define ULLONG_MAX ((unsigned long long) (-1))
3949 # define LLONG_MAX ((long long) (ULLONG_MAX >> 1))
3950 # define LLONG_MIN (~LLONG_MAX)
3951 # endif
3952 #endif
3953
3954 /* Parameters for creating integer conversion routines.
3955
3956 Define the following preprocessor macros before including
3957 "libguile/num2integral.i.c":
3958
3959 NUM2INTEGRAL - the name of the function for converting from a
3960 Scheme object to the integral type. This function will be
3961 defined when including "num2integral.i.c".
3962
3963 INTEGRAL2NUM - the name of the function for converting from the
3964 integral type to a Scheme object. This function will be defined.
3965
3966 INTEGRAL2BIG - the name of an internal function that createas a
3967 bignum from the integral type. This function will be defined.
3968 The name should start with "scm_i_".
3969
3970 ITYPE - the name of the integral type.
3971
3972 UNSIGNED - Define this to 1 when ITYPE is an unsigned type. Define
3973 it to 0 otherwise.
3974
3975 UNSIGNED_ITYPE - the name of the the unsigned variant of the
3976 integral type. If you don't define this, it defaults to
3977 "unsigned ITYPE" for signed types and simply "ITYPE" for unsigned
3978 ones.
3979
3980 SIZEOF_ITYPE - an expression giving the size of the integral type
3981 in bytes. This expression must be computable by the
3982 preprocessor. (SIZEOF_FOO values are calculated by configure.in
3983 for common types).
3984
3985 */
3986
3987 #define NUM2INTEGRAL scm_num2short
3988 #define INTEGRAL2NUM scm_short2num
3989 #define INTEGRAL2BIG scm_i_short2big
3990 #define UNSIGNED 0
3991 #define ITYPE short
3992 #define SIZEOF_ITYPE SIZEOF_SHORT
3993 #include "libguile/num2integral.i.c"
3994
3995 #define NUM2INTEGRAL scm_num2ushort
3996 #define INTEGRAL2NUM scm_ushort2num
3997 #define INTEGRAL2BIG scm_i_ushort2big
3998 #define UNSIGNED 1
3999 #define ITYPE unsigned short
4000 #define SIZEOF_ITYPE SIZEOF_UNSIGNED_SHORT
4001 #include "libguile/num2integral.i.c"
4002
4003 #define NUM2INTEGRAL scm_num2int
4004 #define INTEGRAL2NUM scm_int2num
4005 #define INTEGRAL2BIG scm_i_int2big
4006 #define UNSIGNED 0
4007 #define ITYPE int
4008 #define SIZEOF_ITYPE SIZEOF_INT
4009 #include "libguile/num2integral.i.c"
4010
4011 #define NUM2INTEGRAL scm_num2uint
4012 #define INTEGRAL2NUM scm_uint2num
4013 #define INTEGRAL2BIG scm_i_uint2big
4014 #define UNSIGNED 1
4015 #define ITYPE unsigned int
4016 #define SIZEOF_ITYPE SIZEOF_UNSIGNED_INT
4017 #include "libguile/num2integral.i.c"
4018
4019 #define NUM2INTEGRAL scm_num2long
4020 #define INTEGRAL2NUM scm_long2num
4021 #define INTEGRAL2BIG scm_i_long2big
4022 #define UNSIGNED 0
4023 #define ITYPE long
4024 #define SIZEOF_ITYPE SIZEOF_LONG
4025 #include "libguile/num2integral.i.c"
4026
4027 #define NUM2INTEGRAL scm_num2ulong
4028 #define INTEGRAL2NUM scm_ulong2num
4029 #define INTEGRAL2BIG scm_i_ulong2big
4030 #define UNSIGNED 1
4031 #define ITYPE unsigned long
4032 #define SIZEOF_ITYPE SIZEOF_UNSIGNED_LONG
4033 #include "libguile/num2integral.i.c"
4034
4035 #define NUM2INTEGRAL scm_num2ptrdiff
4036 #define INTEGRAL2NUM scm_ptrdiff2num
4037 #define INTEGRAL2BIG scm_i_ptrdiff2big
4038 #define UNSIGNED 0
4039 #define ITYPE scm_t_ptrdiff
4040 #define UNSIGNED_ITYPE size_t
4041 #define SIZEOF_ITYPE SCM_SIZEOF_SCM_T_PTRDIFF
4042 #include "libguile/num2integral.i.c"
4043
4044 #define NUM2INTEGRAL scm_num2size
4045 #define INTEGRAL2NUM scm_size2num
4046 #define INTEGRAL2BIG scm_i_size2big
4047 #define UNSIGNED 1
4048 #define ITYPE size_t
4049 #define SIZEOF_ITYPE SIZEOF_SIZE_T
4050 #include "libguile/num2integral.i.c"
4051
4052 #if SCM_SIZEOF_LONG_LONG != 0
4053
4054 #ifndef ULONG_LONG_MAX
4055 #define ULONG_LONG_MAX (~0ULL)
4056 #endif
4057
4058 #define NUM2INTEGRAL scm_num2long_long
4059 #define INTEGRAL2NUM scm_long_long2num
4060 #define INTEGRAL2BIG scm_i_long_long2big
4061 #define UNSIGNED 0
4062 #define ITYPE long long
4063 #define SIZEOF_ITYPE SIZEOF_LONG_LONG
4064 #include "libguile/num2integral.i.c"
4065
4066 #define NUM2INTEGRAL scm_num2ulong_long
4067 #define INTEGRAL2NUM scm_ulong_long2num
4068 #define INTEGRAL2BIG scm_i_ulong_long2big
4069 #define UNSIGNED 1
4070 #define ITYPE unsigned long long
4071 #define SIZEOF_ITYPE SIZEOF_UNSIGNED_LONG_LONG
4072 #include "libguile/num2integral.i.c"
4073
4074 #endif /* SCM_SIZEOF_LONG_LONG != 0 */
4075
4076 #define NUM2FLOAT scm_num2float
4077 #define FLOAT2NUM scm_float2num
4078 #define FTYPE float
4079 #include "libguile/num2float.i.c"
4080
4081 #define NUM2FLOAT scm_num2double
4082 #define FLOAT2NUM scm_double2num
4083 #define FTYPE double
4084 #include "libguile/num2float.i.c"
4085
4086 #ifdef GUILE_DEBUG
4087
4088 #ifndef SIZE_MAX
4089 #define SIZE_MAX ((size_t) (-1))
4090 #endif
4091 #ifndef PTRDIFF_MIN
4092 #define PTRDIFF_MIN \
4093 ((scm_t_ptrdiff) ((scm_t_ptrdiff) 1 \
4094 << ((sizeof (scm_t_ptrdiff) * SCM_CHAR_BIT) - 1)))
4095 #endif
4096 #ifndef PTRDIFF_MAX
4097 #define PTRDIFF_MAX (~ PTRDIFF_MIN)
4098 #endif
4099
4100 #define CHECK(type, v) \
4101 do { \
4102 if ((v) != scm_num2##type (scm_##type##2num (v), 1, "check_sanity")) \
4103 abort (); \
4104 } while (0);
4105
4106 static void
4107 check_sanity ()
4108 {
4109 CHECK (short, 0);
4110 CHECK (ushort, 0U);
4111 CHECK (int, 0);
4112 CHECK (uint, 0U);
4113 CHECK (long, 0L);
4114 CHECK (ulong, 0UL);
4115 CHECK (size, 0);
4116 CHECK (ptrdiff, 0);
4117
4118 CHECK (short, -1);
4119 CHECK (int, -1);
4120 CHECK (long, -1L);
4121 CHECK (ptrdiff, -1);
4122
4123 CHECK (short, SHRT_MAX);
4124 CHECK (short, SHRT_MIN);
4125 CHECK (ushort, USHRT_MAX);
4126 CHECK (int, INT_MAX);
4127 CHECK (int, INT_MIN);
4128 CHECK (uint, UINT_MAX);
4129 CHECK (long, LONG_MAX);
4130 CHECK (long, LONG_MIN);
4131 CHECK (ulong, ULONG_MAX);
4132 CHECK (size, SIZE_MAX);
4133 CHECK (ptrdiff, PTRDIFF_MAX);
4134 CHECK (ptrdiff, PTRDIFF_MIN);
4135
4136 #if SCM_SIZEOF_LONG_LONG != 0
4137 CHECK (long_long, 0LL);
4138 CHECK (ulong_long, 0ULL);
4139 CHECK (long_long, -1LL);
4140 CHECK (long_long, LLONG_MAX);
4141 CHECK (long_long, LLONG_MIN);
4142 CHECK (ulong_long, ULLONG_MAX);
4143 #endif
4144 }
4145
4146 #undef CHECK
4147
4148 #define CHECK \
4149 scm_internal_catch (SCM_BOOL_T, check_body, &data, check_handler, &data); \
4150 if (!SCM_FALSEP (data)) abort();
4151
4152 static SCM
4153 check_body (void *data)
4154 {
4155 SCM num = *(SCM *) data;
4156 scm_num2ulong (num, 1, NULL);
4157
4158 return SCM_UNSPECIFIED;
4159 }
4160
4161 static SCM
4162 check_handler (void *data, SCM tag, SCM throw_args)
4163 {
4164 SCM *num = (SCM *) data;
4165 *num = SCM_BOOL_F;
4166
4167 return SCM_UNSPECIFIED;
4168 }
4169
4170 SCM_DEFINE (scm_sys_check_number_conversions, "%check-number-conversions", 0, 0, 0,
4171 (void),
4172 "Number conversion sanity checking.")
4173 #define FUNC_NAME s_scm_sys_check_number_conversions
4174 {
4175 SCM data = SCM_MAKINUM (-1);
4176 CHECK;
4177 data = scm_int2num (INT_MIN);
4178 CHECK;
4179 data = scm_ulong2num (ULONG_MAX);
4180 data = scm_difference (SCM_INUM0, data);
4181 CHECK;
4182 data = scm_ulong2num (ULONG_MAX);
4183 data = scm_sum (SCM_MAKINUM (1), data); data = scm_difference (SCM_INUM0, data);
4184 CHECK;
4185 data = scm_int2num (-10000); data = scm_product (data, data); data = scm_product (data, data);
4186 CHECK;
4187
4188 return SCM_UNSPECIFIED;
4189 }
4190 #undef FUNC_NAME
4191
4192 #endif
4193
4194 void
4195 scm_init_numbers ()
4196 {
4197 abs_most_negative_fixnum = scm_i_long2big (- SCM_MOST_NEGATIVE_FIXNUM);
4198 scm_permanent_object (abs_most_negative_fixnum);
4199
4200 /* It may be possible to tune the performance of some algorithms by using
4201 * the following constants to avoid the creation of bignums. Please, before
4202 * using these values, remember the two rules of program optimization:
4203 * 1st Rule: Don't do it. 2nd Rule (experts only): Don't do it yet. */
4204 scm_c_define ("most-positive-fixnum",
4205 SCM_MAKINUM (SCM_MOST_POSITIVE_FIXNUM));
4206 scm_c_define ("most-negative-fixnum",
4207 SCM_MAKINUM (SCM_MOST_NEGATIVE_FIXNUM));
4208
4209 scm_add_feature ("complex");
4210 scm_add_feature ("inexact");
4211 scm_flo0 = scm_make_real (0.0);
4212 #ifdef DBL_DIG
4213 scm_dblprec = (DBL_DIG > 20) ? 20 : DBL_DIG;
4214 #else
4215 { /* determine floating point precision */
4216 double f = 0.1;
4217 double fsum = 1.0 + f;
4218 while (fsum != 1.0) {
4219 if (++scm_dblprec > 20) {
4220 fsum = 1.0;
4221 } else {
4222 f /= 10.0;
4223 fsum = f + 1.0;
4224 }
4225 }
4226 scm_dblprec = scm_dblprec - 1;
4227 }
4228 #endif /* DBL_DIG */
4229
4230 #ifdef GUILE_DEBUG
4231 check_sanity ();
4232 #endif
4233
4234 #include "libguile/numbers.x"
4235 }
4236
4237 /*
4238 Local Variables:
4239 c-file-style: "gnu"
4240 End:
4241 */