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