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