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