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