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