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