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