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