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