Only include root.h where it is actually needed.
[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),
b380b885
MD
1056 "Returns an integer equivalent to\n"
1057 "@code{(inexact->exact (floor (* @var{int} (expt 2 @var{count}))))}.@refill\n\n"
1058 "Example:\n"
1059 "@lisp\n"
1060 "(number->string (ash #b1 3) 2)\n"
a3c8b9fc
MD
1061 " @result{} \"1000\""
1062 "(number->string (ash #b1010 -1) 2)"
1063 " @result{} \"101\""
1064 "@end lisp")
1bbd0b84 1065#define FUNC_NAME s_scm_ash
0f2d19dd 1066{
1bbd0b84 1067 /* GJB:FIXME:: what is going on here? */
f1267706 1068 SCM res = SCM_PACK (SCM_INUM (n));
3b3b36dd 1069 SCM_VALIDATE_INUM (2,cnt);
0f2d19dd 1070#ifdef SCM_BIGDIG
f872b822
MD
1071 if (cnt < 0)
1072 {
1073 res = scm_integer_expt (SCM_MAKINUM (2), SCM_MAKINUM (-SCM_INUM (cnt)));
1074 if (SCM_NFALSEP (scm_negative_p (n)))
1075 return scm_sum (SCM_MAKINUM (-1L),
1076 scm_quotient (scm_sum (SCM_MAKINUM (1L), n), res));
1077 else
1078 return scm_quotient (n, res);
1079 }
1080 else
1081 return scm_product (n, scm_integer_expt (SCM_MAKINUM (2), cnt));
0f2d19dd 1082#else
3b3b36dd 1083 SCM_VALIDATE_INUM (1,n)
f872b822
MD
1084 cnt = SCM_INUM (cnt);
1085 if (cnt < 0)
1086 return SCM_MAKINUM (SCM_SRS (res, -cnt));
1087 res = SCM_MAKINUM (res << cnt);
1088 if (SCM_INUM (res) >> cnt != SCM_INUM (n))
1bbd0b84 1089 scm_num_overflow (FUNC_NAME);
0f2d19dd
JB
1090 return res;
1091#endif
1092}
1bbd0b84 1093#undef FUNC_NAME
0f2d19dd 1094
1bbd0b84 1095/* GJB:FIXME: do not use SCMs as integers! */
a1ec6916 1096SCM_DEFINE (scm_bit_extract, "bit-extract", 3, 0, 0,
1bbd0b84 1097 (SCM n, SCM start, SCM end),
b380b885
MD
1098 "Returns the integer composed of the @var{start} (inclusive) through\n"
1099 "@var{end} (exclusive) bits of @var{n}. The @var{start}th bit becomes\n"
1100 "the 0-th bit in the result.@refill\n\n"
1101 "Example:\n"
1102 "@lisp\n"
1103 "(number->string (bit-extract #b1101101010 0 4) 2)\n"
1104 " @result{} \"1010\"\n"
1105 "(number->string (bit-extract #b1101101010 4 9) 2)\n"
1106 " @result{} \"10110\"\n"
1107 "@end lisp")
1bbd0b84 1108#define FUNC_NAME s_scm_bit_extract
0f2d19dd 1109{
c1bfcf60 1110 int istart, iend;
3b3b36dd 1111 SCM_VALIDATE_INUM (1,n);
c1bfcf60
GB
1112 SCM_VALIDATE_INUM_MIN_COPY (2,start,0,istart);
1113 SCM_VALIDATE_INUM_MIN_COPY (3, end, 0, iend);
1114 SCM_ASSERT_RANGE (3, end, (iend >= istart));
0f2d19dd 1115#ifdef SCM_BIGDIG
f872b822 1116 if (SCM_NINUMP (n))
0f2d19dd 1117 return
f872b822 1118 scm_logand (scm_difference (scm_integer_expt (SCM_MAKINUM (2),
c1bfcf60 1119 SCM_MAKINUM (iend - istart)),
f872b822 1120 SCM_MAKINUM (1L)),
c1bfcf60 1121 scm_ash (n, SCM_MAKINUM (-istart)));
0f2d19dd 1122#else
3b3b36dd 1123 SCM_VALIDATE_INUM (1,n);
0f2d19dd 1124#endif
c1bfcf60 1125 return SCM_MAKINUM ((SCM_INUM (n) >> istart) & ((1L << (iend - istart)) - 1));
0f2d19dd 1126}
1bbd0b84 1127#undef FUNC_NAME
0f2d19dd 1128
e4755e5c
JB
1129static const char scm_logtab[] = {
1130 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
1131};
1cc91f1b 1132
a1ec6916 1133SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
1bbd0b84 1134 (SCM n),
b380b885
MD
1135 "Returns the number of bits in integer @var{n}. If integer is positive,\n"
1136 "the 1-bits in its binary representation are counted. If negative, the\n"
1137 "0-bits in its two's-complement binary representation are counted. If 0,\n"
1138 "0 is returned.\n\n"
1139 "Example:\n"
1140 "@lisp\n"
1141 "(logcount #b10101010)\n"
1142 " @result{} 4\n"
1143 "(logcount 0)\n"
1144 " @result{} 0\n"
1145 "(logcount -2)\n"
1146 " @result{} 1\n"
1147 "@end lisp")
1bbd0b84 1148#define FUNC_NAME s_scm_logcount
0f2d19dd
JB
1149{
1150 register unsigned long c = 0;
1151 register long nn;
1152#ifdef SCM_BIGDIG
f872b822
MD
1153 if (SCM_NINUMP (n))
1154 {
1155 scm_sizet i;
1156 SCM_BIGDIG *ds, d;
3b3b36dd 1157 SCM_VALIDATE_BIGINT (1,n);
f872b822
MD
1158 if (SCM_BIGSIGN (n))
1159 return scm_logcount (scm_difference (SCM_MAKINUM (-1L), n));
1160 ds = SCM_BDIGITS (n);
1161 for (i = SCM_NUMDIGS (n); i--;)
1162 for (d = ds[i]; d; d >>= 4)
1163 c += scm_logtab[15 & d];
1164 return SCM_MAKINUM (c);
1165 }
0f2d19dd 1166#else
3b3b36dd 1167 SCM_VALIDATE_INUM (1,n);
0f2d19dd 1168#endif
f872b822
MD
1169 if ((nn = SCM_INUM (n)) < 0)
1170 nn = -1 - nn;
1171 for (; nn; nn >>= 4)
1172 c += scm_logtab[15 & nn];
1173 return SCM_MAKINUM (c);
0f2d19dd 1174}
1bbd0b84
GB
1175#undef FUNC_NAME
1176
0f2d19dd 1177
e4755e5c
JB
1178static const char scm_ilentab[] = {
1179 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
1180};
1cc91f1b 1181
a1ec6916 1182SCM_DEFINE (scm_integer_length, "integer-length", 1, 0, 0,
1bbd0b84 1183 (SCM n),
b380b885
MD
1184 "Returns the number of bits neccessary to represent @var{n}.\n\n"
1185 "Example:\n"
1186 "@lisp\n"
1187 "(integer-length #b10101010)\n"
1188 " @result{} 8\n"
1189 "(integer-length 0)\n"
1190 " @result{} 0\n"
1191 "(integer-length #b1111)\n"
1192 " @result{} 4\n"
1193 "@end lisp")
1bbd0b84 1194#define FUNC_NAME s_scm_integer_length
0f2d19dd
JB
1195{
1196 register unsigned long c = 0;
1197 register long nn;
1198 unsigned int l = 4;
1199#ifdef SCM_BIGDIG
f872b822
MD
1200 if (SCM_NINUMP (n))
1201 {
1202 SCM_BIGDIG *ds, d;
3b3b36dd 1203 SCM_VALIDATE_BIGINT (1,n);
f872b822
MD
1204 if (SCM_BIGSIGN (n))
1205 return scm_integer_length (scm_difference (SCM_MAKINUM (-1L), n));
1206 ds = SCM_BDIGITS (n);
1207 d = ds[c = SCM_NUMDIGS (n) - 1];
1208 for (c *= SCM_BITSPERDIG; d; d >>= 4)
1209 {
1210 c += 4;
1211 l = scm_ilentab[15 & d];
1212 }
1213 return SCM_MAKINUM (c - 4 + l);
1214 }
0f2d19dd 1215#else
3b3b36dd 1216 SCM_VALIDATE_INUM (1,n);
0f2d19dd 1217#endif
f872b822
MD
1218 if ((nn = SCM_INUM (n)) < 0)
1219 nn = -1 - nn;
1220 for (; nn; nn >>= 4)
1221 {
1222 c += 4;
1223 l = scm_ilentab[15 & nn];
1224 }
1225 return SCM_MAKINUM (c - 4 + l);
0f2d19dd 1226}
1bbd0b84 1227#undef FUNC_NAME
0f2d19dd
JB
1228
1229
1230#ifdef SCM_BIGDIG
e4755e5c 1231static const char s_bignum[] = "bignum";
1cc91f1b 1232
0f2d19dd 1233SCM
1bbd0b84 1234scm_mkbig (scm_sizet nlen, int sign)
0f2d19dd 1235{
c209c88e
GB
1236 SCM v;
1237 /* Cast to long int to avoid signed/unsigned comparison warnings. */
f3ae5d60
MD
1238 if ((( ((long int) nlen) << SCM_BIGSIZEFIELD) >> SCM_BIGSIZEFIELD)
1239 != (long int) nlen)
e4755e5c 1240 scm_wta (SCM_MAKINUM (nlen), (char *) SCM_NALLOC, s_bignum);
c209c88e 1241
f872b822 1242 SCM_NEWCELL (v);
0f2d19dd 1243 SCM_DEFER_INTS;
f872b822 1244 SCM_SETCHARS (v, scm_must_malloc ((long) (nlen * sizeof (SCM_BIGDIG)),
e4755e5c 1245 s_bignum));
f3ae5d60 1246 SCM_SETNUMDIGS (v, nlen, sign);
0f2d19dd
JB
1247 SCM_ALLOW_INTS;
1248 return v;
1249}
1250
1cc91f1b 1251
0f2d19dd 1252SCM
1bbd0b84 1253scm_big2inum (SCM b, scm_sizet l)
0f2d19dd
JB
1254{
1255 unsigned long num = 0;
f872b822
MD
1256 SCM_BIGDIG *tmp = SCM_BDIGITS (b);
1257 while (l--)
1258 num = SCM_BIGUP (num) + tmp[l];
f3ae5d60 1259 if (!SCM_BIGSIGN (b))
f872b822
MD
1260 {
1261 if (SCM_POSFIXABLE (num))
1262 return SCM_MAKINUM (num);
1263 }
1264 else if (SCM_UNEGFIXABLE (num))
1265 return SCM_MAKINUM (-num);
0f2d19dd
JB
1266 return b;
1267}
1268
1269
e4755e5c 1270static const char s_adjbig[] = "scm_adjbig";
1cc91f1b 1271
0f2d19dd 1272SCM
1bbd0b84 1273scm_adjbig (SCM b, scm_sizet nlen)
0f2d19dd 1274{
2bf746cc 1275 scm_sizet nsiz = nlen;
f3ae5d60 1276 if (((nsiz << SCM_BIGSIZEFIELD) >> SCM_BIGSIZEFIELD) != nlen)
f872b822 1277 scm_wta (scm_ulong2num (nsiz), (char *) SCM_NALLOC, s_adjbig);
2bf746cc 1278
0f2d19dd 1279 SCM_DEFER_INTS;
2bf746cc
JB
1280 {
1281 SCM_BIGDIG *digits
1282 = ((SCM_BIGDIG *)
f872b822
MD
1283 scm_must_realloc ((char *) SCM_CHARS (b),
1284 (long) (SCM_NUMDIGS (b) * sizeof (SCM_BIGDIG)),
1285 (long) (nsiz * sizeof (SCM_BIGDIG)), s_adjbig));
2bf746cc
JB
1286
1287 SCM_SETCHARS (b, digits);
f3ae5d60 1288 SCM_SETNUMDIGS (b, nsiz, SCM_BIGSIGN (b));
2bf746cc 1289 }
0f2d19dd
JB
1290 SCM_ALLOW_INTS;
1291 return b;
1292}
1293
1294
1cc91f1b 1295
0f2d19dd 1296SCM
1bbd0b84 1297scm_normbig (SCM b)
0f2d19dd 1298{
f872b822
MD
1299#ifndef _UNICOS
1300 scm_sizet nlen = SCM_NUMDIGS (b);
0f2d19dd 1301#else
f872b822 1302 int nlen = SCM_NUMDIGS (b); /* unsigned nlen breaks on Cray when nlen => 0 */
0f2d19dd 1303#endif
f872b822
MD
1304 SCM_BIGDIG *zds = SCM_BDIGITS (b);
1305 while (nlen-- && !zds[nlen]);
1306 nlen++;
1307 if (nlen * SCM_BITSPERDIG / SCM_CHAR_BIT <= sizeof (SCM))
1308 if (SCM_INUMP (b = scm_big2inum (b, (scm_sizet) nlen)))
1309 return b;
1310 if (SCM_NUMDIGS (b) == nlen)
1311 return b;
1312 return scm_adjbig (b, (scm_sizet) nlen);
0f2d19dd
JB
1313}
1314
1315
1cc91f1b 1316
0f2d19dd 1317SCM
1bbd0b84 1318scm_copybig (SCM b, int sign)
0f2d19dd 1319{
f872b822
MD
1320 scm_sizet i = SCM_NUMDIGS (b);
1321 SCM ans = scm_mkbig (i, sign);
1322 SCM_BIGDIG *src = SCM_BDIGITS (b), *dst = SCM_BDIGITS (ans);
1323 while (i--)
1324 dst[i] = src[i];
0f2d19dd
JB
1325 return ans;
1326}
1327
1328
1cc91f1b 1329
0f2d19dd 1330SCM
1bbd0b84 1331scm_long2big (long n)
0f2d19dd
JB
1332{
1333 scm_sizet i = 0;
1334 SCM_BIGDIG *digits;
f872b822
MD
1335 SCM ans = scm_mkbig (SCM_DIGSPERLONG, n < 0);
1336 digits = SCM_BDIGITS (ans);
1337 if (n < 0)
1338 n = -n;
1339 while (i < SCM_DIGSPERLONG)
1340 {
1341 digits[i++] = SCM_BIGLO (n);
1342 n = SCM_BIGDN ((unsigned long) n);
1343 }
0f2d19dd
JB
1344 return ans;
1345}
1346
5c11cc9d 1347#ifdef HAVE_LONG_LONGS
1cc91f1b 1348
0f2d19dd 1349SCM
1bbd0b84 1350scm_long_long2big (long_long n)
0f2d19dd
JB
1351{
1352 scm_sizet i;
1353 SCM_BIGDIG *digits;
1354 SCM ans;
1355 int n_digits;
1356
1357 {
1358 long tn;
1359 tn = (long) n;
f872b822 1360 if ((long long) tn == n)
0f2d19dd
JB
1361 return scm_long2big (tn);
1362 }
1363
1364 {
1365 long_long tn;
1366
1367 for (tn = n, n_digits = 0;
1368 tn;
f872b822 1369 ++n_digits, tn = SCM_BIGDN ((ulong_long) tn))
0f2d19dd
JB
1370 ;
1371 }
1372
1373 i = 0;
f872b822
MD
1374 ans = scm_mkbig (n_digits, n < 0);
1375 digits = SCM_BDIGITS (ans);
0f2d19dd
JB
1376 if (n < 0)
1377 n = -n;
f872b822
MD
1378 while (i < n_digits)
1379 {
1380 digits[i++] = SCM_BIGLO (n);
1381 n = SCM_BIGDN ((ulong_long) n);
1382 }
0f2d19dd
JB
1383 return ans;
1384}
1385#endif
1386
1cc91f1b 1387
0f2d19dd 1388SCM
1bbd0b84 1389scm_2ulong2big (unsigned long *np)
0f2d19dd
JB
1390{
1391 unsigned long n;
1392 scm_sizet i;
1393 SCM_BIGDIG *digits;
1394 SCM ans;
1395
f872b822
MD
1396 ans = scm_mkbig (2 * SCM_DIGSPERLONG, 0);
1397 digits = SCM_BDIGITS (ans);
0f2d19dd
JB
1398
1399 n = np[0];
1400 for (i = 0; i < SCM_DIGSPERLONG; ++i)
1401 {
f872b822
MD
1402 digits[i] = SCM_BIGLO (n);
1403 n = SCM_BIGDN ((unsigned long) n);
0f2d19dd
JB
1404 }
1405 n = np[1];
1406 for (i = 0; i < SCM_DIGSPERLONG; ++i)
1407 {
f872b822
MD
1408 digits[i + SCM_DIGSPERLONG] = SCM_BIGLO (n);
1409 n = SCM_BIGDN ((unsigned long) n);
0f2d19dd
JB
1410 }
1411 return ans;
1412}
1413
1414
1cc91f1b 1415
0f2d19dd 1416SCM
1bbd0b84 1417scm_ulong2big (unsigned long n)
0f2d19dd
JB
1418{
1419 scm_sizet i = 0;
1420 SCM_BIGDIG *digits;
f872b822
MD
1421 SCM ans = scm_mkbig (SCM_DIGSPERLONG, 0);
1422 digits = SCM_BDIGITS (ans);
1423 while (i < SCM_DIGSPERLONG)
1424 {
1425 digits[i++] = SCM_BIGLO (n);
1426 n = SCM_BIGDN (n);
1427 }
0f2d19dd
JB
1428 return ans;
1429}
1430
1431
1cc91f1b 1432
0f2d19dd 1433int
1bbd0b84 1434scm_bigcomp (SCM x, SCM y)
0f2d19dd 1435{
f872b822
MD
1436 int xsign = SCM_BIGSIGN (x);
1437 int ysign = SCM_BIGSIGN (y);
0f2d19dd 1438 scm_sizet xlen, ylen;
2bf746cc
JB
1439
1440 /* Look at the signs, first. */
f872b822
MD
1441 if (ysign < xsign)
1442 return 1;
1443 if (ysign > xsign)
1444 return -1;
2bf746cc
JB
1445
1446 /* They're the same sign, so see which one has more digits. Note
1447 that, if they are negative, the longer number is the lesser. */
f872b822
MD
1448 ylen = SCM_NUMDIGS (y);
1449 xlen = SCM_NUMDIGS (x);
2bf746cc
JB
1450 if (ylen > xlen)
1451 return (xsign) ? -1 : 1;
f872b822
MD
1452 if (ylen < xlen)
1453 return (xsign) ? 1 : -1;
2bf746cc
JB
1454
1455 /* They have the same number of digits, so find the most significant
1456 digit where they differ. */
1457 while (xlen)
1458 {
1459 --xlen;
1460 if (SCM_BDIGITS (y)[xlen] != SCM_BDIGITS (x)[xlen])
1461 /* Make the discrimination based on the digit that differs. */
f872b822
MD
1462 return ((SCM_BDIGITS (y)[xlen] > SCM_BDIGITS (x)[xlen])
1463 ? (xsign ? -1 : 1)
1464 : (xsign ? 1 : -1));
2bf746cc
JB
1465 }
1466
1467 /* The numbers are identical. */
1468 return 0;
0f2d19dd
JB
1469}
1470
1471#ifndef SCM_DIGSTOOBIG
1472
1cc91f1b 1473
0f2d19dd 1474long
1bbd0b84 1475scm_pseudolong (long x)
0f2d19dd 1476{
f872b822
MD
1477 union
1478 {
0f2d19dd
JB
1479 long l;
1480 SCM_BIGDIG bd[SCM_DIGSPERLONG];
f872b822
MD
1481 }
1482 p;
0f2d19dd 1483 scm_sizet i = 0;
f872b822
MD
1484 if (x < 0)
1485 x = -x;
1486 while (i < SCM_DIGSPERLONG)
1487 {
1488 p.bd[i++] = SCM_BIGLO (x);
1489 x = SCM_BIGDN (x);
1490 }
0f2d19dd
JB
1491 /* p.bd[0] = SCM_BIGLO(x); p.bd[1] = SCM_BIGDN(x); */
1492 return p.l;
1493}
1494
1495#else
1496
1cc91f1b 1497
0f2d19dd 1498void
1bbd0b84 1499scm_longdigs (long x, SCM_BIGDIG digs[])
0f2d19dd
JB
1500{
1501 scm_sizet i = 0;
f872b822
MD
1502 if (x < 0)
1503 x = -x;
1504 while (i < SCM_DIGSPERLONG)
1505 {
1506 digs[i++] = SCM_BIGLO (x);
1507 x = SCM_BIGDN (x);
1508 }
0f2d19dd
JB
1509}
1510#endif
1511
1512
1cc91f1b 1513
0f2d19dd 1514SCM
1bbd0b84 1515scm_addbig (SCM_BIGDIG *x, scm_sizet nx, int xsgn, SCM bigy, int sgny)
0f2d19dd
JB
1516{
1517 /* Assumes nx <= SCM_NUMDIGS(bigy) */
f3ae5d60 1518 /* Assumes xsgn and sgny scm_equal either 0 or SCM_BIGSIGNFLAG */
0f2d19dd 1519 long num = 0;
f872b822
MD
1520 scm_sizet i = 0, ny = SCM_NUMDIGS (bigy);
1521 SCM z = scm_copybig (bigy, SCM_BIGSIGN (bigy) ^ sgny);
1522 SCM_BIGDIG *zds = SCM_BDIGITS (z);
1523 if (xsgn ^ SCM_BIGSIGN (z))
1524 {
1525 do
1526 {
1527 num += (long) zds[i] - x[i];
1528 if (num < 0)
1529 {
1530 zds[i] = num + SCM_BIGRAD;
1531 num = -1;
1532 }
1533 else
1534 {
1535 zds[i] = SCM_BIGLO (num);
1536 num = 0;
1537 }
1538 }
1539 while (++i < nx);
1540 if (num && nx == ny)
1541 {
1542 num = 1;
1543 i = 0;
f3ae5d60 1544 SCM_SETCAR (z, SCM_UNPACK_CAR (z) ^ SCM_BIGSIGNFLAG);
f872b822
MD
1545 do
1546 {
1547 num += (SCM_BIGRAD - 1) - zds[i];
1548 zds[i++] = SCM_BIGLO (num);
1549 num = SCM_BIGDN (num);
1550 }
1551 while (i < ny);
1552 }
1553 else
1554 while (i < ny)
1555 {
1556 num += zds[i];
1557 if (num < 0)
1558 {
1559 zds[i++] = num + SCM_BIGRAD;
1560 num = -1;
1561 }
1562 else
1563 {
1564 zds[i++] = SCM_BIGLO (num);
1565 num = 0;
1566 }
1567 }
1568 }
1569 else
1570 {
1571 do
1572 {
1573 num += (long) zds[i] + x[i];
1574 zds[i++] = SCM_BIGLO (num);
1575 num = SCM_BIGDN (num);
1576 }
1577 while (i < nx);
1578 if (!num)
1579 return z;
1580 while (i < ny)
1581 {
1582 num += zds[i];
1583 zds[i++] = SCM_BIGLO (num);
1584 num = SCM_BIGDN (num);
1585 if (!num)
1586 return z;
1587 }
1588 if (num)
1589 {
1590 z = scm_adjbig (z, ny + 1);
1591 SCM_BDIGITS (z)[ny] = num;
1592 return z;
1593 }
1594 }
1595 return scm_normbig (z);
0f2d19dd
JB
1596}
1597
1cc91f1b 1598
0f2d19dd 1599SCM
1bbd0b84 1600scm_mulbig (SCM_BIGDIG *x, scm_sizet nx, SCM_BIGDIG *y, scm_sizet ny, int sgn)
0f2d19dd
JB
1601{
1602 scm_sizet i = 0, j = nx + ny;
1603 unsigned long n = 0;
f872b822
MD
1604 SCM z = scm_mkbig (j, sgn);
1605 SCM_BIGDIG *zds = SCM_BDIGITS (z);
1606 while (j--)
1607 zds[j] = 0;
1608 do
1609 {
1610 j = 0;
1611 if (x[i])
1612 {
1613 do
1614 {
1615 n += zds[i + j] + ((unsigned long) x[i] * y[j]);
1616 zds[i + j++] = SCM_BIGLO (n);
1617 n = SCM_BIGDN (n);
1618 }
1619 while (j < ny);
1620 if (n)
1621 {
1622 zds[i + j] = n;
1623 n = 0;
1624 }
1625 }
0f2d19dd 1626 }
f872b822
MD
1627 while (++i < nx);
1628 return scm_normbig (z);
0f2d19dd
JB
1629}
1630
1cc91f1b 1631
805df3e8
JB
1632/* Sun's compiler complains about the fact that this function has an
1633 ANSI prototype in numbers.h, but a K&R declaration here, and the
1634 two specify different promotions for the third argument. I'm going
1635 to turn this into an ANSI declaration, and see if anyone complains
1636 about it not being K&R. */
1637
0f2d19dd 1638unsigned int
f872b822
MD
1639scm_divbigdig (SCM_BIGDIG * ds,
1640 scm_sizet h,
1641 SCM_BIGDIG div)
0f2d19dd
JB
1642{
1643 register unsigned long t2 = 0;
f872b822
MD
1644 while (h--)
1645 {
1646 t2 = SCM_BIGUP (t2) + ds[h];
1647 ds[h] = t2 / div;
1648 t2 %= div;
1649 }
0f2d19dd
JB
1650 return t2;
1651}
1652
1653
1cc91f1b 1654
0f2d19dd 1655SCM
1bbd0b84 1656scm_divbigint (SCM x, long z, int sgn, int mode)
0f2d19dd 1657{
f872b822
MD
1658 if (z < 0)
1659 z = -z;
1660 if (z < SCM_BIGRAD)
1661 {
1662 register unsigned long t2 = 0;
1663 register SCM_BIGDIG *ds = SCM_BDIGITS (x);
1664 scm_sizet nd = SCM_NUMDIGS (x);
1665 while (nd--)
1666 t2 = (SCM_BIGUP (t2) + ds[nd]) % z;
1667 if (mode && t2)
1668 t2 = z - t2;
1669 return SCM_MAKINUM (sgn ? -t2 : t2);
1670 }
0f2d19dd
JB
1671 {
1672#ifndef SCM_DIGSTOOBIG
f872b822
MD
1673 unsigned long t2 = scm_pseudolong (z);
1674 return scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
1675 (SCM_BIGDIG *) & t2, SCM_DIGSPERLONG,
1676 sgn, mode);
0f2d19dd
JB
1677#else
1678 SCM_BIGDIG t2[SCM_DIGSPERLONG];
f872b822
MD
1679 scm_longdigs (z, t2);
1680 return scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
1681 t2, SCM_DIGSPERLONG,
1682 sgn, mode);
0f2d19dd
JB
1683#endif
1684 }
1685}
1686
1cc91f1b 1687
0f2d19dd 1688SCM
1bbd0b84 1689scm_divbigbig (SCM_BIGDIG *x, scm_sizet nx, SCM_BIGDIG *y, scm_sizet ny, int sgn, int modes)
0f2d19dd
JB
1690{
1691 /* modes description
f872b822
MD
1692 0 remainder
1693 1 scm_modulo
1694 2 quotient
1695 3 quotient but returns 0 if division is not exact. */
0f2d19dd
JB
1696 scm_sizet i = 0, j = 0;
1697 long num = 0;
1698 unsigned long t2 = 0;
1699 SCM z, newy;
f872b822 1700 SCM_BIGDIG d = 0, qhat, *zds, *yds;
0f2d19dd
JB
1701 /* algorithm requires nx >= ny */
1702 if (nx < ny)
f872b822
MD
1703 switch (modes)
1704 {
1705 case 0: /* remainder -- just return x */
1706 z = scm_mkbig (nx, sgn);
1707 zds = SCM_BDIGITS (z);
1708 do
1709 {
1710 zds[i] = x[i];
1711 }
1712 while (++i < nx);
1713 return z;
1714 case 1: /* scm_modulo -- return y-x */
1715 z = scm_mkbig (ny, sgn);
1716 zds = SCM_BDIGITS (z);
1717 do
1718 {
1719 num += (long) y[i] - x[i];
1720 if (num < 0)
1721 {
1722 zds[i] = num + SCM_BIGRAD;
1723 num = -1;
1724 }
1725 else
1726 {
1727 zds[i] = num;
1728 num = 0;
1729 }
1730 }
1731 while (++i < nx);
1732 while (i < ny)
1733 {
1734 num += y[i];
1735 if (num < 0)
1736 {
1737 zds[i++] = num + SCM_BIGRAD;
1738 num = -1;
1739 }
1740 else
1741 {
1742 zds[i++] = num;
1743 num = 0;
1744 }
1745 }
1746 goto doadj;
1747 case 2:
1748 return SCM_INUM0; /* quotient is zero */
1749 case 3:
1750 return 0; /* the division is not exact */
0f2d19dd 1751 }
f872b822
MD
1752
1753 z = scm_mkbig (nx == ny ? nx + 2 : nx + 1, sgn);
1754 zds = SCM_BDIGITS (z);
1755 if (nx == ny)
1756 zds[nx + 1] = 0;
1757 while (!y[ny - 1])
1758 ny--; /* in case y came in as a psuedolong */
1759 if (y[ny - 1] < (SCM_BIGRAD >> 1))
1760 { /* normalize operands */
1761 d = SCM_BIGRAD / (y[ny - 1] + 1);
1762 newy = scm_mkbig (ny, 0);
1763 yds = SCM_BDIGITS (newy);
1764 while (j < ny)
1765 {
1766 t2 += (unsigned long) y[j] * d;
1767 yds[j++] = SCM_BIGLO (t2);
1768 t2 = SCM_BIGDN (t2);
1769 }
1770 y = yds;
1771 j = 0;
1772 t2 = 0;
1773 while (j < nx)
1774 {
1775 t2 += (unsigned long) x[j] * d;
1776 zds[j++] = SCM_BIGLO (t2);
1777 t2 = SCM_BIGDN (t2);
1778 }
1779 zds[j] = t2;
1780 }
1781 else
1782 {
1783 zds[j = nx] = 0;
1784 while (j--)
1785 zds[j] = x[j];
1786 }
1787 j = nx == ny ? nx + 1 : nx; /* dividend needs more digits than divisor */
1788 do
1789 { /* loop over digits of quotient */
1790 if (zds[j] == y[ny - 1])
1791 qhat = SCM_BIGRAD - 1;
1792 else
1793 qhat = (SCM_BIGUP (zds[j]) + zds[j - 1]) / y[ny - 1];
1794 if (!qhat)
1795 continue;
1796 i = 0;
1797 num = 0;
1798 t2 = 0;
1799 do
1800 { /* multiply and subtract */
1801 t2 += (unsigned long) y[i] * qhat;
1802 num += zds[j - ny + i] - SCM_BIGLO (t2);
1803 if (num < 0)
1804 {
1805 zds[j - ny + i] = num + SCM_BIGRAD;
1806 num = -1;
1807 }
1808 else
1809 {
1810 zds[j - ny + i] = num;
1811 num = 0;
1812 }
1813 t2 = SCM_BIGDN (t2);
1814 }
1815 while (++i < ny);
1816 num += zds[j - ny + i] - t2; /* borrow from high digit; don't update */
1817 while (num)
1818 { /* "add back" required */
1819 i = 0;
1820 num = 0;
1821 qhat--;
1822 do
1823 {
1824 num += (long) zds[j - ny + i] + y[i];
1825 zds[j - ny + i] = SCM_BIGLO (num);
1826 num = SCM_BIGDN (num);
1827 }
1828 while (++i < ny);
1829 num--;
1830 }
1831 if (modes & 2)
1832 zds[j] = qhat;
1833 }
1834 while (--j >= ny);
1835 switch (modes)
1836 {
1837 case 3: /* check that remainder==0 */
1838 for (j = ny; j && !zds[j - 1]; --j);
1839 if (j)
1840 return 0;
1841 case 2: /* move quotient down in z */
1842 j = (nx == ny ? nx + 2 : nx + 1) - ny;
1843 for (i = 0; i < j; i++)
1844 zds[i] = zds[i + ny];
1845 ny = i;
1846 break;
1847 case 1: /* subtract for scm_modulo */
1848 i = 0;
1849 num = 0;
1850 j = 0;
1851 do
1852 {
1853 num += y[i] - zds[i];
1854 j = j | zds[i];
1855 if (num < 0)
1856 {
1857 zds[i] = num + SCM_BIGRAD;
1858 num = -1;
1859 }
1860 else
1861 {
1862 zds[i] = num;
1863 num = 0;
1864 }
1865 }
1866 while (++i < ny);
1867 if (!j)
1868 return SCM_INUM0;
1869 case 0: /* just normalize remainder */
1870 if (d)
1871 scm_divbigdig (zds, ny, d);
1872 }
0f2d19dd 1873 doadj:
f872b822
MD
1874 for (j = ny; j && !zds[j - 1]; --j);
1875 if (j * SCM_BITSPERDIG <= sizeof (SCM) * SCM_CHAR_BIT)
1876 if (SCM_INUMP (z = scm_big2inum (z, j)))
1877 return z;
1878 return scm_adjbig (z, j);
0f2d19dd
JB
1879}
1880#endif
f872b822 1881\f
0f2d19dd
JB
1882
1883
1884
0f2d19dd
JB
1885
1886/*** NUMBERS -> STRINGS ***/
0f2d19dd 1887int scm_dblprec;
e4755e5c 1888static const double fx[] =
f872b822
MD
1889{ 0.0, 5e-1, 5e-2, 5e-3, 5e-4, 5e-5,
1890 5e-6, 5e-7, 5e-8, 5e-9, 5e-10,
1891 5e-11, 5e-12, 5e-13, 5e-14, 5e-15,
1892 5e-16, 5e-17, 5e-18, 5e-19, 5e-20};
0f2d19dd
JB
1893
1894
1895
1cc91f1b 1896
0f2d19dd 1897static scm_sizet
1bbd0b84 1898idbl2str (double f, char *a)
0f2d19dd
JB
1899{
1900 int efmt, dpt, d, i, wp = scm_dblprec;
1901 scm_sizet ch = 0;
1902 int exp = 0;
1903
f872b822
MD
1904 if (f == 0.0)
1905 goto zero; /*{a[0]='0'; a[1]='.'; a[2]='0'; return 3;} */
1906 if (f < 0.0)
1907 {
1908 f = -f;
1909 a[ch++] = '-';
1910 }
1911 else if (f > 0.0);
1912 else
1913 goto funny;
1914 if (IS_INF (f))
1915 {
1916 if (ch == 0)
1917 a[ch++] = '+';
1918 funny:
1919 a[ch++] = '#';
1920 a[ch++] = '.';
1921 a[ch++] = '#';
1922 return ch;
1923 }
1924#ifdef DBL_MIN_10_EXP /* Prevent unnormalized values, as from
1925 make-uniform-vector, from causing infinite loops. */
1926 while (f < 1.0)
1927 {
1928 f *= 10.0;
1929 if (exp-- < DBL_MIN_10_EXP)
1930 goto funny;
1931 }
1932 while (f > 10.0)
1933 {
1934 f *= 0.10;
1935 if (exp++ > DBL_MAX_10_EXP)
1936 goto funny;
1937 }
1938#else
1939 while (f < 1.0)
1940 {
1941 f *= 10.0;
1942 exp--;
1943 }
1944 while (f > 10.0)
1945 {
1946 f /= 10.0;
1947 exp++;
1948 }
1949#endif
1950 if (f + fx[wp] >= 10.0)
1951 {
1952 f = 1.0;
1953 exp++;
1954 }
0f2d19dd 1955 zero:
f872b822
MD
1956#ifdef ENGNOT
1957 dpt = (exp + 9999) % 3;
0f2d19dd
JB
1958 exp -= dpt++;
1959 efmt = 1;
f872b822
MD
1960#else
1961 efmt = (exp < -3) || (exp > wp + 2);
0f2d19dd 1962 if (!efmt)
cda139a7
MD
1963 {
1964 if (exp < 0)
1965 {
1966 a[ch++] = '0';
1967 a[ch++] = '.';
1968 dpt = exp;
f872b822
MD
1969 while (++dpt)
1970 a[ch++] = '0';
cda139a7
MD
1971 }
1972 else
f872b822 1973 dpt = exp + 1;
cda139a7 1974 }
0f2d19dd
JB
1975 else
1976 dpt = 1;
f872b822
MD
1977#endif
1978
1979 do
1980 {
1981 d = f;
1982 f -= d;
1983 a[ch++] = d + '0';
1984 if (f < fx[wp])
1985 break;
1986 if (f + fx[wp] >= 1.0)
1987 {
1988 a[ch - 1]++;
1989 break;
1990 }
1991 f *= 10.0;
1992 if (!(--dpt))
1993 a[ch++] = '.';
0f2d19dd 1994 }
f872b822 1995 while (wp--);
0f2d19dd
JB
1996
1997 if (dpt > 0)
cda139a7 1998 {
f872b822 1999#ifndef ENGNOT
cda139a7
MD
2000 if ((dpt > 4) && (exp > 6))
2001 {
f872b822 2002 d = (a[0] == '-' ? 2 : 1);
cda139a7 2003 for (i = ch++; i > d; i--)
f872b822 2004 a[i] = a[i - 1];
cda139a7
MD
2005 a[d] = '.';
2006 efmt = 1;
2007 }
2008 else
f872b822 2009#endif
cda139a7 2010 {
f872b822
MD
2011 while (--dpt)
2012 a[ch++] = '0';
cda139a7
MD
2013 a[ch++] = '.';
2014 }
2015 }
f872b822
MD
2016 if (a[ch - 1] == '.')
2017 a[ch++] = '0'; /* trailing zero */
2018 if (efmt && exp)
2019 {
2020 a[ch++] = 'e';
2021 if (exp < 0)
2022 {
2023 exp = -exp;
2024 a[ch++] = '-';
2025 }
2026 for (i = 10; i <= exp; i *= 10);
2027 for (i /= 10; i; i /= 10)
2028 {
2029 a[ch++] = exp / i + '0';
2030 exp %= i;
2031 }
0f2d19dd 2032 }
0f2d19dd
JB
2033 return ch;
2034}
2035
1cc91f1b 2036
0f2d19dd 2037static scm_sizet
1bbd0b84 2038iflo2str (SCM flt, char *str)
0f2d19dd
JB
2039{
2040 scm_sizet i;
f3ae5d60
MD
2041 if (SCM_SLOPPY_REALP (flt))
2042 i = idbl2str (SCM_REAL_VALUE (flt), str);
0f2d19dd 2043 else
f872b822 2044 {
f3ae5d60
MD
2045 i = idbl2str (SCM_COMPLEX_REAL (flt), str);
2046 if (SCM_COMPLEX_IMAG (flt) != 0.0)
2047 {
2048 if (0 <= SCM_COMPLEX_IMAG (flt))
2049 str[i++] = '+';
2050 i += idbl2str (SCM_COMPLEX_IMAG (flt), &str[i]);
2051 str[i++] = 'i';
2052 }
f872b822 2053 }
0f2d19dd
JB
2054 return i;
2055}
0f2d19dd 2056
5c11cc9d 2057/* convert a long to a string (unterminated). returns the number of
1bbd0b84
GB
2058 characters in the result.
2059 rad is output base
2060 p is destination: worst case (base 2) is SCM_INTBUFLEN */
0f2d19dd 2061scm_sizet
1bbd0b84 2062scm_iint2str (long num, int rad, char *p)
0f2d19dd 2063{
5c11cc9d
GH
2064 scm_sizet j = 1;
2065 scm_sizet i;
2066 unsigned long n = (num < 0) ? -num : num;
2067
f872b822 2068 for (n /= rad; n > 0; n /= rad)
5c11cc9d
GH
2069 j++;
2070
2071 i = j;
2072 if (num < 0)
f872b822 2073 {
f872b822 2074 *p++ = '-';
5c11cc9d
GH
2075 j++;
2076 n = -num;
f872b822 2077 }
5c11cc9d
GH
2078 else
2079 n = num;
f872b822
MD
2080 while (i--)
2081 {
5c11cc9d
GH
2082 int d = n % rad;
2083
f872b822
MD
2084 n /= rad;
2085 p[i] = d + ((d < 10) ? '0' : 'a' - 10);
2086 }
0f2d19dd
JB
2087 return j;
2088}
2089
2090
2091#ifdef SCM_BIGDIG
1cc91f1b 2092
0f2d19dd 2093static SCM
1bbd0b84 2094big2str (SCM b, unsigned int radix)
0f2d19dd 2095{
f872b822
MD
2096 SCM t = scm_copybig (b, 0); /* sign of temp doesn't matter */
2097 register SCM_BIGDIG *ds = SCM_BDIGITS (t);
2098 scm_sizet i = SCM_NUMDIGS (t);
2099 scm_sizet j = radix == 16 ? (SCM_BITSPERDIG * i) / 4 + 2
2100 : radix >= 10 ? (SCM_BITSPERDIG * i * 241L) / 800 + 2
2101 : (SCM_BITSPERDIG * i) + 2;
0f2d19dd
JB
2102 scm_sizet k = 0;
2103 scm_sizet radct = 0;
2104 scm_sizet ch; /* jeh */
2105 SCM_BIGDIG radpow = 1, radmod = 0;
f872b822
MD
2106 SCM ss = scm_makstr ((long) j, 0);
2107 char *s = SCM_CHARS (ss), c;
2108 while ((long) radpow * radix < SCM_BIGRAD)
2109 {
2110 radpow *= radix;
2111 radct++;
2112 }
f3ae5d60 2113 s[0] = SCM_BIGSIGN (b) ? '-' : '+';
f872b822
MD
2114 while ((i || radmod) && j)
2115 {
2116 if (k == 0)
2117 {
2118 radmod = (SCM_BIGDIG) scm_divbigdig (ds, i, radpow);
2119 k = radct;
2120 if (!ds[i - 1])
2121 i--;
2122 }
2123 c = radmod % radix;
2124 radmod /= radix;
2125 k--;
2126 s[--j] = c < 10 ? c + '0' : c + 'a' - 10;
2127 }
0f2d19dd 2128 ch = s[0] == '-' ? 1 : 0; /* jeh */
f872b822
MD
2129 if (ch < j)
2130 { /* jeh */
2131 for (i = j; j < SCM_LENGTH (ss); j++)
2132 s[ch + j - i] = s[j]; /* jeh */
2133 scm_vector_set_length_x (ss, /* jeh */
2134 (SCM) SCM_MAKINUM (ch + SCM_LENGTH (ss) - i));
2135 }
b098016b
JB
2136
2137 return scm_return_first (ss, t);
0f2d19dd
JB
2138}
2139#endif
2140
2141
a1ec6916 2142SCM_DEFINE (scm_number_to_string, "number->string", 1, 1, 0,
1bbd0b84 2143 (SCM x, SCM radix),
b380b885 2144 "")
1bbd0b84 2145#define FUNC_NAME s_scm_number_to_string
0f2d19dd 2146{
1bbd0b84 2147 int base;
3b3b36dd 2148 SCM_VALIDATE_INUM_MIN_DEF_COPY (2,radix,2,10,base);
f872b822
MD
2149 if (SCM_NINUMP (x))
2150 {
2151 char num_buf[SCM_FLOBUFLEN];
2152#ifdef SCM_BIGDIG
2153 SCM_ASRTGO (SCM_NIMP (x), badx);
2154 if (SCM_BIGP (x))
1bbd0b84 2155 return big2str (x, (unsigned int) base);
f872b822 2156#ifndef SCM_RECKLESS
f3ae5d60 2157 if (!SCM_SLOPPY_INEXACTP (x))
f872b822
MD
2158 {
2159 badx:
4638e087 2160 SCM_WTA (1, x);
f872b822
MD
2161 }
2162#endif
0f2d19dd 2163#else
f3ae5d60 2164 SCM_ASSERT (SCM_SLOPPY_INEXACTP (x),
f872b822 2165 x, SCM_ARG1, s_number_to_string);
0f2d19dd 2166#endif
f872b822
MD
2167 return scm_makfromstr (num_buf, iflo2str (x, num_buf), 0);
2168 }
f872b822
MD
2169 {
2170 char num_buf[SCM_INTBUFLEN];
2171 return scm_makfromstr (num_buf,
2172 scm_iint2str (SCM_INUM (x),
1bbd0b84 2173 base,
f872b822
MD
2174 num_buf),
2175 0);
0f2d19dd
JB
2176 }
2177}
1bbd0b84 2178#undef FUNC_NAME
0f2d19dd
JB
2179
2180
2181/* These print routines are stubbed here so that scm_repl.c doesn't need
f3ae5d60 2182 SCM_BIGDIG conditionals */
1cc91f1b 2183
0f2d19dd 2184int
f3ae5d60 2185scm_print_real (SCM sexp, SCM port, scm_print_state *pstate)
0f2d19dd 2186{
0f2d19dd 2187 char num_buf[SCM_FLOBUFLEN];
f872b822 2188 scm_lfwrite (num_buf, iflo2str (sexp, num_buf), port);
0f2d19dd
JB
2189 return !0;
2190}
2191
f3ae5d60
MD
2192int
2193scm_print_complex (SCM sexp, SCM port, scm_print_state *pstate)
2194{
2195 char num_buf[SCM_FLOBUFLEN];
2196 scm_lfwrite (num_buf, iflo2str (sexp, num_buf), port);
2197 return !0;
2198}
1cc91f1b 2199
0f2d19dd 2200int
1bbd0b84 2201scm_bigprint (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2202{
2203#ifdef SCM_BIGDIG
f872b822
MD
2204 exp = big2str (exp, (unsigned int) 10);
2205 scm_lfwrite (SCM_CHARS (exp), (scm_sizet) SCM_LENGTH (exp), port);
0f2d19dd 2206#else
f872b822 2207 scm_ipruk ("bignum", exp, port);
0f2d19dd
JB
2208#endif
2209 return !0;
2210}
2211/*** END nums->strs ***/
2212
2213/*** STRINGS -> NUMBERS ***/
2a8fecee
JB
2214
2215static SCM
1bbd0b84 2216scm_small_istr2int (char *str, long len, long radix)
2a8fecee
JB
2217{
2218 register long n = 0, ln;
2219 register int c;
2220 register int i = 0;
2221 int lead_neg = 0;
f872b822
MD
2222 if (0 >= len)
2223 return SCM_BOOL_F; /* zero scm_length */
2224 switch (*str)
2225 { /* leading sign */
2226 case '-':
2227 lead_neg = 1;
2228 case '+':
2229 if (++i == len)
2230 return SCM_BOOL_F; /* bad if lone `+' or `-' */
2231 }
2a8fecee 2232
f872b822
MD
2233 do
2234 {
2235 switch (c = str[i++])
2236 {
2237 case DIGITS:
2238 c = c - '0';
2239 goto accumulate;
2240 case 'A':
2241 case 'B':
2242 case 'C':
2243 case 'D':
2244 case 'E':
2245 case 'F':
2246 c = c - 'A' + 10;
2247 goto accumulate;
2248 case 'a':
2249 case 'b':
2250 case 'c':
2251 case 'd':
2252 case 'e':
2253 case 'f':
2254 c = c - 'a' + 10;
2255 accumulate:
2256 if (c >= radix)
2257 return SCM_BOOL_F; /* bad digit for radix */
2258 ln = n;
2259 n = n * radix - c;
2260 /* Negation is a workaround for HP700 cc bug */
2261 if (n > ln || (-n > -SCM_MOST_NEGATIVE_FIXNUM))
2262 goto ovfl;
2263 break;
2264 default:
2265 return SCM_BOOL_F; /* not a digit */
2266 }
2a8fecee 2267 }
f872b822
MD
2268 while (i < len);
2269 if (!lead_neg)
2270 if ((n = -n) > SCM_MOST_POSITIVE_FIXNUM)
2271 goto ovfl;
2272 return SCM_MAKINUM (n);
2a8fecee
JB
2273 ovfl: /* overflow scheme integer */
2274 return SCM_BOOL_F;
2275}
2276
2277
1cc91f1b 2278
0f2d19dd 2279SCM
1bbd0b84 2280scm_istr2int (char *str, long len, long radix)
0f2d19dd
JB
2281{
2282 scm_sizet j;
2283 register scm_sizet k, blen = 1;
2284 scm_sizet i = 0;
2285 int c;
2286 SCM res;
2287 register SCM_BIGDIG *ds;
2288 register unsigned long t2;
2289
f872b822
MD
2290 if (0 >= len)
2291 return SCM_BOOL_F; /* zero scm_length */
2a8fecee
JB
2292
2293 /* Short numbers we parse directly into an int, to avoid the overhead
2294 of creating a bignum. */
2295 if (len < 6)
2296 return scm_small_istr2int (str, len, radix);
2297
f872b822
MD
2298 if (16 == radix)
2299 j = 1 + (4 * len * sizeof (char)) / (SCM_BITSPERDIG);
0f2d19dd 2300 else if (10 <= radix)
f872b822
MD
2301 j = 1 + (84 * len * sizeof (char)) / (SCM_BITSPERDIG * 25);
2302 else
2303 j = 1 + (len * sizeof (char)) / (SCM_BITSPERDIG);
2304 switch (str[0])
2305 { /* leading sign */
2306 case '-':
2307 case '+':
2308 if (++i == (unsigned) len)
2309 return SCM_BOOL_F; /* bad if lone `+' or `-' */
2310 }
2311 res = scm_mkbig (j, '-' == str[0]);
2312 ds = SCM_BDIGITS (res);
2313 for (k = j; k--;)
2314 ds[k] = 0;
2315 do
2316 {
2317 switch (c = str[i++])
2318 {
2319 case DIGITS:
2320 c = c - '0';
2321 goto accumulate;
2322 case 'A':
2323 case 'B':
2324 case 'C':
2325 case 'D':
2326 case 'E':
2327 case 'F':
2328 c = c - 'A' + 10;
2329 goto accumulate;
2330 case 'a':
2331 case 'b':
2332 case 'c':
2333 case 'd':
2334 case 'e':
2335 case 'f':
2336 c = c - 'a' + 10;
2337 accumulate:
2338 if (c >= radix)
2339 return SCM_BOOL_F; /* bad digit for radix */
2340 k = 0;
2341 t2 = c;
2342 moretodo:
2343 while (k < blen)
2344 {
2345/* printf ("k = %d, blen = %d, t2 = %ld, ds[k] = %d\n", k, blen, t2, ds[k]); */
2346 t2 += ds[k] * radix;
2347 ds[k++] = SCM_BIGLO (t2);
2348 t2 = SCM_BIGDN (t2);
2349 }
2350 if (blen > j)
2351 scm_num_overflow ("bignum");
2352 if (t2)
2353 {
2354 blen++;
2355 goto moretodo;
2356 }
2357 break;
2358 default:
2359 return SCM_BOOL_F; /* not a digit */
2360 }
0f2d19dd 2361 }
f872b822
MD
2362 while (i < (unsigned) len);
2363 if (blen * SCM_BITSPERDIG / SCM_CHAR_BIT <= sizeof (SCM))
2364 if (SCM_INUMP (res = scm_big2inum (res, blen)))
2365 return res;
2366 if (j == blen)
2367 return res;
2368 return scm_adjbig (res, blen);
0f2d19dd 2369}
0f2d19dd 2370
0f2d19dd 2371SCM
1bbd0b84 2372scm_istr2flo (char *str, long len, long radix)
0f2d19dd
JB
2373{
2374 register int c, i = 0;
2375 double lead_sgn;
2376 double res = 0.0, tmp = 0.0;
2377 int flg = 0;
2378 int point = 0;
2379 SCM second;
2380
f872b822
MD
2381 if (i >= len)
2382 return SCM_BOOL_F; /* zero scm_length */
0f2d19dd 2383
f872b822
MD
2384 switch (*str)
2385 { /* leading sign */
2386 case '-':
2387 lead_sgn = -1.0;
2388 i++;
2389 break;
2390 case '+':
2391 lead_sgn = 1.0;
2392 i++;
0f2d19dd
JB
2393 break;
2394 default:
f872b822 2395 lead_sgn = 0.0;
0f2d19dd 2396 }
f872b822
MD
2397 if (i == len)
2398 return SCM_BOOL_F; /* bad if lone `+' or `-' */
2399
2400 if (str[i] == 'i' || str[i] == 'I')
2401 { /* handle `+i' and `-i' */
2402 if (lead_sgn == 0.0)
2403 return SCM_BOOL_F; /* must have leading sign */
2404 if (++i < len)
2405 return SCM_BOOL_F; /* `i' not last character */
2406 return scm_makdbl (0.0, lead_sgn);
2407 }
2408 do
2409 { /* check initial digits */
2410 switch (c = str[i])
2411 {
2412 case DIGITS:
2413 c = c - '0';
2414 goto accum1;
2415 case 'D':
2416 case 'E':
2417 case 'F':
2418 if (radix == 10)
2419 goto out1; /* must be exponent */
2420 case 'A':
2421 case 'B':
2422 case 'C':
2423 c = c - 'A' + 10;
2424 goto accum1;
2425 case 'd':
2426 case 'e':
2427 case 'f':
2428 if (radix == 10)
2429 goto out1;
2430 case 'a':
2431 case 'b':
2432 case 'c':
2433 c = c - 'a' + 10;
2434 accum1:
2435 if (c >= radix)
2436 return SCM_BOOL_F; /* bad digit for radix */
2437 res = res * radix + c;
2438 flg = 1; /* res is valid */
2439 break;
2440 default:
2441 goto out1;
2442 }
2443 }
2444 while (++i < len);
0f2d19dd
JB
2445 out1:
2446
2447 /* if true, then we did see a digit above, and res is valid */
f872b822
MD
2448 if (i == len)
2449 goto done;
0f2d19dd
JB
2450
2451 /* By here, must have seen a digit,
2452 or must have next char be a `.' with radix==10 */
2453 if (!flg)
f872b822 2454 if (!(str[i] == '.' && radix == 10))
0f2d19dd
JB
2455 return SCM_BOOL_F;
2456
f872b822
MD
2457 while (str[i] == '#')
2458 { /* optional sharps */
2459 res *= radix;
2460 if (++i == len)
2461 goto done;
0f2d19dd 2462 }
0f2d19dd 2463
f872b822
MD
2464 if (str[i] == '/')
2465 {
2466 while (++i < len)
2467 {
2468 switch (c = str[i])
2469 {
2470 case DIGITS:
2471 c = c - '0';
2472 goto accum2;
2473 case 'A':
2474 case 'B':
2475 case 'C':
2476 case 'D':
2477 case 'E':
2478 case 'F':
2479 c = c - 'A' + 10;
2480 goto accum2;
2481 case 'a':
2482 case 'b':
2483 case 'c':
2484 case 'd':
2485 case 'e':
2486 case 'f':
2487 c = c - 'a' + 10;
2488 accum2:
2489 if (c >= radix)
2490 return SCM_BOOL_F;
2491 tmp = tmp * radix + c;
2492 break;
2493 default:
2494 goto out2;
2495 }
2496 }
2497 out2:
2498 if (tmp == 0.0)
2499 return SCM_BOOL_F; /* `slash zero' not allowed */
2500 if (i < len)
2501 while (str[i] == '#')
2502 { /* optional sharps */
2503 tmp *= radix;
2504 if (++i == len)
2505 break;
2506 }
2507 res /= tmp;
2508 goto done;
0f2d19dd 2509 }
f872b822
MD
2510
2511 if (str[i] == '.')
2512 { /* decimal point notation */
2513 if (radix != 10)
2514 return SCM_BOOL_F; /* must be radix 10 */
2515 while (++i < len)
2516 {
2517 switch (c = str[i])
2518 {
2519 case DIGITS:
2520 point--;
2521 res = res * 10.0 + c - '0';
2522 flg = 1;
2523 break;
2524 default:
2525 goto out3;
2526 }
2527 }
2528 out3:
2529 if (!flg)
2530 return SCM_BOOL_F; /* no digits before or after decimal point */
2531 if (i == len)
2532 goto adjust;
2533 while (str[i] == '#')
2534 { /* ignore remaining sharps */
2535 if (++i == len)
2536 goto adjust;
2537 }
0f2d19dd 2538 }
0f2d19dd 2539
f872b822
MD
2540 switch (str[i])
2541 { /* exponent */
2542 case 'd':
2543 case 'D':
2544 case 'e':
2545 case 'E':
2546 case 'f':
2547 case 'F':
2548 case 'l':
2549 case 'L':
2550 case 's':
2551 case 'S':
2552 {
2553 int expsgn = 1, expon = 0;
2554 if (radix != 10)
2555 return SCM_BOOL_F; /* only in radix 10 */
2556 if (++i == len)
2557 return SCM_BOOL_F; /* bad exponent */
2558 switch (str[i])
2559 {
2560 case '-':
2561 expsgn = (-1);
2562 case '+':
2563 if (++i == len)
2564 return SCM_BOOL_F; /* bad exponent */
2565 }
2566 if (str[i] < '0' || str[i] > '9')
2567 return SCM_BOOL_F; /* bad exponent */
2568 do
2569 {
2570 switch (c = str[i])
2571 {
2572 case DIGITS:
2573 expon = expon * 10 + c - '0';
f3ae5d60 2574 if (expon > SCM_MAXEXP)
f872b822
MD
2575 return SCM_BOOL_F; /* exponent too large */
2576 break;
2577 default:
2578 goto out4;
2579 }
2580 }
2581 while (++i < len);
2582 out4:
2583 point += expsgn * expon;
0f2d19dd 2584 }
f872b822 2585 }
0f2d19dd
JB
2586
2587 adjust:
2588 if (point >= 0)
f872b822
MD
2589 while (point--)
2590 res *= 10.0;
0f2d19dd 2591 else
f872b822
MD
2592#ifdef _UNICOS
2593 while (point++)
2594 res *= 0.1;
2595#else
2596 while (point++)
2597 res /= 10.0;
2598#endif
0f2d19dd
JB
2599
2600 done:
2601 /* at this point, we have a legitimate floating point result */
f872b822
MD
2602 if (lead_sgn == -1.0)
2603 res = -res;
2604 if (i == len)
2605 return scm_makdbl (res, 0.0);
2606
2607 if (str[i] == 'i' || str[i] == 'I')
2608 { /* pure imaginary number */
2609 if (lead_sgn == 0.0)
2610 return SCM_BOOL_F; /* must have leading sign */
2611 if (++i < len)
2612 return SCM_BOOL_F; /* `i' not last character */
2613 return scm_makdbl (0.0, res);
2614 }
0f2d19dd 2615
f872b822
MD
2616 switch (str[i++])
2617 {
2618 case '-':
2619 lead_sgn = -1.0;
2620 break;
2621 case '+':
2622 lead_sgn = 1.0;
2623 break;
2624 case '@':
2625 { /* polar input for complex number */
2626 /* get a `real' for scm_angle */
2627 second = scm_istr2flo (&str[i], (long) (len - i), radix);
f3ae5d60 2628 if (!SCM_SLOPPY_INEXACTP (second))
f872b822 2629 return SCM_BOOL_F; /* not `real' */
f3ae5d60 2630 if (SCM_SLOPPY_COMPLEXP (second))
f872b822
MD
2631 return SCM_BOOL_F; /* not `real' */
2632 tmp = SCM_REALPART (second);
2633 return scm_makdbl (res * cos (tmp), res * sin (tmp));
2634 }
2635 default:
2636 return SCM_BOOL_F;
2637 }
0f2d19dd
JB
2638
2639 /* at this point, last char must be `i' */
f872b822
MD
2640 if (str[len - 1] != 'i' && str[len - 1] != 'I')
2641 return SCM_BOOL_F;
0f2d19dd 2642 /* handles `x+i' and `x-i' */
f872b822
MD
2643 if (i == (len - 1))
2644 return scm_makdbl (res, lead_sgn);
0f2d19dd 2645 /* get a `ureal' for complex part */
f872b822 2646 second = scm_istr2flo (&str[i], (long) ((len - i) - 1), radix);
f3ae5d60 2647 if (!SCM_INEXACTP (second))
f872b822 2648 return SCM_BOOL_F; /* not `ureal' */
f3ae5d60 2649 if (SCM_SLOPPY_COMPLEXP (second))
f872b822
MD
2650 return SCM_BOOL_F; /* not `ureal' */
2651 tmp = SCM_REALPART (second);
2652 if (tmp < 0.0)
2653 return SCM_BOOL_F; /* not `ureal' */
2654 return scm_makdbl (res, (lead_sgn * tmp));
0f2d19dd 2655}
0f2d19dd
JB
2656
2657
1cc91f1b 2658
0f2d19dd 2659SCM
1bbd0b84 2660scm_istring2number (char *str, long len, long radix)
0f2d19dd
JB
2661{
2662 int i = 0;
2663 char ex = 0;
2664 char ex_p = 0, rx_p = 0; /* Only allow 1 exactness and 1 radix prefix */
2665 SCM res;
f872b822
MD
2666 if (len == 1)
2667 if (*str == '+' || *str == '-') /* Catches lone `+' and `-' for speed */
0f2d19dd
JB
2668 return SCM_BOOL_F;
2669
f872b822
MD
2670 while ((len - i) >= 2 && str[i] == '#' && ++i)
2671 switch (str[i++])
2672 {
2673 case 'b':
2674 case 'B':
2675 if (rx_p++)
2676 return SCM_BOOL_F;
2677 radix = 2;
2678 break;
2679 case 'o':
2680 case 'O':
2681 if (rx_p++)
2682 return SCM_BOOL_F;
2683 radix = 8;
2684 break;
2685 case 'd':
2686 case 'D':
2687 if (rx_p++)
2688 return SCM_BOOL_F;
2689 radix = 10;
2690 break;
2691 case 'x':
2692 case 'X':
2693 if (rx_p++)
2694 return SCM_BOOL_F;
2695 radix = 16;
2696 break;
2697 case 'i':
2698 case 'I':
2699 if (ex_p++)
2700 return SCM_BOOL_F;
2701 ex = 2;
2702 break;
2703 case 'e':
2704 case 'E':
2705 if (ex_p++)
2706 return SCM_BOOL_F;
2707 ex = 1;
2708 break;
2709 default:
2710 return SCM_BOOL_F;
2711 }
2712
2713 switch (ex)
2714 {
2715 case 1:
2716 return scm_istr2int (&str[i], len - i, radix);
2717 case 0:
2718 res = scm_istr2int (&str[i], len - i, radix);
2719 if (SCM_NFALSEP (res))
2720 return res;
f872b822
MD
2721 case 2:
2722 return scm_istr2flo (&str[i], len - i, radix);
f872b822 2723 }
0f2d19dd
JB
2724 return SCM_BOOL_F;
2725}
2726
2727
a1ec6916 2728SCM_DEFINE (scm_string_to_number, "string->number", 1, 1, 0,
1bbd0b84 2729 (SCM str, SCM radix),
b380b885 2730 "")
1bbd0b84 2731#define FUNC_NAME s_scm_string_to_number
0f2d19dd
JB
2732{
2733 SCM answer;
1bbd0b84 2734 int base;
3b3b36dd
GB
2735 SCM_VALIDATE_ROSTRING (1,str);
2736 SCM_VALIDATE_INUM_MIN_DEF_COPY (2,radix,2,10,base);
f872b822
MD
2737 answer = scm_istring2number (SCM_ROCHARS (str),
2738 SCM_ROLENGTH (str),
1bbd0b84 2739 base);
0f2d19dd
JB
2740 return scm_return_first (answer, str);
2741}
1bbd0b84 2742#undef FUNC_NAME
0f2d19dd
JB
2743/*** END strs->nums ***/
2744
0f2d19dd 2745SCM
f3ae5d60 2746scm_make_real (double x)
0f2d19dd
JB
2747{
2748 SCM z;
f3ae5d60 2749 SCM_NEWREAL (z, x);
0f2d19dd
JB
2750 return z;
2751}
0f2d19dd 2752
f3ae5d60
MD
2753SCM
2754scm_make_complex (double x, double y)
2755{
2756 SCM z;
2757 SCM_NEWCOMPLEX (z, x, y);
2758 return z;
2759}
1cc91f1b 2760
0f2d19dd 2761SCM
1bbd0b84 2762scm_bigequal (SCM x, SCM y)
0f2d19dd
JB
2763{
2764#ifdef SCM_BIGDIG
f872b822
MD
2765 if (0 == scm_bigcomp (x, y))
2766 return SCM_BOOL_T;
0f2d19dd
JB
2767#endif
2768 return SCM_BOOL_F;
2769}
2770
0f2d19dd 2771SCM
f3ae5d60 2772scm_real_equalp (SCM x, SCM y)
0f2d19dd 2773{
f3ae5d60 2774 return SCM_BOOL (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
0f2d19dd
JB
2775}
2776
f3ae5d60
MD
2777SCM
2778scm_complex_equalp (SCM x, SCM y)
2779{
2780 return SCM_BOOL (SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y)
2781 && SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y));
2782}
0f2d19dd
JB
2783
2784
2785
1bbd0b84 2786SCM_REGISTER_PROC (s_number_p, "number?", 1, 0, 0, scm_number_p);
1cc91f1b 2787
a1ec6916 2788SCM_DEFINE (scm_number_p, "complex?", 1, 0, 0,
1bbd0b84 2789 (SCM x),
b380b885 2790 "")
1bbd0b84 2791#define FUNC_NAME s_scm_number_p
0f2d19dd 2792{
f872b822
MD
2793 if (SCM_INUMP (x))
2794 return SCM_BOOL_T;
0c95b57d 2795 if (SCM_NUMP (x))
f872b822 2796 return SCM_BOOL_T;
0f2d19dd
JB
2797 return SCM_BOOL_F;
2798}
1bbd0b84 2799#undef FUNC_NAME
0f2d19dd
JB
2800
2801
2802
1bbd0b84 2803SCM_REGISTER_PROC (s_real_p, "real?", 1, 0, 0, scm_real_p);
1cc91f1b 2804
1bbd0b84 2805
a1ec6916 2806SCM_DEFINE (scm_real_p, "rational?", 1, 0, 0,
1bbd0b84 2807 (SCM x),
b380b885 2808 "")
1bbd0b84 2809#define FUNC_NAME s_scm_real_p
0f2d19dd 2810{
f872b822 2811 if (SCM_INUMP (x))
0f2d19dd 2812 return SCM_BOOL_T;
f872b822 2813 if (SCM_IMP (x))
0f2d19dd 2814 return SCM_BOOL_F;
f3ae5d60 2815 if (SCM_SLOPPY_REALP (x))
0f2d19dd 2816 return SCM_BOOL_T;
f872b822
MD
2817#ifdef SCM_BIGDIG
2818 if (SCM_BIGP (x))
0f2d19dd 2819 return SCM_BOOL_T;
f872b822 2820#endif
0f2d19dd
JB
2821 return SCM_BOOL_F;
2822}
1bbd0b84 2823#undef FUNC_NAME
0f2d19dd
JB
2824
2825
2826
a1ec6916 2827SCM_DEFINE (scm_integer_p, "integer?", 1, 0, 0,
1bbd0b84 2828 (SCM x),
b380b885 2829 "")
1bbd0b84 2830#define FUNC_NAME s_scm_integer_p
0f2d19dd
JB
2831{
2832 double r;
f872b822
MD
2833 if (SCM_INUMP (x))
2834 return SCM_BOOL_T;
2835 if (SCM_IMP (x))
2836 return SCM_BOOL_F;
2837#ifdef SCM_BIGDIG
2838 if (SCM_BIGP (x))
2839 return SCM_BOOL_T;
2840#endif
f3ae5d60 2841 if (!SCM_SLOPPY_INEXACTP (x))
f872b822 2842 return SCM_BOOL_F;
f3ae5d60 2843 if (SCM_SLOPPY_COMPLEXP (x))
f872b822
MD
2844 return SCM_BOOL_F;
2845 r = SCM_REALPART (x);
2846 if (r == floor (r))
2847 return SCM_BOOL_T;
0f2d19dd
JB
2848 return SCM_BOOL_F;
2849}
1bbd0b84 2850#undef FUNC_NAME
0f2d19dd
JB
2851
2852
2853
a1ec6916 2854SCM_DEFINE (scm_inexact_p, "inexact?", 1, 0, 0,
1bbd0b84 2855 (SCM x),
b380b885 2856 "")
1bbd0b84 2857#define FUNC_NAME s_scm_inexact_p
0f2d19dd 2858{
f3ae5d60 2859 if (SCM_INEXACTP (x))
f872b822 2860 return SCM_BOOL_T;
0f2d19dd
JB
2861 return SCM_BOOL_F;
2862}
1bbd0b84 2863#undef FUNC_NAME
0f2d19dd
JB
2864
2865
2866
2867
152f82bf 2868SCM_GPROC1 (s_eq_p, "=", scm_tc7_rpsubr, scm_num_eq_p, g_eq_p);
1cc91f1b 2869
0f2d19dd 2870SCM
6e8d25a6 2871scm_num_eq_p (SCM x, SCM y)
0f2d19dd 2872{
0f2d19dd 2873 SCM t;
f872b822
MD
2874 if (SCM_NINUMP (x))
2875 {
2876#ifdef SCM_BIGDIG
0c95b57d 2877 if (!SCM_NIMP (x))
f872b822
MD
2878 {
2879 badx:
152f82bf 2880 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARG1, s_eq_p);
f872b822 2881 }
f872b822
MD
2882 if (SCM_BIGP (x))
2883 {
2884 if (SCM_INUMP (y))
2885 return SCM_BOOL_F;
2886 SCM_ASRTGO (SCM_NIMP (y), bady);
2887 if (SCM_BIGP (y))
156dcb09 2888 return SCM_BOOL(0 == scm_bigcomp (x, y));
f3ae5d60 2889 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822 2890 bigreal:
f3ae5d60 2891 return ((SCM_SLOPPY_REALP (y) && (scm_big2dbl (x) == SCM_REALPART (y)))
f872b822
MD
2892 ? SCM_BOOL_T
2893 : SCM_BOOL_F);
2894 }
f3ae5d60 2895 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x), badx);
0f2d19dd 2896#else
f3ae5d60 2897 SCM_GASSERT2 (SCM_SLOPPY_INEXACTP (x),
152f82bf 2898 g_eq_p, x, y, SCM_ARG1, s_eq_p);
f872b822
MD
2899#endif
2900 if (SCM_INUMP (y))
2901 {
2902 t = x;
2903 x = y;
2904 y = t;
2905 goto realint;
2906 }
2907#ifdef SCM_BIGDIG
2908 SCM_ASRTGO (SCM_NIMP (y), bady);
2909 if (SCM_BIGP (y))
2910 {
2911 t = x;
2912 x = y;
2913 y = t;
2914 goto bigreal;
2915 }
f3ae5d60 2916 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822 2917#else
f3ae5d60 2918 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822 2919#endif
f3ae5d60
MD
2920 if (SCM_SLOPPY_REALP (x))
2921 {
2922 if (SCM_SLOPPY_REALP (y))
2923 return SCM_BOOL (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
2924 else
2925 return SCM_BOOL (SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y)
2926 && 0.0 == SCM_COMPLEX_IMAG (y));
2927 }
2928 else
2929 {
2930 if (SCM_SLOPPY_REALP (y))
2931 return SCM_BOOL (SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y)
2932 && SCM_COMPLEX_IMAG (x) == 0.0);
2933 else
2934 return SCM_BOOL (SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y)
2935 && SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y));
2936 }
f872b822
MD
2937 }
2938 if (SCM_NINUMP (y))
2939 {
2940#ifdef SCM_BIGDIG
2941 SCM_ASRTGO (SCM_NIMP (y), bady);
2942 if (SCM_BIGP (y))
2943 return SCM_BOOL_F;
f3ae5d60 2944 if (!SCM_SLOPPY_INEXACTP (y))
f872b822
MD
2945 {
2946 bady:
152f82bf 2947 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
f872b822 2948 }
f872b822 2949#else
f3ae5d60 2950 if (!SCM_SLOPPY_INEXACTP (y))
f872b822
MD
2951 {
2952 bady:
152f82bf 2953 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
f872b822 2954 }
f872b822
MD
2955#endif
2956 realint:
f3ae5d60
MD
2957 if (SCM_SLOPPY_REALP (y))
2958 return SCM_BOOL ((double) SCM_INUM (x) == SCM_REAL_VALUE (y));
2959 else
2960 return SCM_BOOL ((double) SCM_INUM (x) == SCM_COMPLEX_REAL (y)
2961 && 0.0 == SCM_COMPLEX_IMAG (y));
f872b822 2962 }
156dcb09 2963 return SCM_BOOL((long) x == (long) y);
0f2d19dd
JB
2964}
2965
2966
2967
152f82bf 2968SCM_GPROC1 (s_less_p, "<", scm_tc7_rpsubr, scm_less_p, g_less_p);
1cc91f1b 2969
0f2d19dd 2970SCM
6e8d25a6 2971scm_less_p (SCM x, SCM y)
0f2d19dd 2972{
f872b822
MD
2973 if (SCM_NINUMP (x))
2974 {
2975#ifdef SCM_BIGDIG
0c95b57d 2976 if (!SCM_NIMP (x))
f872b822
MD
2977 {
2978 badx:
152f82bf 2979 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARG1, s_less_p);
f872b822 2980 }
f872b822
MD
2981 if (SCM_BIGP (x))
2982 {
2983 if (SCM_INUMP (y))
156dcb09 2984 return SCM_BOOL(SCM_BIGSIGN (x));
f872b822
MD
2985 SCM_ASRTGO (SCM_NIMP (y), bady);
2986 if (SCM_BIGP (y))
156dcb09 2987 return SCM_BOOL(1 == scm_bigcomp (x, y));
f3ae5d60 2988 SCM_ASRTGO (SCM_SLOPPY_REALP (y), bady);
f872b822
MD
2989 return ((scm_big2dbl (x) < SCM_REALPART (y))
2990 ? SCM_BOOL_T
2991 : SCM_BOOL_F);
2992 }
f3ae5d60 2993 SCM_ASRTGO (SCM_SLOPPY_REALP (x), badx);
0f2d19dd 2994#else
f3ae5d60 2995 SCM_GASSERT2 (SCM_SLOPPY_REALP (x),
152f82bf 2996 g_less_p, x, y, SCM_ARG1, s_less_p);
f872b822
MD
2997#endif
2998 if (SCM_INUMP (y))
2999 return ((SCM_REALPART (x) < ((double) SCM_INUM (y)))
3000 ? SCM_BOOL_T
3001 : SCM_BOOL_F);
3002#ifdef SCM_BIGDIG
3003 SCM_ASRTGO (SCM_NIMP (y), bady);
3004 if (SCM_BIGP (y))
156dcb09 3005 return SCM_BOOL(SCM_REALPART (x) < scm_big2dbl (y));
f3ae5d60 3006 SCM_ASRTGO (SCM_SLOPPY_REALP (y), bady);
f872b822 3007#else
f3ae5d60 3008 SCM_ASRTGO (SCM_SLOPPY_REALP (y), bady);
f872b822 3009#endif
156dcb09 3010 return SCM_BOOL(SCM_REALPART (x) < SCM_REALPART (y));
f872b822
MD
3011 }
3012 if (SCM_NINUMP (y))
3013 {
3014#ifdef SCM_BIGDIG
3015 SCM_ASRTGO (SCM_NIMP (y), bady);
3016 if (SCM_BIGP (y))
156dcb09 3017 return SCM_NEGATE_BOOL(SCM_BIGSIGN (y));
f3ae5d60 3018 if (!SCM_SLOPPY_REALP (y))
f872b822
MD
3019 {
3020 bady:
152f82bf 3021 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
f872b822 3022 }
f872b822 3023#else
f3ae5d60 3024 if (!SCM_SLOPPY_REALP (y))
f872b822
MD
3025 {
3026 bady:
152f82bf 3027 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
f872b822 3028 }
f872b822
MD
3029#endif
3030 return ((((double) SCM_INUM (x)) < SCM_REALPART (y))
3031 ? SCM_BOOL_T
3032 : SCM_BOOL_F);
3033 }
156dcb09 3034 return SCM_BOOL((long) x < (long) y);
0f2d19dd
JB
3035}
3036
3037
c3ee7520 3038SCM_DEFINE1 (scm_gr_p, ">", scm_tc7_rpsubr,
1bbd0b84 3039 (SCM x, SCM y),
b380b885 3040 "")
1bbd0b84 3041#define FUNC_NAME s_scm_gr_p
0f2d19dd 3042{
f872b822 3043 return scm_less_p (y, x);
0f2d19dd 3044}
1bbd0b84 3045#undef FUNC_NAME
0f2d19dd
JB
3046
3047
3048
c3ee7520 3049SCM_DEFINE1 (scm_leq_p, "<=", scm_tc7_rpsubr,
1bbd0b84 3050 (SCM x, SCM y),
b380b885 3051 "")
1bbd0b84 3052#define FUNC_NAME s_scm_leq_p
0f2d19dd 3053{
f872b822 3054 return SCM_BOOL_NOT (scm_less_p (y, x));
0f2d19dd 3055}
1bbd0b84 3056#undef FUNC_NAME
0f2d19dd
JB
3057
3058
3059
c3ee7520 3060SCM_DEFINE1 (scm_geq_p, ">=", scm_tc7_rpsubr,
1bbd0b84 3061 (SCM x, SCM y),
b380b885 3062 "")
1bbd0b84 3063#define FUNC_NAME s_scm_geq_p
0f2d19dd 3064{
f872b822 3065 return SCM_BOOL_NOT (scm_less_p (x, y));
0f2d19dd 3066}
1bbd0b84 3067#undef FUNC_NAME
0f2d19dd
JB
3068
3069
3070
152f82bf 3071SCM_GPROC (s_zero_p, "zero?", 1, 0, 0, scm_zero_p, g_zero_p);
1cc91f1b 3072
0f2d19dd 3073SCM
6e8d25a6 3074scm_zero_p (SCM z)
0f2d19dd 3075{
f872b822
MD
3076 if (SCM_NINUMP (z))
3077 {
3078#ifdef SCM_BIGDIG
3079 SCM_ASRTGO (SCM_NIMP (z), badz);
3080 if (SCM_BIGP (z))
3081 return SCM_BOOL_F;
f3ae5d60 3082 if (!SCM_SLOPPY_INEXACTP (z))
f872b822
MD
3083 {
3084 badz:
152f82bf 3085 SCM_WTA_DISPATCH_1 (g_zero_p, z, SCM_ARG1, s_zero_p);
f872b822 3086 }
0f2d19dd 3087#else
f3ae5d60 3088 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z),
152f82bf 3089 g_zero_p, z, SCM_ARG1, s_zero_p);
f872b822 3090#endif
f3ae5d60
MD
3091 if (SCM_SLOPPY_REALP (z))
3092 return SCM_BOOL (SCM_REAL_VALUE (z) == 0.0);
3093 else
3094 return SCM_BOOL (SCM_COMPLEX_REAL (z) == 0.0
3095 && SCM_COMPLEX_IMAG (z) == 0.0);
f872b822 3096 }
156dcb09 3097 return SCM_BOOL(z == SCM_INUM0);
0f2d19dd
JB
3098}
3099
3100
3101
152f82bf 3102SCM_GPROC (s_positive_p, "positive?", 1, 0, 0, scm_positive_p, g_positive_p);
1cc91f1b 3103
0f2d19dd 3104SCM
6e8d25a6 3105scm_positive_p (SCM x)
0f2d19dd 3106{
f872b822
MD
3107 if (SCM_NINUMP (x))
3108 {
3109#ifdef SCM_BIGDIG
3110 SCM_ASRTGO (SCM_NIMP (x), badx);
3111 if (SCM_BIGP (x))
f3ae5d60
MD
3112 return SCM_BOOL (!SCM_BIGSIGN (x));
3113 if (!SCM_SLOPPY_REALP (x))
f872b822
MD
3114 {
3115 badx:
152f82bf 3116 SCM_WTA_DISPATCH_1 (g_positive_p, x, SCM_ARG1, s_positive_p);
f872b822 3117 }
0f2d19dd 3118#else
f3ae5d60 3119 SCM_GASSERT1 (SCM_SLOPPY_REALP (x),
152f82bf 3120 g_positive_p, x, SCM_ARG1, s_positive_p);
f872b822 3121#endif
156dcb09 3122 return SCM_BOOL(SCM_REALPART (x) > 0.0);
f872b822 3123 }
c209c88e 3124 return SCM_BOOL(SCM_INUM(x) > 0);
0f2d19dd
JB
3125}
3126
3127
3128
152f82bf 3129SCM_GPROC (s_negative_p, "negative?", 1, 0, 0, scm_negative_p, g_negative_p);
1cc91f1b 3130
0f2d19dd 3131SCM
6e8d25a6 3132scm_negative_p (SCM x)
0f2d19dd 3133{
f872b822
MD
3134 if (SCM_NINUMP (x))
3135 {
3136#ifdef SCM_BIGDIG
3137 SCM_ASRTGO (SCM_NIMP (x), badx);
3138 if (SCM_BIGP (x))
f3ae5d60
MD
3139 return SCM_BOOL (SCM_BIGSIGN (x));
3140 if (!(SCM_SLOPPY_REALP (x)))
f872b822
MD
3141 {
3142 badx:
152f82bf 3143 SCM_WTA_DISPATCH_1 (g_negative_p, x, SCM_ARG1, s_negative_p);
f872b822 3144 }
0f2d19dd 3145#else
f3ae5d60 3146 SCM_GASSERT1 (SCM_SLOPPY_REALP (x),
152f82bf 3147 g_negative_p, x, SCM_ARG1, s_negative_p);
0f2d19dd 3148#endif
156dcb09 3149 return SCM_BOOL(SCM_REALPART (x) < 0.0);
f872b822 3150 }
c209c88e 3151 return SCM_BOOL(SCM_INUM(x) < 0);
0f2d19dd
JB
3152}
3153
3154
9de33deb 3155SCM_GPROC1 (s_max, "max", scm_tc7_asubr, scm_max, g_max);
1cc91f1b 3156
0f2d19dd 3157SCM
6e8d25a6 3158scm_max (SCM x, SCM y)
0f2d19dd 3159{
0f2d19dd 3160 double z;
f872b822
MD
3161 if (SCM_UNBNDP (y))
3162 {
73ef98d6
MD
3163 SCM_GASSERT0 (!SCM_UNBNDP (x),
3164 g_max, scm_makfrom0str (s_max), SCM_WNA, 0);
0e3aa89f 3165 SCM_GASSERT1 (SCM_NUMBERP (x), g_max, x, SCM_ARG1, s_max);
f872b822
MD
3166 return x;
3167 }
f872b822
MD
3168 if (SCM_NINUMP (x))
3169 {
3170#ifdef SCM_BIGDIG
0e3aa89f
MD
3171 if (!SCM_NIMP (x))
3172 {
3173 badx2:
3174 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARG1, s_max);
3175 }
f872b822
MD
3176 if (SCM_BIGP (x))
3177 {
3178 if (SCM_INUMP (y))
3179 return SCM_BIGSIGN (x) ? y : x;
3180 SCM_ASRTGO (SCM_NIMP (y), bady);
3181 if (SCM_BIGP (y))
3182 return (1 == scm_bigcomp (x, y)) ? y : x;
f3ae5d60 3183 SCM_ASRTGO (SCM_SLOPPY_REALP (y), bady);
f872b822
MD
3184 z = scm_big2dbl (x);
3185 return (z < SCM_REALPART (y)) ? y : scm_makdbl (z, 0.0);
3186 }
f3ae5d60 3187 SCM_ASRTGO (SCM_SLOPPY_REALP (x), badx2);
0f2d19dd 3188#else
f3ae5d60 3189 SCM_GASSERT2 (SCM_SLOPPY_REALP (x),
9de33deb 3190 g_max, x, y, SCM_ARG1, s_max);
f872b822
MD
3191#endif
3192 if (SCM_INUMP (y))
3193 return ((SCM_REALPART (x) < (z = SCM_INUM (y)))
3194 ? scm_makdbl (z, 0.0)
3195 : x);
3196#ifdef SCM_BIGDIG
3197 SCM_ASRTGO (SCM_NIMP (y), bady);
3198 if (SCM_BIGP (y))
3199 return ((SCM_REALPART (x) < (z = scm_big2dbl (y)))
3200 ? scm_makdbl (z, 0.0)
3201 : x);
f3ae5d60 3202 SCM_ASRTGO (SCM_SLOPPY_REALP (y), bady);
f872b822 3203#else
f3ae5d60 3204 SCM_ASRTGO (SCM_SLOPPY_REALP (y), bady);
f872b822
MD
3205#endif
3206 return (SCM_REALPART (x) < SCM_REALPART (y)) ? y : x;
3207 }
3208 if (SCM_NINUMP (y))
3209 {
3210#ifdef SCM_BIGDIG
3211 SCM_ASRTGO (SCM_NIMP (y), bady);
3212 if (SCM_BIGP (y))
3213 return SCM_BIGSIGN (y) ? x : y;
f3ae5d60 3214 if (!(SCM_SLOPPY_REALP (y)))
f872b822
MD
3215 {
3216 bady:
9de33deb 3217 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
f872b822 3218 }
f872b822 3219#else
f3ae5d60 3220 if (!SCM_SLOPPY_REALP (y))
f872b822
MD
3221 {
3222 bady:
9de33deb 3223 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
f872b822 3224 }
f872b822
MD
3225#endif
3226 return (((z = SCM_INUM (x)) < SCM_REALPART (y))
3227 ? y
3228 : scm_makdbl (z, 0.0));
3229 }
f872b822 3230 return ((long) x < (long) y) ? y : x;
0f2d19dd
JB
3231}
3232
3233
c209c88e
GB
3234#define SCM_SWAP(x,y) do { SCM t = x; x = y; y = t; } while (0)
3235
0f2d19dd
JB
3236
3237
9de33deb 3238SCM_GPROC1 (s_min, "min", scm_tc7_asubr, scm_min, g_min);
1cc91f1b 3239
0f2d19dd 3240SCM
6e8d25a6 3241scm_min (SCM x, SCM y)
0f2d19dd 3242{
0f2d19dd 3243 double z;
f872b822
MD
3244 if (SCM_UNBNDP (y))
3245 {
73ef98d6
MD
3246 SCM_GASSERT0 (!SCM_UNBNDP (x),
3247 g_min, scm_makfrom0str (s_min), SCM_WNA, 0);
0e3aa89f 3248 SCM_GASSERT1 (SCM_NUMBERP (x), g_min, x, SCM_ARG1, s_min);
f872b822
MD
3249 return x;
3250 }
f872b822
MD
3251 if (SCM_NINUMP (x))
3252 {
3253#ifdef SCM_BIGDIG
0c95b57d 3254 if (!SCM_NIMP (x))
0e3aa89f
MD
3255 {
3256 badx2:
3257 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARG1, s_min);
3258 }
f872b822
MD
3259 if (SCM_BIGP (x))
3260 {
3261 if (SCM_INUMP (y))
3262 return SCM_BIGSIGN (x) ? x : y;
3263 SCM_ASRTGO (SCM_NIMP (y), bady);
3264 if (SCM_BIGP (y))
3265 return (-1 == scm_bigcomp (x, y)) ? y : x;
f3ae5d60 3266 SCM_ASRTGO (SCM_SLOPPY_REALP (y), bady);
f872b822
MD
3267 z = scm_big2dbl (x);
3268 return (z > SCM_REALPART (y)) ? y : scm_makdbl (z, 0.0);
3269 }
f3ae5d60 3270 SCM_ASRTGO (SCM_SLOPPY_REALP (x), badx2);
0f2d19dd 3271#else
f3ae5d60 3272 SCM_GASSERT2 (SCM_SLOPPY_REALP (x),
9de33deb 3273 g_min, x, y, SCM_ARG1, s_min);
f872b822
MD
3274#endif
3275 if (SCM_INUMP (y))
3276 return ((SCM_REALPART (x) > (z = SCM_INUM (y)))
3277 ? scm_makdbl (z, 0.0)
3278 : x);
3279#ifdef SCM_BIGDIG
3280 SCM_ASRTGO (SCM_NIMP (y), bady);
3281 if (SCM_BIGP (y))
3282 return ((SCM_REALPART (x) > (z = scm_big2dbl (y)))
3283 ? scm_makdbl (z, 0.0)
3284 : x);
f3ae5d60 3285 SCM_ASRTGO (SCM_SLOPPY_REALP (y), bady);
f872b822 3286#else
f3ae5d60 3287 SCM_ASRTGO (SCM_SLOPPY_REALP (y), bady);
f872b822
MD
3288#endif
3289 return (SCM_REALPART (x) > SCM_REALPART (y)) ? y : x;
3290 }
3291 if (SCM_NINUMP (y))
3292 {
3293#ifdef SCM_BIGDIG
3294 SCM_ASRTGO (SCM_NIMP (y), bady);
3295 if (SCM_BIGP (y))
3296 return SCM_BIGSIGN (y) ? y : x;
f3ae5d60 3297 if (!(SCM_SLOPPY_REALP (y)))
f872b822
MD
3298 {
3299 bady:
9de33deb 3300 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
f872b822 3301 }
f872b822 3302#else
f3ae5d60 3303 if (!SCM_SLOPPY_REALP (y))
f872b822
MD
3304 {
3305 bady:
9de33deb 3306 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
f872b822 3307 }
0f2d19dd 3308#endif
f872b822
MD
3309 return (((z = SCM_INUM (x)) > SCM_REALPART (y))
3310 ? y
3311 : scm_makdbl (z, 0.0));
3312 }
f872b822 3313 return ((long) x > (long) y) ? y : x;
0f2d19dd
JB
3314}
3315
3316
3317
3318
9de33deb 3319SCM_GPROC1 (s_sum, "+", scm_tc7_asubr, scm_sum, g_sum);
1cc91f1b 3320
c209c88e
GB
3321/*
3322 This is sick, sick, sick code.
3323
3324 */
0f2d19dd 3325SCM
6e8d25a6 3326scm_sum (SCM x, SCM y)
0f2d19dd 3327{
f872b822
MD
3328 if (SCM_UNBNDP (y))
3329 {
3330 if (SCM_UNBNDP (x))
3331 return SCM_INUM0;
0e3aa89f 3332 SCM_GASSERT1 (SCM_NUMBERP (x), g_sum, x, SCM_ARG1, s_sum);
f872b822
MD
3333 return x;
3334 }
f872b822
MD
3335 if (SCM_NINUMP (x))
3336 {
c209c88e 3337# ifdef SCM_BIGDIG
0e3aa89f
MD
3338 if (!SCM_NIMP (x))
3339 {
3340 badx2:
3341 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARG1, s_sum);
3342 }
f872b822
MD
3343 if (SCM_BIGP (x))
3344 {
3345 if (SCM_INUMP (y))
3346 {
c209c88e 3347 SCM_SWAP(x,y);
f872b822
MD
3348 goto intbig;
3349 }
3350 SCM_ASRTGO (SCM_NIMP (y), bady);
3351 if (SCM_BIGP (y))
3352 {
3353 if (SCM_NUMDIGS (x) > SCM_NUMDIGS (y))
3354 {
c209c88e 3355 SCM_SWAP(x,y);
f872b822
MD
3356 }
3357 return scm_addbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
3358 SCM_BIGSIGN (x),
3359 y, 0);
3360 }
f3ae5d60 3361 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822 3362 bigreal:
f3ae5d60
MD
3363 if (SCM_SLOPPY_REALP (y))
3364 return scm_make_real (scm_big2dbl (x) + SCM_REAL_VALUE (y));
3365 else
3366 return scm_make_complex (scm_big2dbl (x) + SCM_COMPLEX_REAL (y),
3367 SCM_COMPLEX_IMAG (y));
f872b822 3368 }
c209c88e 3369# endif /* SCM_BIGDIG */
f3ae5d60 3370 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x), badx2);
c209c88e 3371
f872b822
MD
3372 if (SCM_INUMP (y))
3373 {
c209c88e 3374 SCM_SWAP(x,y);
f872b822
MD
3375 goto intreal;
3376 }
c209c88e 3377# ifdef SCM_BIGDIG
f872b822
MD
3378 SCM_ASRTGO (SCM_NIMP (y), bady);
3379 if (SCM_BIGP (y))
3380 {
c209c88e 3381 SCM_SWAP(x,y);
f872b822
MD
3382 goto bigreal;
3383 }
f3ae5d60 3384 else if (!SCM_SLOPPY_INEXACTP (y))
f872b822
MD
3385 {
3386 bady:
9de33deb 3387 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
f872b822 3388 }
c209c88e 3389# else /* SCM_BIGDIG */
f3ae5d60 3390 if (!SCM_SLOPPY_INEXACTP (y))
f872b822
MD
3391 {
3392 bady:
9de33deb 3393 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
f872b822 3394 }
c209c88e 3395# endif /* SCM_BIGDIG */
f872b822
MD
3396 {
3397 double i = 0.0;
f3ae5d60
MD
3398 if (SCM_SLOPPY_COMPLEXP (x))
3399 i = SCM_COMPLEX_IMAG (x);
3400 if (SCM_SLOPPY_COMPLEXP (y))
3401 i += SCM_COMPLEX_IMAG (y);
f872b822 3402 return scm_makdbl (SCM_REALPART (x) + SCM_REALPART (y), i);
0f2d19dd 3403 }
f872b822
MD
3404 }
3405 if (SCM_NINUMP (y))
3406 {
c209c88e 3407# ifdef SCM_BIGDIG
f872b822
MD
3408 SCM_ASRTGO (SCM_NIMP (y), bady);
3409 if (SCM_BIGP (y))
3410 {
3411 intbig:
3412 {
c209c88e 3413# ifndef SCM_DIGSTOOBIG
f872b822
MD
3414 long z = scm_pseudolong (SCM_INUM (x));
3415 return scm_addbig ((SCM_BIGDIG *) & z,
3416 SCM_DIGSPERLONG,
f3ae5d60 3417 (x < 0) ? SCM_BIGSIGNFLAG : 0,
f872b822 3418 y, 0);
c209c88e 3419# else /* SCM_DIGSTOOBIG */
f872b822
MD
3420 SCM_BIGDIG zdigs[SCM_DIGSPERLONG];
3421 scm_longdigs (SCM_INUM (x), zdigs);
f3ae5d60 3422 return scm_addbig (zdigs, SCM_DIGSPERLONG, (x < 0) ? SCM_BIGSIGNFLAG : 0,
f872b822 3423 y, 0);
c209c88e 3424# endif /* SCM_DIGSTOOBIG */
f872b822
MD
3425 }
3426 }
c209c88e 3427# endif /* SCM_BIGDIG */
f3ae5d60 3428 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822 3429 intreal:
f3ae5d60
MD
3430 if (SCM_REALP (y))
3431 return scm_make_real (SCM_INUM (x) + SCM_REAL_VALUE (y));
3432 else
3433 return scm_make_complex (SCM_INUM (x) + SCM_COMPLEX_REAL (y),
3434 SCM_COMPLEX_IMAG (y));
f872b822 3435 }
c209c88e
GB
3436 { /* scope */
3437 long int i = SCM_INUM (x) + SCM_INUM (y);
3438 if (SCM_FIXABLE (i))
3439 return SCM_MAKINUM (i);
0f2d19dd 3440#ifdef SCM_BIGDIG
c209c88e
GB
3441 return scm_long2big (i);
3442#else /* SCM_BIGDIG */
c209c88e 3443 return scm_makdbl ((double) i, 0.0);
c209c88e
GB
3444#endif /* SCM_BIGDIG */
3445 } /* end scope */
0f2d19dd
JB
3446}
3447
3448
3449
3450
9de33deb 3451SCM_GPROC1 (s_difference, "-", scm_tc7_asubr, scm_difference, g_difference);
1cc91f1b 3452
c209c88e
GB
3453/*
3454 HWN:FIXME:: This is sick,sick, sick code. Rewrite me.
3455*/
0f2d19dd 3456SCM
6e8d25a6 3457scm_difference (SCM x, SCM y)
0f2d19dd 3458{
c209c88e 3459 long int cx = 0;
f872b822
MD
3460 if (SCM_NINUMP (x))
3461 {
c209c88e 3462 if (!SCM_NIMP (x))
f872b822 3463 {
0e3aa89f
MD
3464 if (SCM_UNBNDP (y))
3465 {
73ef98d6
MD
3466 SCM_GASSERT0 (!SCM_UNBNDP (x), g_difference,
3467 scm_makfrom0str (s_difference), SCM_WNA, 0);
0e3aa89f
MD
3468 badx:
3469 SCM_WTA_DISPATCH_1 (g_difference, x, SCM_ARG1, s_difference);
3470 }
3471 else
3472 {
3473 badx2:
3474 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARG1, s_difference);
3475 }
f872b822 3476 }
f872b822
MD
3477 if (SCM_UNBNDP (y))
3478 {
3479#ifdef SCM_BIGDIG
3480 if (SCM_BIGP (x))
3481 {
3482 x = scm_copybig (x, !SCM_BIGSIGN (x));
3483 return (SCM_NUMDIGS (x) * SCM_BITSPERDIG / SCM_CHAR_BIT
3484 <= sizeof (SCM)
3485 ? scm_big2inum (x, SCM_NUMDIGS (x))
3486 : x);
3487 }
3488#endif
f3ae5d60
MD
3489 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x), badx);
3490 if (SCM_SLOPPY_REALP (x))
3491 return scm_make_real (- SCM_REAL_VALUE (x));
3492 else
3493 return scm_make_complex (- SCM_COMPLEX_REAL (x),
3494 - SCM_COMPLEX_IMAG (x));
f872b822
MD
3495 }
3496 if (SCM_INUMP (y))
3497 return scm_sum (x, SCM_MAKINUM (- SCM_INUM (y)));
3498#ifdef SCM_BIGDIG
3499 SCM_ASRTGO (SCM_NIMP (y), bady);
3500 if (SCM_BIGP (x))
3501 {
3502 if (SCM_BIGP (y))
3503 return ((SCM_NUMDIGS (x) < SCM_NUMDIGS (y))
3504 ? scm_addbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
3505 SCM_BIGSIGN (x),
f3ae5d60 3506 y, SCM_BIGSIGNFLAG)
f872b822 3507 : scm_addbig (SCM_BDIGITS (y), SCM_NUMDIGS (y),
f3ae5d60 3508 SCM_BIGSIGN (y) ^ SCM_BIGSIGNFLAG,
f872b822 3509 x, 0));
f3ae5d60
MD
3510 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
3511 if (SCM_REALP (y))
3512 return scm_make_real (scm_big2dbl (x) - SCM_REAL_VALUE (y));
3513 else
3514 return scm_make_complex (scm_big2dbl (x) - SCM_COMPLEX_REAL (y),
3515 - SCM_COMPLEX_IMAG (y));
f872b822 3516 }
f3ae5d60 3517 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x), badx2);
f872b822 3518 if (SCM_BIGP (y))
f872b822 3519 {
f3ae5d60
MD
3520 if (SCM_REALP (x))
3521 return scm_make_real (SCM_REAL_VALUE (x) - scm_big2dbl (y));
f872b822 3522 else
f3ae5d60
MD
3523 return scm_make_complex (SCM_COMPLEX_REAL (x) - scm_big2dbl (y),
3524 SCM_COMPLEX_IMAG (x));
f872b822 3525 }
f3ae5d60
MD
3526 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
3527#else
3528 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x), badx2);
3529 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
3530#endif
3531 {
3532 SCM z;
3533 if (SCM_SLOPPY_COMPLEXP (x))
3534 {
3535 if (SCM_SLOPPY_COMPLEXP (y))
3536 SCM_NEWCOMPLEX (z,
3537 SCM_COMPLEX_REAL (x) - SCM_COMPLEX_REAL (y),
3538 SCM_COMPLEX_IMAG (x) - SCM_COMPLEX_IMAG (y));
3539 else
3540 SCM_NEWCOMPLEX (z,
3541 SCM_COMPLEX_REAL (x) - SCM_REAL_VALUE (y),
3542 SCM_COMPLEX_IMAG (x));
3543 }
3544 else
3545 {
3546 if (SCM_SLOPPY_COMPLEXP (y))
3547 SCM_NEWCOMPLEX (z,
3548 SCM_REAL_VALUE (x) - SCM_COMPLEX_REAL (y),
3549 - SCM_COMPLEX_IMAG (y));
3550 else
3551 SCM_NEWREAL (z, SCM_REAL_VALUE (x) - SCM_REAL_VALUE (y));
3552 }
3553 return z;
3554 }
f872b822
MD
3555 }
3556 if (SCM_UNBNDP (y))
3557 {
c209c88e 3558 cx = -SCM_INUM (x);
f872b822
MD
3559 goto checkx;
3560 }
3561 if (SCM_NINUMP (y))
3562 {
3563#ifdef SCM_BIGDIG
3564 SCM_ASRTGO (SCM_NIMP (y), bady);
3565 if (SCM_BIGP (y))
3566 {
3567#ifndef SCM_DIGSTOOBIG
3568 long z = scm_pseudolong (SCM_INUM (x));
3569 return scm_addbig ((SCM_BIGDIG *) & z, SCM_DIGSPERLONG,
f3ae5d60
MD
3570 (x < 0) ? SCM_BIGSIGNFLAG : 0,
3571 y, SCM_BIGSIGNFLAG);
f872b822
MD
3572#else
3573 SCM_BIGDIG zdigs[SCM_DIGSPERLONG];
3574 scm_longdigs (SCM_INUM (x), zdigs);
f3ae5d60
MD
3575 return scm_addbig (zdigs, SCM_DIGSPERLONG, (x < 0) ? SCM_BIGSIGNFLAG : 0,
3576 y, SCM_BIGSIGNFLAG);
f872b822
MD
3577#endif
3578 }
f3ae5d60 3579 if (!SCM_SLOPPY_INEXACTP (y))
f872b822
MD
3580 {
3581 bady:
9de33deb 3582 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
f872b822 3583 }
f872b822 3584#else
f3ae5d60 3585 if (!SCM_SLOPPY_INEXACTP (y))
f872b822
MD
3586 {
3587 bady:
9de33deb 3588 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
f872b822 3589 }
f872b822
MD
3590#endif
3591 return scm_makdbl (SCM_INUM (x) - SCM_REALPART (y),
f3ae5d60 3592 SCM_SLOPPY_COMPLEXP (y) ? -SCM_IMAG (y) : 0.0);
f872b822 3593 }
c209c88e 3594 cx = SCM_INUM (x) - SCM_INUM (y);
0f2d19dd 3595 checkx:
c209c88e
GB
3596 if (SCM_FIXABLE (cx))
3597 return SCM_MAKINUM (cx);
0f2d19dd 3598#ifdef SCM_BIGDIG
c209c88e 3599 return scm_long2big (cx);
f872b822 3600#else
c209c88e 3601 return scm_makdbl ((double) cx, 0.0);
0f2d19dd
JB
3602#endif
3603}
3604
3605
3606
3607
9de33deb 3608SCM_GPROC1 (s_product, "*", scm_tc7_asubr, scm_product, g_product);
1cc91f1b 3609
0f2d19dd 3610SCM
6e8d25a6 3611scm_product (SCM x, SCM y)
0f2d19dd 3612{
f872b822
MD
3613 if (SCM_UNBNDP (y))
3614 {
3615 if (SCM_UNBNDP (x))
3616 return SCM_MAKINUM (1L);
0e3aa89f 3617 SCM_GASSERT1 (SCM_NUMBERP (x), g_product, x, SCM_ARG1, s_product);
f872b822
MD
3618 return x;
3619 }
f872b822
MD
3620 if (SCM_NINUMP (x))
3621 {
3622 SCM t;
3623#ifdef SCM_BIGDIG
0e3aa89f
MD
3624 if (!SCM_NIMP (x))
3625 {
3626 badx2:
3627 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARG1, s_product);
3628 }
f872b822
MD
3629 if (SCM_BIGP (x))
3630 {
3631 if (SCM_INUMP (y))
3632 {
3633 t = x;
3634 x = y;
3635 y = t;
3636 goto intbig;
3637 }
3638 SCM_ASRTGO (SCM_NIMP (y), bady);
3639 if (SCM_BIGP (y))
3640 return scm_mulbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
3641 SCM_BDIGITS (y), SCM_NUMDIGS (y),
3642 SCM_BIGSIGN (x) ^ SCM_BIGSIGN (y));
f3ae5d60 3643 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822
MD
3644 bigreal:
3645 {
3646 double bg = scm_big2dbl (x);
3647 return scm_makdbl (bg * SCM_REALPART (y),
f3ae5d60 3648 SCM_SLOPPY_COMPLEXP (y) ? bg * SCM_IMAG (y) : 0.0);
f872b822
MD
3649 }
3650 }
f3ae5d60 3651 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x), badx2);
f872b822 3652#else
f3ae5d60 3653 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x), badx2);
f872b822
MD
3654#endif
3655 if (SCM_INUMP (y))
3656 {
3657 t = x;
3658 x = y;
3659 y = t;
3660 goto intreal;
3661 }
3662#ifdef SCM_BIGDIG
3663 SCM_ASRTGO (SCM_NIMP (y), bady);
3664 if (SCM_BIGP (y))
3665 {
3666 t = x;
3667 x = y;
3668 y = t;
3669 goto bigreal;
3670 }
f3ae5d60 3671 else if (!(SCM_SLOPPY_INEXACTP (y)))
f872b822
MD
3672 {
3673 bady:
9de33deb 3674 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
f872b822 3675 }
f872b822 3676#else
f3ae5d60 3677 if (!SCM_SLOPPY_INEXACTP (y))
f872b822
MD
3678 {
3679 bady:
9de33deb 3680 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
f872b822 3681 }
f872b822 3682#endif
f3ae5d60 3683 if (SCM_SLOPPY_COMPLEXP (x))
f872b822 3684 {
f3ae5d60 3685 if (SCM_SLOPPY_COMPLEXP (y))
f872b822
MD
3686 return scm_makdbl (SCM_REAL (x) * SCM_REAL (y)
3687 - SCM_IMAG (x) * SCM_IMAG (y),
3688 SCM_REAL (x) * SCM_IMAG (y)
3689 + SCM_IMAG (x) * SCM_REAL (y));
3690 else
3691 return scm_makdbl (SCM_REAL (x) * SCM_REALPART (y),
3692 SCM_IMAG (x) * SCM_REALPART (y));
3693 }
3694 return scm_makdbl (SCM_REALPART (x) * SCM_REALPART (y),
f3ae5d60 3695 SCM_SLOPPY_COMPLEXP (y)
f872b822
MD
3696 ? SCM_REALPART (x) * SCM_IMAG (y)
3697 : 0.0);
3698 }
3699 if (SCM_NINUMP (y))
3700 {
3701#ifdef SCM_BIGDIG
3702 SCM_ASRTGO (SCM_NIMP (y), bady);
3703 if (SCM_BIGP (y))
3704 {
3705 intbig:
3706 if (SCM_INUM0 == x)
3707 return x;
3708 if (SCM_MAKINUM (1L) == x)
3709 return y;
3710 {
3711#ifndef SCM_DIGSTOOBIG
3712 long z = scm_pseudolong (SCM_INUM (x));
3713 return scm_mulbig ((SCM_BIGDIG *) & z, SCM_DIGSPERLONG,
3714 SCM_BDIGITS (y), SCM_NUMDIGS (y),
3715 SCM_BIGSIGN (y) ? (x > 0) : (x < 0));
3716#else
3717 SCM_BIGDIG zdigs[SCM_DIGSPERLONG];
3718 scm_longdigs (SCM_INUM (x), zdigs);
3719 return scm_mulbig (zdigs, SCM_DIGSPERLONG,
3720 SCM_BDIGITS (y), SCM_NUMDIGS (y),
3721 SCM_BIGSIGN (y) ? (x > 0) : (x < 0));
3722#endif
3723 }
3724 }
f3ae5d60 3725 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822 3726#else
f3ae5d60 3727 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822
MD
3728#endif
3729 intreal:
3730 return scm_makdbl (SCM_INUM (x) * SCM_REALPART (y),
f3ae5d60 3731 SCM_SLOPPY_COMPLEXP (y) ? SCM_INUM (x) * SCM_IMAG (y) : 0.0);
f872b822 3732 }
0f2d19dd
JB
3733 {
3734 long i, j, k;
f872b822
MD
3735 i = SCM_INUM (x);
3736 if (0 == i)
3737 return x;
3738 j = SCM_INUM (y);
0f2d19dd 3739 k = i * j;
f872b822
MD
3740 y = SCM_MAKINUM (k);
3741 if (k != SCM_INUM (y) || k / i != j)
3742#ifdef SCM_BIGDIG
3743 {
3744 int sgn = (i < 0) ^ (j < 0);
3745#ifndef SCM_DIGSTOOBIG
3746 i = scm_pseudolong (i);
3747 j = scm_pseudolong (j);
3748 return scm_mulbig ((SCM_BIGDIG *) & i, SCM_DIGSPERLONG,
3749 (SCM_BIGDIG *) & j, SCM_DIGSPERLONG, sgn);
3750#else /* SCM_DIGSTOOBIG */
0f2d19dd
JB
3751 SCM_BIGDIG idigs[SCM_DIGSPERLONG];
3752 SCM_BIGDIG jdigs[SCM_DIGSPERLONG];
f872b822
MD
3753 scm_longdigs (i, idigs);
3754 scm_longdigs (j, jdigs);
3755 return scm_mulbig (idigs, SCM_DIGSPERLONG,
3756 jdigs, SCM_DIGSPERLONG,
3757 sgn);
3758#endif
0f2d19dd
JB
3759 }
3760#else
f872b822 3761 return scm_makdbl (((double) i) * ((double) j), 0.0);
0f2d19dd
JB
3762#endif
3763 return y;
3764 }
3765}
3766
3767
1cc91f1b 3768
0f2d19dd 3769double
6e8d25a6 3770scm_num2dbl (SCM a, const char *why)
0f2d19dd
JB
3771{
3772 if (SCM_INUMP (a))
3773 return (double) SCM_INUM (a);
0f2d19dd 3774 SCM_ASSERT (SCM_NIMP (a), a, "wrong type argument", why);
f3ae5d60 3775 if (SCM_SLOPPY_REALP (a))
0f2d19dd 3776 return (SCM_REALPART (a));
0f2d19dd
JB
3777#ifdef SCM_BIGDIG
3778 return scm_big2dbl (a);
3779#endif
3780 SCM_ASSERT (0, a, "wrong type argument", why);
c209c88e
GB
3781 /*
3782 unreachable, hopefully.
3783 */
3784 return (double) 0.0; /* ugh. */
3785 /* return SCM_UNSPECIFIED; */
0f2d19dd
JB
3786}
3787
3788
9de33deb 3789SCM_GPROC1 (s_divide, "/", scm_tc7_asubr, scm_divide, g_divide);
1cc91f1b 3790
0f2d19dd 3791SCM
6e8d25a6 3792scm_divide (SCM x, SCM y)
0f2d19dd 3793{
0f2d19dd 3794 double d, r, i, a;
f872b822
MD
3795 if (SCM_NINUMP (x))
3796 {
f872b822
MD
3797 if (!(SCM_NIMP (x)))
3798 {
0e3aa89f
MD
3799 if (SCM_UNBNDP (y))
3800 {
73ef98d6
MD
3801 SCM_GASSERT0 (!SCM_UNBNDP (x),
3802 g_divide, scm_makfrom0str (s_divide), SCM_WNA, 0);
0e3aa89f
MD
3803 badx:
3804 SCM_WTA_DISPATCH_1 (g_divide, x, SCM_ARG1, s_divide);
3805 }
3806 else
3807 {
3808 badx2:
3809 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARG1, s_divide);
3810 }
f872b822 3811 }
f872b822
MD
3812 if (SCM_UNBNDP (y))
3813 {
3814#ifdef SCM_BIGDIG
3815 if (SCM_BIGP (x))
3816 return scm_makdbl (1.0 / scm_big2dbl (x), 0.0);
3817#endif
f3ae5d60
MD
3818 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x), badx);
3819 if (SCM_SLOPPY_REALP (x))
f872b822
MD
3820 return scm_makdbl (1.0 / SCM_REALPART (x), 0.0);
3821 r = SCM_REAL (x);
3822 i = SCM_IMAG (x);
3823 d = r * r + i * i;
3824 return scm_makdbl (r / d, -i / d);
3825 }
3826#ifdef SCM_BIGDIG
3827 if (SCM_BIGP (x))
3828 {
f872b822
MD
3829 if (SCM_INUMP (y))
3830 {
c209c88e 3831 long int z = SCM_INUM (y);
f872b822
MD
3832#ifndef SCM_RECKLESS
3833 if (!z)
3834 scm_num_overflow (s_divide);
3835#endif
3836 if (1 == z)
3837 return x;
3838 if (z < 0)
3839 z = -z;
3840 if (z < SCM_BIGRAD)
3841 {
3842 SCM w = scm_copybig (x, SCM_BIGSIGN (x) ? (y > 0) : (y < 0));
3843 return (scm_divbigdig (SCM_BDIGITS (w), SCM_NUMDIGS (w),
3844 (SCM_BIGDIG) z)
3845 ? scm_makdbl (scm_big2dbl (x) / SCM_INUM (y), 0.0)
3846 : scm_normbig (w));
3847 }
3848#ifndef SCM_DIGSTOOBIG
c209c88e 3849 /*ugh! Does anyone know what this is supposed to do?*/
f872b822 3850 z = scm_pseudolong (z);
c209c88e
GB
3851 z = SCM_INUM(scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
3852 (SCM_BIGDIG *) & z, SCM_DIGSPERLONG,
3853 SCM_BIGSIGN (x) ? (y > 0) : (y < 0), 3));
f872b822
MD
3854#else
3855 {
3856 SCM_BIGDIG zdigs[SCM_DIGSPERLONG];
3857 scm_longdigs (z, zdigs);
3858 z = scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
3859 zdigs, SCM_DIGSPERLONG,
3860 SCM_BIGSIGN (x) ? (y > 0) : (y < 0), 3);
3861 }
3862#endif
f1267706 3863 return z ? SCM_PACK (z) : scm_makdbl (scm_big2dbl (x) / SCM_INUM (y), 0.0);
f872b822
MD
3864 }
3865 SCM_ASRTGO (SCM_NIMP (y), bady);
3866 if (SCM_BIGP (y))
3867 {
c209c88e 3868 SCM z = scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
f872b822
MD
3869 SCM_BDIGITS (y), SCM_NUMDIGS (y),
3870 SCM_BIGSIGN (x) ^ SCM_BIGSIGN (y), 3);
3871 return z ? z : scm_makdbl (scm_big2dbl (x) / scm_big2dbl (y),
3872 0.0);
3873 }
f3ae5d60
MD
3874 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
3875 if (SCM_SLOPPY_REALP (y))
f872b822
MD
3876 return scm_makdbl (scm_big2dbl (x) / SCM_REALPART (y), 0.0);
3877 a = scm_big2dbl (x);
3878 goto complex_div;
3879 }
3880#endif
f3ae5d60 3881 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x), badx2);
f872b822
MD
3882 if (SCM_INUMP (y))
3883 {
3884 d = SCM_INUM (y);
3885 goto basic_div;
3886 }
3887#ifdef SCM_BIGDIG
3888 SCM_ASRTGO (SCM_NIMP (y), bady);
3889 if (SCM_BIGP (y))
3890 {
3891 d = scm_big2dbl (y);
3892 goto basic_div;
3893 }
f3ae5d60 3894 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822 3895#else
f3ae5d60 3896 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y), bady);
f872b822 3897#endif
f3ae5d60 3898 if (SCM_SLOPPY_REALP (y))
f872b822
MD
3899 {
3900 d = SCM_REALPART (y);
3901 basic_div:
3902 return scm_makdbl (SCM_REALPART (x) / d,
f3ae5d60 3903 SCM_SLOPPY_COMPLEXP (x) ? SCM_IMAG (x) / d : 0.0);
f872b822
MD
3904 }
3905 a = SCM_REALPART (x);
f3ae5d60 3906 if (SCM_SLOPPY_REALP (x))
f872b822
MD
3907 goto complex_div;
3908 r = SCM_REAL (y);
3909 i = SCM_IMAG (y);
3910 d = r * r + i * i;
3911 return scm_makdbl ((a * r + SCM_IMAG (x) * i) / d,
3912 (SCM_IMAG (x) * r - a * i) / d);
3913 }
3914 if (SCM_UNBNDP (y))
3915 {
3916 if ((SCM_MAKINUM (1L) == x) || (SCM_MAKINUM (-1L) == x))
3917 return x;
3918 return scm_makdbl (1.0 / ((double) SCM_INUM (x)), 0.0);
3919 }
3920 if (SCM_NINUMP (y))
3921 {
3922#ifdef SCM_BIGDIG
3923 SCM_ASRTGO (SCM_NIMP (y), bady);
3924 if (SCM_BIGP (y))
3925 return scm_makdbl (SCM_INUM (x) / scm_big2dbl (y), 0.0);
f3ae5d60 3926 if (!(SCM_SLOPPY_INEXACTP (y)))
f872b822
MD
3927 {
3928 bady:
9de33deb 3929 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
f872b822 3930 }
f872b822 3931#else
f3ae5d60 3932 if (!SCM_SLOPPY_INEXACTP (y))
f872b822
MD
3933 {
3934 bady:
9de33deb 3935 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
f872b822 3936 }
f872b822 3937#endif
f3ae5d60 3938 if (SCM_SLOPPY_REALP (y))
f872b822
MD
3939 return scm_makdbl (SCM_INUM (x) / SCM_REALPART (y), 0.0);
3940 a = SCM_INUM (x);
3941 complex_div:
3942 r = SCM_REAL (y);
3943 i = SCM_IMAG (y);
3944 d = r * r + i * i;
3945 return scm_makdbl ((a * r) / d, (-a * i) / d);
3946 }
0f2d19dd 3947 {
f872b822
MD
3948 long z = SCM_INUM (y);
3949 if ((0 == z) || SCM_INUM (x) % z)
3950 goto ov;
3951 z = SCM_INUM (x) / z;
3952 if (SCM_FIXABLE (z))
3953 return SCM_MAKINUM (z);
0f2d19dd 3954#ifdef SCM_BIGDIG
f872b822 3955 return scm_long2big (z);
0f2d19dd 3956#endif
f872b822
MD
3957 ov:
3958 return scm_makdbl (((double) SCM_INUM (x)) / ((double) SCM_INUM (y)), 0.0);
0f2d19dd
JB
3959 }
3960}
3961
3962
3963
3964
9de33deb 3965SCM_GPROC1 (s_asinh, "$asinh", scm_tc7_cxr, (SCM (*)()) scm_asinh, g_asinh);
1cc91f1b 3966
0f2d19dd 3967double
6e8d25a6 3968scm_asinh (double x)
0f2d19dd 3969{
f872b822 3970 return log (x + sqrt (x * x + 1));
0f2d19dd
JB
3971}
3972
3973
3974
3975
9de33deb 3976SCM_GPROC1 (s_acosh, "$acosh", scm_tc7_cxr, (SCM (*)()) scm_acosh, g_acosh);
1cc91f1b 3977
0f2d19dd 3978double
6e8d25a6 3979scm_acosh (double x)
0f2d19dd 3980{
f872b822 3981 return log (x + sqrt (x * x - 1));
0f2d19dd
JB
3982}
3983
3984
3985
3986
9de33deb 3987SCM_GPROC1 (s_atanh, "$atanh", scm_tc7_cxr, (SCM (*)()) scm_atanh, g_atanh);
1cc91f1b 3988
0f2d19dd 3989double
6e8d25a6 3990scm_atanh (double x)
0f2d19dd 3991{
f872b822 3992 return 0.5 * log ((1 + x) / (1 - x));
0f2d19dd
JB
3993}
3994
3995
3996
3997
9de33deb 3998SCM_GPROC1 (s_truncate, "truncate", scm_tc7_cxr, (SCM (*)()) scm_truncate, g_truncate);
1cc91f1b 3999
0f2d19dd 4000double
6e8d25a6 4001scm_truncate (double x)
0f2d19dd 4002{
f872b822
MD
4003 if (x < 0.0)
4004 return -floor (-x);
4005 return floor (x);
0f2d19dd
JB
4006}
4007
4008
4009
9de33deb 4010SCM_GPROC1 (s_round, "round", scm_tc7_cxr, (SCM (*)()) scm_round, g_round);
1cc91f1b 4011
0f2d19dd 4012double
6e8d25a6 4013scm_round (double x)
0f2d19dd
JB
4014{
4015 double plus_half = x + 0.5;
f872b822 4016 double result = floor (plus_half);
0f2d19dd 4017 /* Adjust so that the scm_round is towards even. */
f872b822 4018 return (plus_half == result && plus_half / 2 != floor (plus_half / 2))
0f2d19dd
JB
4019 ? result - 1 : result;
4020}
4021
4022
4023
9de33deb 4024SCM_GPROC1 (s_exact_to_inexact, "exact->inexact", scm_tc7_cxr, (SCM (*)()) scm_exact_to_inexact, g_exact_to_inexact);
1cc91f1b 4025
0f2d19dd 4026double
6e8d25a6 4027scm_exact_to_inexact (double z)
0f2d19dd
JB
4028{
4029 return z;
4030}
4031
4032
9de33deb
MD
4033SCM_GPROC1 (s_i_floor, "floor", scm_tc7_cxr, (SCM (*)()) floor, g_i_floor);
4034SCM_GPROC1 (s_i_ceil, "ceiling", scm_tc7_cxr, (SCM (*)()) ceil, g_i_ceil);
4035SCM_GPROC1 (s_i_sqrt, "$sqrt", scm_tc7_cxr, (SCM (*)()) sqrt, g_i_sqrt);
4036SCM_GPROC1 (s_i_abs, "$abs", scm_tc7_cxr, (SCM (*)()) fabs, g_i_abs);
4037SCM_GPROC1 (s_i_exp, "$exp", scm_tc7_cxr, (SCM (*)()) exp, g_i_exp);
4038SCM_GPROC1 (s_i_log, "$log", scm_tc7_cxr, (SCM (*)()) log, g_i_log);
4039SCM_GPROC1 (s_i_sin, "$sin", scm_tc7_cxr, (SCM (*)()) sin, g_i_sin);
4040SCM_GPROC1 (s_i_cos, "$cos", scm_tc7_cxr, (SCM (*)()) cos, g_i_cos);
4041SCM_GPROC1 (s_i_tan, "$tan", scm_tc7_cxr, (SCM (*)()) tan, g_i_tan);
4042SCM_GPROC1 (s_i_asin, "$asin", scm_tc7_cxr, (SCM (*)()) asin, g_i_asin);
4043SCM_GPROC1 (s_i_acos, "$acos", scm_tc7_cxr, (SCM (*)()) acos, g_i_acos);
4044SCM_GPROC1 (s_i_atan, "$atan", scm_tc7_cxr, (SCM (*)()) atan, g_i_atan);
4045SCM_GPROC1 (s_i_sinh, "$sinh", scm_tc7_cxr, (SCM (*)()) sinh, g_i_sinh);
4046SCM_GPROC1 (s_i_cosh, "$cosh", scm_tc7_cxr, (SCM (*)()) cosh, g_i_cosh);
4047SCM_GPROC1 (s_i_tanh, "$tanh", scm_tc7_cxr, (SCM (*)()) tanh, g_i_tanh);
f872b822
MD
4048
4049struct dpair
4050{
4051 double x, y;
4052};
4053
3eeba8d4
JB
4054static void scm_two_doubles (SCM z1,
4055 SCM z2,
4056 const char *sstring,
4057 struct dpair * xy);
f872b822
MD
4058
4059static void
6e8d25a6 4060scm_two_doubles (SCM z1, SCM z2, const char *sstring, struct dpair *xy)
0f2d19dd 4061{
f872b822
MD
4062 if (SCM_INUMP (z1))
4063 xy->x = SCM_INUM (z1);
4064 else
4065 {
4066#ifdef SCM_BIGDIG
4067 SCM_ASRTGO (SCM_NIMP (z1), badz1);
4068 if (SCM_BIGP (z1))
4069 xy->x = scm_big2dbl (z1);
4070 else
4071 {
4072#ifndef SCM_RECKLESS
f3ae5d60 4073 if (!SCM_SLOPPY_REALP (z1))
f872b822
MD
4074 badz1:scm_wta (z1, (char *) SCM_ARG1, sstring);
4075#endif
4076 xy->x = SCM_REALPART (z1);
4077 }
4078#else
4079 {
f3ae5d60 4080 SCM_ASSERT (SCM_SLOPPY_REALP (z1), z1, SCM_ARG1, sstring);
f872b822
MD
4081 xy->x = SCM_REALPART (z1);
4082 }
4083#endif
4084 }
4085 if (SCM_INUMP (z2))
4086 xy->y = SCM_INUM (z2);
4087 else
4088 {
4089#ifdef SCM_BIGDIG
4090 SCM_ASRTGO (SCM_NIMP (z2), badz2);
4091 if (SCM_BIGP (z2))
4092 xy->y = scm_big2dbl (z2);
4093 else
4094 {
4095#ifndef SCM_RECKLESS
f3ae5d60 4096 if (!(SCM_SLOPPY_REALP (z2)))
f872b822
MD
4097 badz2:scm_wta (z2, (char *) SCM_ARG2, sstring);
4098#endif
4099 xy->y = SCM_REALPART (z2);
4100 }
4101#else
4102 {
f3ae5d60 4103 SCM_ASSERT (SCM_SLOPPY_REALP (z2), z2, SCM_ARG2, sstring);
f872b822
MD
4104 xy->y = SCM_REALPART (z2);
4105 }
4106#endif
4107 }
0f2d19dd
JB
4108}
4109
4110
4111
4112
a1ec6916 4113SCM_DEFINE (scm_sys_expt, "$expt", 2, 0, 0,
1bbd0b84 4114 (SCM z1, SCM z2),
b380b885 4115 "")
1bbd0b84 4116#define FUNC_NAME s_scm_sys_expt
0f2d19dd
JB
4117{
4118 struct dpair xy;
1bbd0b84 4119 scm_two_doubles (z1, z2, FUNC_NAME, &xy);
f872b822 4120 return scm_makdbl (pow (xy.x, xy.y), 0.0);
0f2d19dd 4121}
1bbd0b84 4122#undef FUNC_NAME
0f2d19dd
JB
4123
4124
4125
a1ec6916 4126SCM_DEFINE (scm_sys_atan2, "$atan2", 2, 0, 0,
1bbd0b84 4127 (SCM z1, SCM z2),
b380b885 4128 "")
1bbd0b84 4129#define FUNC_NAME s_scm_sys_atan2
0f2d19dd
JB
4130{
4131 struct dpair xy;
1bbd0b84 4132 scm_two_doubles (z1, z2, FUNC_NAME, &xy);
f872b822 4133 return scm_makdbl (atan2 (xy.x, xy.y), 0.0);
0f2d19dd 4134}
1bbd0b84 4135#undef FUNC_NAME
0f2d19dd
JB
4136
4137
4138
a1ec6916 4139SCM_DEFINE (scm_make_rectangular, "make-rectangular", 2, 0, 0,
1bbd0b84 4140 (SCM z1, SCM z2),
b380b885 4141 "")
1bbd0b84 4142#define FUNC_NAME s_scm_make_rectangular
0f2d19dd
JB
4143{
4144 struct dpair xy;
1bbd0b84 4145 scm_two_doubles (z1, z2, FUNC_NAME, &xy);
f872b822 4146 return scm_makdbl (xy.x, xy.y);
0f2d19dd 4147}
1bbd0b84 4148#undef FUNC_NAME
0f2d19dd
JB
4149
4150
4151
a1ec6916 4152SCM_DEFINE (scm_make_polar, "make-polar", 2, 0, 0,
1bbd0b84 4153 (SCM z1, SCM z2),
b380b885 4154 "")
1bbd0b84 4155#define FUNC_NAME s_scm_make_polar
0f2d19dd
JB
4156{
4157 struct dpair xy;
1bbd0b84 4158 scm_two_doubles (z1, z2, FUNC_NAME, &xy);
f872b822 4159 return scm_makdbl (xy.x * cos (xy.y), xy.x * sin (xy.y));
0f2d19dd 4160}
1bbd0b84 4161#undef FUNC_NAME
0f2d19dd
JB
4162
4163
4164
4165
152f82bf 4166SCM_GPROC (s_real_part, "real-part", 1, 0, 0, scm_real_part, g_real_part);
1cc91f1b 4167
0f2d19dd 4168SCM
6e8d25a6 4169scm_real_part (SCM z)
0f2d19dd 4170{
f872b822
MD
4171 if (SCM_NINUMP (z))
4172 {
4173#ifdef SCM_BIGDIG
4174 SCM_ASRTGO (SCM_NIMP (z), badz);
4175 if (SCM_BIGP (z))
4176 return z;
f3ae5d60 4177 if (!(SCM_SLOPPY_INEXACTP (z)))
f872b822
MD
4178 {
4179 badz:
152f82bf 4180 SCM_WTA_DISPATCH_1 (g_real_part, z, SCM_ARG1, s_real_part);
f872b822 4181 }
f872b822 4182#else
f3ae5d60 4183 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z),
152f82bf 4184 g_real_part, z, SCM_ARG1, s_real_part);
f872b822 4185#endif
f3ae5d60 4186 if (SCM_SLOPPY_COMPLEXP (z))
f872b822
MD
4187 return scm_makdbl (SCM_REAL (z), 0.0);
4188 }
0f2d19dd
JB
4189 return z;
4190}
4191
4192
4193
152f82bf 4194SCM_GPROC (s_imag_part, "imag-part", 1, 0, 0, scm_imag_part, g_imag_part);
1cc91f1b 4195
0f2d19dd 4196SCM
6e8d25a6 4197scm_imag_part (SCM z)
0f2d19dd 4198{
f872b822
MD
4199 if (SCM_INUMP (z))
4200 return SCM_INUM0;
4201#ifdef SCM_BIGDIG
4202 SCM_ASRTGO (SCM_NIMP (z), badz);
4203 if (SCM_BIGP (z))
4204 return SCM_INUM0;
f3ae5d60 4205 if (!(SCM_SLOPPY_INEXACTP (z)))
f872b822
MD
4206 {
4207 badz:
152f82bf 4208 SCM_WTA_DISPATCH_1 (g_imag_part, z, SCM_ARG1, s_imag_part);
f872b822 4209 }
f872b822 4210#else
f3ae5d60 4211 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z),
152f82bf 4212 g_imag_part, z, SCM_ARG1, s_imag_part);
f872b822 4213#endif
f3ae5d60 4214 if (SCM_SLOPPY_COMPLEXP (z))
f872b822 4215 return scm_makdbl (SCM_IMAG (z), 0.0);
0f2d19dd
JB
4216 return scm_flo0;
4217}
4218
4219
4220
9de33deb 4221SCM_GPROC (s_magnitude, "magnitude", 1, 0, 0, scm_magnitude, g_magnitude);
1cc91f1b 4222
0f2d19dd 4223SCM
6e8d25a6 4224scm_magnitude (SCM z)
0f2d19dd 4225{
f872b822
MD
4226 if (SCM_INUMP (z))
4227 return scm_abs (z);
4228#ifdef SCM_BIGDIG
4229 SCM_ASRTGO (SCM_NIMP (z), badz);
4230 if (SCM_BIGP (z))
4231 return scm_abs (z);
f3ae5d60 4232 if (!(SCM_SLOPPY_INEXACTP (z)))
f872b822
MD
4233 {
4234 badz:
9de33deb 4235 SCM_WTA_DISPATCH_1 (g_magnitude, z, SCM_ARG1, s_magnitude);
f872b822 4236 }
f872b822 4237#else
f3ae5d60 4238 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z),
9de33deb 4239 g_magnitude, z, SCM_ARG1, s_magnitude);
f872b822 4240#endif
f3ae5d60 4241 if (SCM_SLOPPY_COMPLEXP (z))
0f2d19dd 4242 {
f872b822
MD
4243 double i = SCM_IMAG (z), r = SCM_REAL (z);
4244 return scm_makdbl (sqrt (i * i + r * r), 0.0);
0f2d19dd 4245 }
f872b822 4246 return scm_makdbl (fabs (SCM_REALPART (z)), 0.0);
0f2d19dd
JB
4247}
4248
4249
4250
4251
9de33deb 4252SCM_GPROC (s_angle, "angle", 1, 0, 0, scm_angle, g_angle);
1cc91f1b 4253
0f2d19dd 4254SCM
6e8d25a6 4255scm_angle (SCM z)
0f2d19dd
JB
4256{
4257 double x, y = 0.0;
f872b822
MD
4258 if (SCM_INUMP (z))
4259 {
4260 x = (z >= SCM_INUM0) ? 1.0 : -1.0;
4261 goto do_angle;
4262 }
4263#ifdef SCM_BIGDIG
4264 SCM_ASRTGO (SCM_NIMP (z), badz);
4265 if (SCM_BIGP (z))
4266 {
f3ae5d60 4267 x = (SCM_BIGSIGN (z)) ? -1.0 : 1.0;
f872b822
MD
4268 goto do_angle;
4269 }
f3ae5d60 4270 if (!(SCM_SLOPPY_INEXACTP (z)))
f872b822
MD
4271 {
4272 badz:
9de33deb 4273 SCM_WTA_DISPATCH_1 (g_angle, z, SCM_ARG1, s_angle);
f872b822 4274 }
f872b822 4275#else
f3ae5d60 4276 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z), g_angle, z, SCM_ARG1, s_angle);
f872b822 4277#endif
f3ae5d60 4278 if (SCM_SLOPPY_REALP (z))
f872b822
MD
4279 {
4280 x = SCM_REALPART (z);
0f2d19dd
JB
4281 goto do_angle;
4282 }
f872b822
MD
4283 x = SCM_REAL (z);
4284 y = SCM_IMAG (z);
0f2d19dd 4285 do_angle:
f872b822 4286 return scm_makdbl (atan2 (y, x), 0.0);
0f2d19dd
JB
4287}
4288
4289
a1ec6916 4290SCM_DEFINE (scm_inexact_to_exact, "inexact->exact", 1, 0, 0,
1bbd0b84 4291 (SCM z),
b380b885 4292 "")
1bbd0b84 4293#define FUNC_NAME s_scm_inexact_to_exact
0f2d19dd 4294{
f872b822
MD
4295 if (SCM_INUMP (z))
4296 return z;
4297#ifdef SCM_BIGDIG
4298 SCM_ASRTGO (SCM_NIMP (z), badz);
4299 if (SCM_BIGP (z))
4300 return z;
4301#ifndef SCM_RECKLESS
f3ae5d60 4302 if (!(SCM_SLOPPY_REALP (z)))
f872b822
MD
4303 {
4304 badz:
4638e087 4305 SCM_WTA (1, z);
f872b822
MD
4306 }
4307#endif
4308#else
3b3b36dd 4309 SCM_VALIDATE_REAL (1,z);
f872b822
MD
4310#endif
4311#ifdef SCM_BIGDIG
0f2d19dd 4312 {
f872b822
MD
4313 double u = floor (SCM_REALPART (z) + 0.5);
4314 if ((u <= SCM_MOST_POSITIVE_FIXNUM) && (-u <= -SCM_MOST_NEGATIVE_FIXNUM))
4315 {
4316 /* Negation is a workaround for HP700 cc bug */
4317 SCM ans = SCM_MAKINUM ((long) u);
4318 if (SCM_INUM (ans) == (long) u)
4319 return ans;
4320 }
e6f3ef58 4321 SCM_ASRTGO (isfinite (u), badz); /* problem? */
f872b822 4322 return scm_dbl2big (u);
0f2d19dd 4323 }
f872b822
MD
4324#else
4325 return SCM_MAKINUM ((long) floor (SCM_REALPART (z) + 0.5));
4326#endif
0f2d19dd 4327}
1bbd0b84 4328#undef FUNC_NAME
0f2d19dd
JB
4329
4330
4331
0f2d19dd 4332#ifdef SCM_BIGDIG
0f2d19dd 4333/* d must be integer */
1cc91f1b 4334
0f2d19dd 4335SCM
6e8d25a6 4336scm_dbl2big (double d)
0f2d19dd
JB
4337{
4338 scm_sizet i = 0;
4339 long c;
4340 SCM_BIGDIG *digits;
4341 SCM ans;
f872b822
MD
4342 double u = (d < 0) ? -d : d;
4343 while (0 != floor (u))
4344 {
4345 u /= SCM_BIGRAD;
4346 i++;
4347 }
4348 ans = scm_mkbig (i, d < 0);
4349 digits = SCM_BDIGITS (ans);
4350 while (i--)
4351 {
4352 u *= SCM_BIGRAD;
4353 c = floor (u);
4354 u -= c;
4355 digits[i] = c;
4356 }
cf7c17e9 4357#ifndef SCM_RECKLESS
e1724d20 4358 if (u != 0)
52859adf 4359 scm_num_overflow ("dbl2big");
e1724d20 4360#endif
0f2d19dd
JB
4361 return ans;
4362}
4363
4364
4365
0f2d19dd 4366double
6e8d25a6 4367scm_big2dbl (SCM b)
0f2d19dd
JB
4368{
4369 double ans = 0.0;
f872b822
MD
4370 scm_sizet i = SCM_NUMDIGS (b);
4371 SCM_BIGDIG *digits = SCM_BDIGITS (b);
4372 while (i--)
4373 ans = digits[i] + SCM_BIGRAD * ans;
f3ae5d60
MD
4374 if (SCM_BIGSIGN (b))
4375 return - ans;
0f2d19dd
JB
4376 return ans;
4377}
f872b822 4378#endif
0f2d19dd 4379
1cc91f1b 4380
0f2d19dd 4381SCM
6e8d25a6 4382scm_long2num (long sl)
0f2d19dd 4383{
f872b822
MD
4384 if (!SCM_FIXABLE (sl))
4385 {
0f2d19dd 4386#ifdef SCM_BIGDIG
f872b822 4387 return scm_long2big (sl);
0f2d19dd 4388#else
f872b822 4389 return scm_makdbl ((double) sl, 0.0);
f872b822
MD
4390#endif
4391 }
4392 return SCM_MAKINUM (sl);
0f2d19dd
JB
4393}
4394
4395
5c11cc9d 4396#ifdef HAVE_LONG_LONGS
1cc91f1b 4397
0f2d19dd 4398SCM
6e8d25a6 4399scm_long_long2num (long_long sl)
0f2d19dd 4400{
f872b822
MD
4401 if (!SCM_FIXABLE (sl))
4402 {
0f2d19dd 4403#ifdef SCM_BIGDIG
f872b822 4404 return scm_long_long2big (sl);
0f2d19dd 4405#else
f872b822 4406 return scm_makdbl ((double) sl, 0.0);
f872b822
MD
4407#endif
4408 }
4409 return SCM_MAKINUM (sl);
0f2d19dd
JB
4410}
4411#endif
4412
4413
1cc91f1b 4414
0f2d19dd 4415SCM
6e8d25a6 4416scm_ulong2num (unsigned long sl)
0f2d19dd 4417{
f872b822
MD
4418 if (!SCM_POSFIXABLE (sl))
4419 {
0f2d19dd 4420#ifdef SCM_BIGDIG
f872b822 4421 return scm_ulong2big (sl);
0f2d19dd 4422#else
f872b822 4423 return scm_makdbl ((double) sl, 0.0);
f872b822
MD
4424#endif
4425 }
4426 return SCM_MAKINUM (sl);
0f2d19dd
JB
4427}
4428
1cc91f1b 4429
0f2d19dd 4430long
6e8d25a6 4431scm_num2long (SCM num, char *pos, const char *s_caller)
0f2d19dd
JB
4432{
4433 long res;
5c11cc9d 4434
f872b822 4435 if (SCM_INUMP (num))
0f2d19dd 4436 {
f872b822 4437 res = SCM_INUM (num);
0f2d19dd
JB
4438 return res;
4439 }
5c11cc9d 4440 SCM_ASRTGO (SCM_NIMP (num), wrong_type_arg);
f3ae5d60 4441 if (SCM_SLOPPY_REALP (num))
0f2d19dd 4442 {
5c11cc9d
GH
4443 volatile double u = SCM_REALPART (num);
4444
0f2d19dd 4445 res = u;
5c11cc9d
GH
4446 if (res != u)
4447 goto out_of_range;
4448 return res;
0f2d19dd 4449 }
0f2d19dd 4450#ifdef SCM_BIGDIG
f872b822
MD
4451 if (SCM_BIGP (num))
4452 {
5c11cc9d 4453 unsigned long oldres = 0;
f872b822 4454 scm_sizet l;
5c11cc9d
GH
4455 /* can't use res directly in case num is -2^31. */
4456 unsigned long pos_res = 0;
4457
f872b822
MD
4458 for (l = SCM_NUMDIGS (num); l--;)
4459 {
5c11cc9d
GH
4460 pos_res = SCM_BIGUP (pos_res) + SCM_BDIGITS (num)[l];
4461 /* check for overflow. */
4462 if (pos_res < oldres)
4463 goto out_of_range;
4464 oldres = pos_res;
f872b822 4465 }
f3ae5d60 4466 if (SCM_BIGSIGN (num))
5c11cc9d 4467 {
f3ae5d60
MD
4468 res = - pos_res;
4469 if (res > 0)
5c11cc9d
GH
4470 goto out_of_range;
4471 }
f872b822 4472 else
5c11cc9d 4473 {
f3ae5d60
MD
4474 res = pos_res;
4475 if (res < 0)
5c11cc9d
GH
4476 goto out_of_range;
4477 }
4478 return res;
f872b822 4479 }
0f2d19dd 4480#endif
5c11cc9d
GH
4481 wrong_type_arg:
4482 scm_wrong_type_arg (s_caller, (int) pos, num);
4483 out_of_range:
4484 scm_out_of_range (s_caller, num);
0f2d19dd
JB
4485}
4486
4487
4488
5c11cc9d 4489#ifdef HAVE_LONG_LONGS
1cc91f1b 4490
0f2d19dd 4491long_long
6e8d25a6 4492scm_num2long_long (SCM num, char *pos, const char *s_caller)
0f2d19dd
JB
4493{
4494 long_long res;
5c11cc9d 4495
f872b822
MD
4496 if (SCM_INUMP (num))
4497 {
5c11cc9d 4498 res = SCM_INUM (num);
0f2d19dd
JB
4499 return res;
4500 }
5c11cc9d 4501 SCM_ASRTGO (SCM_NIMP (num), wrong_type_arg);
f3ae5d60 4502 if (SCM_SLOPPY_REALP (num))
f872b822
MD
4503 {
4504 double u = SCM_REALPART (num);
5c11cc9d
GH
4505
4506 res = u;
4507 if ((res < 0 && u > 0) || (res > 0 && u < 0)) /* check for overflow. */
4508 goto out_of_range;
4509
4510 return res;
f872b822 4511 }
0f2d19dd 4512#ifdef SCM_BIGDIG
f872b822
MD
4513 if (SCM_BIGP (num))
4514 {
5c11cc9d
GH
4515 unsigned long long oldres = 0;
4516 scm_sizet l;
4517 /* can't use res directly in case num is -2^63. */
4518 unsigned long long pos_res = 0;
4519
4520 for (l = SCM_NUMDIGS (num); l--;)
4521 {
4522 pos_res = SCM_LONGLONGBIGUP (pos_res) + SCM_BDIGITS (num)[l];
4523 /* check for overflow. */
4524 if (pos_res < oldres)
4525 goto out_of_range;
4526 oldres = pos_res;
4527 }
f3ae5d60 4528 if (SCM_BIGSIGN (num))
5c11cc9d 4529 {
f3ae5d60
MD
4530 res = - pos_res;
4531 if (res > 0)
5c11cc9d
GH
4532 goto out_of_range;
4533 }
4534 else
4535 {
f3ae5d60
MD
4536 res = pos_res;
4537 if (res < 0)
5c11cc9d
GH
4538 goto out_of_range;
4539 }
f872b822
MD
4540 return res;
4541 }
0f2d19dd 4542#endif
5c11cc9d
GH
4543 wrong_type_arg:
4544 scm_wrong_type_arg (s_caller, (int) pos, num);
4545 out_of_range:
4546 scm_out_of_range (s_caller, num);
0f2d19dd
JB
4547}
4548#endif
4549
4550
1cc91f1b 4551
0f2d19dd 4552unsigned long
6e8d25a6 4553scm_num2ulong (SCM num, char *pos, const char *s_caller)
0f2d19dd
JB
4554{
4555 unsigned long res;
5c11cc9d 4556
f872b822 4557 if (SCM_INUMP (num))
0f2d19dd 4558 {
5c11cc9d
GH
4559 if (SCM_INUM (num) < 0)
4560 goto out_of_range;
4561 res = SCM_INUM (num);
0f2d19dd
JB
4562 return res;
4563 }
5c11cc9d 4564 SCM_ASRTGO (SCM_NIMP (num), wrong_type_arg);
f3ae5d60 4565 if (SCM_SLOPPY_REALP (num))
0f2d19dd 4566 {
f872b822 4567 double u = SCM_REALPART (num);
5c11cc9d
GH
4568
4569 res = u;
4570 if (res != u)
4571 goto out_of_range;
4572 return res;
0f2d19dd 4573 }
0f2d19dd 4574#ifdef SCM_BIGDIG
f872b822
MD
4575 if (SCM_BIGP (num))
4576 {
5c11cc9d 4577 unsigned long oldres = 0;
f872b822 4578 scm_sizet l;
5c11cc9d 4579
f872b822 4580 res = 0;
f872b822
MD
4581 for (l = SCM_NUMDIGS (num); l--;)
4582 {
4583 res = SCM_BIGUP (res) + SCM_BDIGITS (num)[l];
4584 if (res < oldres)
5c11cc9d 4585 goto out_of_range;
f872b822
MD
4586 oldres = res;
4587 }
4588 return res;
4589 }
0f2d19dd 4590#endif
5c11cc9d
GH
4591 wrong_type_arg:
4592 scm_wrong_type_arg (s_caller, (int) pos, num);
4593 out_of_range:
4594 scm_out_of_range (s_caller, num);
0f2d19dd
JB
4595}
4596
4597
f872b822 4598#ifndef DBL_DIG
f872b822 4599static void
6e8d25a6 4600add1 (double f, double *fsum)
0f2d19dd
JB
4601{
4602 *fsum = f + 1.0;
4603}
f872b822 4604#endif
0f2d19dd
JB
4605
4606
1cc91f1b 4607
0f2d19dd
JB
4608void
4609scm_init_numbers ()
0f2d19dd 4610{
f3ae5d60
MD
4611 scm_add_feature ("complex");
4612 scm_add_feature ("inexact");
4613 SCM_NEWREAL (scm_flo0, 0.0);
f872b822 4614#ifdef DBL_DIG
0f2d19dd 4615 scm_dblprec = (DBL_DIG > 20) ? 20 : DBL_DIG;
f872b822 4616#else
0f2d19dd
JB
4617 { /* determine floating point precision */
4618 double f = 0.1;
f872b822
MD
4619 double fsum = 1.0 + f;
4620 while (fsum != 1.0)
4621 {
4622 f /= 10.0;
4623 if (++scm_dblprec > 20)
4624 break;
4625 add1 (f, &fsum);
4626 }
4627 scm_dblprec = scm_dblprec - 1;
0f2d19dd 4628 }
f872b822 4629#endif /* DBL_DIG */
0f2d19dd
JB
4630#include "numbers.x"
4631}