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