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