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