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