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