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