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