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