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