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