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