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