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