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