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