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