bb01d7ad308aab252dd77944cb06441ad9bafe9f
[bpt/guile.git] / libguile / numbers.c
1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002 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_GPROC (s_abs, "abs", 1, 0, 0, scm_abs, g_abs);
293 /* "Return the absolute value of @var{x}."
294 */
295 SCM
296 scm_abs (SCM x)
297 {
298 if (SCM_INUMP (x)) {
299 long int xx = SCM_INUM (x);
300 if (xx >= 0) {
301 return x;
302 } else if (SCM_POSFIXABLE (-xx)) {
303 return SCM_MAKINUM (-xx);
304 } else {
305 #ifdef SCM_BIGDIG
306 return scm_i_long2big (-xx);
307 #else
308 scm_num_overflow (s_abs);
309 #endif
310 }
311 } else if (SCM_BIGP (x)) {
312 if (!SCM_BIGSIGN (x)) {
313 return x;
314 } else {
315 return scm_i_copybig (x, 0);
316 }
317 } else if (SCM_REALP (x)) {
318 return scm_make_real (fabs (SCM_REAL_VALUE (x)));
319 } else {
320 SCM_WTA_DISPATCH_1 (g_abs, x, 1, s_abs);
321 }
322 }
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 if (SCM_EQ_P (n, SCM_INUM0) || SCM_EQ_P (n, acc))
1248 return n;
1249 else if (SCM_EQ_P (n, SCM_MAKINUM (-1L)))
1250 return SCM_FALSEP (scm_even_p (k)) ? n : acc;
1251 #endif
1252 if (SCM_REALP (k))
1253 {
1254 double r = SCM_REAL_VALUE (k);
1255 i2 = r;
1256 if (i2 != r)
1257 SCM_WRONG_TYPE_ARG (2, k);
1258 }
1259 else
1260 SCM_VALIDATE_ULONG_COPY (2, k, i2);
1261 if (i2 < 0)
1262 {
1263 i2 = -i2;
1264 n = scm_divide (n, SCM_UNDEFINED);
1265 }
1266 while (1)
1267 {
1268 if (0 == i2)
1269 return acc;
1270 if (1 == i2)
1271 return scm_product (acc, n);
1272 if (i2 & 1)
1273 acc = scm_product (acc, n);
1274 n = scm_product (n, n);
1275 i2 >>= 1;
1276 }
1277 }
1278 #undef FUNC_NAME
1279
1280 SCM_DEFINE (scm_ash, "ash", 2, 0, 0,
1281 (SCM n, SCM cnt),
1282 "The function ash performs an arithmetic shift left by @var{cnt}\n"
1283 "bits (or shift right, if @var{cnt} is negative). 'Arithmetic'\n"
1284 "means, that the function does not guarantee to keep the bit\n"
1285 "structure of @var{n}, but rather guarantees that the result\n"
1286 "will always be rounded towards minus infinity. Therefore, the\n"
1287 "results of ash and a corresponding bitwise shift will differ if\n"
1288 "@var{n} is negative.\n"
1289 "\n"
1290 "Formally, the function returns an integer equivalent to\n"
1291 "@code{(inexact->exact (floor (* @var{n} (expt 2 @var{cnt}))))}.\n"
1292 "\n"
1293 "@lisp\n"
1294 "(number->string (ash #b1 3) 2) @result{} \"1000\"\n"
1295 "(number->string (ash #b1010 -1) 2) @result{} \"101\"\n"
1296 "@end lisp")
1297 #define FUNC_NAME s_scm_ash
1298 {
1299 long bits_to_shift;
1300
1301 #ifndef SCM_BIGDIG
1302 SCM_VALIDATE_INUM (1, n)
1303 #endif
1304 SCM_VALIDATE_INUM (2, cnt);
1305
1306 bits_to_shift = SCM_INUM (cnt);
1307 #ifdef SCM_BIGDIG
1308 if (bits_to_shift < 0) {
1309 /* Shift right by abs(cnt) bits. This is realized as a division by
1310 div:=2^abs(cnt). However, to guarantee the floor rounding, negative
1311 values require some special treatment.
1312 */
1313 SCM div = scm_integer_expt (SCM_MAKINUM (2), SCM_MAKINUM (-bits_to_shift));
1314 if (SCM_FALSEP (scm_negative_p (n)))
1315 return scm_quotient (n, div);
1316 else
1317 return scm_sum (SCM_MAKINUM (-1L),
1318 scm_quotient (scm_sum (SCM_MAKINUM (1L), n), div));
1319 } else
1320 /* Shift left is done by multiplication with 2^CNT */
1321 return scm_product (n, scm_integer_expt (SCM_MAKINUM (2), cnt));
1322 #else
1323 if (bits_to_shift < 0)
1324 /* Signed right shift (SCM_SRS does it right) by abs(cnt) bits. */
1325 return SCM_MAKINUM (SCM_SRS (SCM_INUM (n), -bits_to_shift));
1326 else {
1327 /* Shift left, but make sure not to leave the range of inums */
1328 SCM res = SCM_MAKINUM (SCM_INUM (n) << cnt);
1329 if (SCM_INUM (res) >> cnt != SCM_INUM (n))
1330 scm_num_overflow (FUNC_NAME);
1331 return res;
1332 }
1333 #endif
1334 }
1335 #undef FUNC_NAME
1336
1337
1338 SCM_DEFINE (scm_bit_extract, "bit-extract", 3, 0, 0,
1339 (SCM n, SCM start, SCM end),
1340 "Return the integer composed of the @var{start} (inclusive)\n"
1341 "through @var{end} (exclusive) bits of @var{n}. The\n"
1342 "@var{start}th bit becomes the 0-th bit in the result.\n"
1343 "\n"
1344 "@lisp\n"
1345 "(number->string (bit-extract #b1101101010 0 4) 2)\n"
1346 " @result{} \"1010\"\n"
1347 "(number->string (bit-extract #b1101101010 4 9) 2)\n"
1348 " @result{} \"10110\"\n"
1349 "@end lisp")
1350 #define FUNC_NAME s_scm_bit_extract
1351 {
1352 unsigned long int istart, iend;
1353 SCM_VALIDATE_INUM_MIN_COPY (2, start,0, istart);
1354 SCM_VALIDATE_INUM_MIN_COPY (3, end, 0, iend);
1355 SCM_ASSERT_RANGE (3, end, (iend >= istart));
1356
1357 if (SCM_INUMP (n)) {
1358 long int in = SCM_INUM (n);
1359 unsigned long int bits = iend - istart;
1360
1361 if (in < 0 && bits >= SCM_I_FIXNUM_BIT)
1362 {
1363 /* Since we emulate two's complement encoded numbers, this special
1364 * case requires us to produce a result that has more bits than can be
1365 * stored in a fixnum. Thus, we fall back to the more general
1366 * algorithm that is used for bignums.
1367 */
1368 goto generalcase;
1369 }
1370
1371 if (istart < SCM_I_FIXNUM_BIT)
1372 {
1373 in = in >> istart;
1374 if (bits < SCM_I_FIXNUM_BIT)
1375 return SCM_MAKINUM (in & ((1L << bits) - 1));
1376 else /* we know: in >= 0 */
1377 return SCM_MAKINUM (in);
1378 }
1379 else if (in < 0)
1380 {
1381 return SCM_MAKINUM (-1L & ((1L << bits) - 1));
1382 }
1383 else
1384 {
1385 return SCM_MAKINUM (0);
1386 }
1387 } else if (SCM_BIGP (n)) {
1388 generalcase:
1389 {
1390 SCM num1 = SCM_MAKINUM (1L);
1391 SCM num2 = SCM_MAKINUM (2L);
1392 SCM bits = SCM_MAKINUM (iend - istart);
1393 SCM mask = scm_difference (scm_integer_expt (num2, bits), num1);
1394 return scm_logand (mask, scm_ash (n, SCM_MAKINUM (-istart)));
1395 }
1396 } else {
1397 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1398 }
1399 }
1400 #undef FUNC_NAME
1401
1402
1403 static const char scm_logtab[] = {
1404 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
1405 };
1406
1407 SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
1408 (SCM n),
1409 "Return the number of bits in integer @var{n}. If integer is\n"
1410 "positive, the 1-bits in its binary representation are counted.\n"
1411 "If negative, the 0-bits in its two's-complement binary\n"
1412 "representation are counted. If 0, 0 is returned.\n"
1413 "\n"
1414 "@lisp\n"
1415 "(logcount #b10101010)\n"
1416 " @result{} 4\n"
1417 "(logcount 0)\n"
1418 " @result{} 0\n"
1419 "(logcount -2)\n"
1420 " @result{} 1\n"
1421 "@end lisp")
1422 #define FUNC_NAME s_scm_logcount
1423 {
1424 if (SCM_INUMP (n)) {
1425 unsigned long int c = 0;
1426 long int nn = SCM_INUM (n);
1427 if (nn < 0) {
1428 nn = -1 - nn;
1429 };
1430 while (nn) {
1431 c += scm_logtab[15 & nn];
1432 nn >>= 4;
1433 };
1434 return SCM_MAKINUM (c);
1435 } else if (SCM_BIGP (n)) {
1436 if (SCM_BIGSIGN (n)) {
1437 return scm_logcount (scm_difference (SCM_MAKINUM (-1L), n));
1438 } else {
1439 unsigned long int c = 0;
1440 size_t i = SCM_NUMDIGS (n);
1441 SCM_BIGDIG * ds = SCM_BDIGITS (n);
1442 while (i--) {
1443 SCM_BIGDIG d;
1444 for (d = ds[i]; d; d >>= 4) {
1445 c += scm_logtab[15 & d];
1446 }
1447 }
1448 return SCM_MAKINUM (c);
1449 }
1450 } else {
1451 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1452 }
1453 }
1454 #undef FUNC_NAME
1455
1456
1457 static const char scm_ilentab[] = {
1458 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
1459 };
1460
1461 SCM_DEFINE (scm_integer_length, "integer-length", 1, 0, 0,
1462 (SCM n),
1463 "Return the number of bits necessary to represent @var{n}.\n"
1464 "\n"
1465 "@lisp\n"
1466 "(integer-length #b10101010)\n"
1467 " @result{} 8\n"
1468 "(integer-length 0)\n"
1469 " @result{} 0\n"
1470 "(integer-length #b1111)\n"
1471 " @result{} 4\n"
1472 "@end lisp")
1473 #define FUNC_NAME s_scm_integer_length
1474 {
1475 if (SCM_INUMP (n)) {
1476 unsigned long int c = 0;
1477 unsigned int l = 4;
1478 long int nn = SCM_INUM (n);
1479 if (nn < 0) {
1480 nn = -1 - nn;
1481 };
1482 while (nn) {
1483 c += 4;
1484 l = scm_ilentab [15 & nn];
1485 nn >>= 4;
1486 };
1487 return SCM_MAKINUM (c - 4 + l);
1488 } else if (SCM_BIGP (n)) {
1489 if (SCM_BIGSIGN (n)) {
1490 return scm_integer_length (scm_difference (SCM_MAKINUM (-1L), n));
1491 } else {
1492 unsigned long int digs = SCM_NUMDIGS (n) - 1;
1493 unsigned long int c = digs * SCM_BITSPERDIG;
1494 unsigned int l = 4;
1495 SCM_BIGDIG * ds = SCM_BDIGITS (n);
1496 SCM_BIGDIG d = ds [digs];
1497 while (d) {
1498 c += 4;
1499 l = scm_ilentab [15 & d];
1500 d >>= 4;
1501 };
1502 return SCM_MAKINUM (c - 4 + l);
1503 }
1504 } else {
1505 SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
1506 }
1507 }
1508 #undef FUNC_NAME
1509
1510
1511 #ifdef SCM_BIGDIG
1512 static const char s_bignum[] = "bignum";
1513
1514 SCM
1515 scm_i_mkbig (size_t nlen, int sign)
1516 {
1517 SCM v;
1518 SCM_BIGDIG *base;
1519
1520 if (((nlen << SCM_BIGSIZEFIELD) >> SCM_BIGSIZEFIELD) != nlen)
1521 scm_memory_error (s_bignum);
1522
1523 base = scm_gc_malloc (nlen * sizeof (SCM_BIGDIG), s_bignum);
1524
1525 v = scm_cell (SCM_MAKE_BIGNUM_TAG (nlen, sign), (scm_t_bits) base);
1526 return v;
1527 }
1528
1529 SCM
1530 scm_i_big2inum (SCM b, size_t l)
1531 {
1532 unsigned long num = 0;
1533 SCM_BIGDIG *tmp = SCM_BDIGITS (b);
1534 while (l--)
1535 num = SCM_BIGUP (num) + tmp[l];
1536 if (!SCM_BIGSIGN (b))
1537 {
1538 if (SCM_POSFIXABLE (num))
1539 return SCM_MAKINUM (num);
1540 }
1541 else if (num <= -SCM_MOST_NEGATIVE_FIXNUM)
1542 return SCM_MAKINUM (-num);
1543 return b;
1544 }
1545
1546 static const char s_adjbig[] = "scm_i_adjbig";
1547
1548 SCM
1549 scm_i_adjbig (SCM b, size_t nlen)
1550 {
1551 size_t nsiz = nlen;
1552 if (((nsiz << SCM_BIGSIZEFIELD) >> SCM_BIGSIZEFIELD) != nlen)
1553 scm_memory_error (s_adjbig);
1554
1555 SCM_DEFER_INTS;
1556 {
1557 SCM_BIGDIG *digits
1558 = ((SCM_BIGDIG *)
1559 scm_gc_realloc (SCM_BDIGITS (b),
1560 SCM_NUMDIGS (b) * sizeof (SCM_BIGDIG),
1561 nsiz * sizeof (SCM_BIGDIG), s_bignum));
1562
1563 SCM_SET_BIGNUM_BASE (b, digits);
1564 SCM_SETNUMDIGS (b, nsiz, SCM_BIGSIGN (b));
1565 }
1566 SCM_ALLOW_INTS;
1567 return b;
1568 }
1569
1570 SCM
1571 scm_i_normbig (SCM b)
1572 {
1573 #ifndef _UNICOS
1574 size_t nlen = SCM_NUMDIGS (b);
1575 #else
1576 int nlen = SCM_NUMDIGS (b); /* unsigned nlen breaks on Cray when nlen => 0 */
1577 #endif
1578 SCM_BIGDIG *zds = SCM_BDIGITS (b);
1579 while (nlen-- && !zds[nlen]);
1580 nlen++;
1581 if (nlen * SCM_BITSPERDIG / SCM_CHAR_BIT <= sizeof (SCM))
1582 if (SCM_INUMP (b = scm_i_big2inum (b, (size_t) nlen)))
1583 return b;
1584 if (SCM_NUMDIGS (b) == nlen)
1585 return b;
1586 return scm_i_adjbig (b, (size_t) nlen);
1587 }
1588
1589 SCM
1590 scm_i_copybig (SCM b, int sign)
1591 {
1592 size_t i = SCM_NUMDIGS (b);
1593 SCM ans = scm_i_mkbig (i, sign);
1594 SCM_BIGDIG *src = SCM_BDIGITS (b), *dst = SCM_BDIGITS (ans);
1595 while (i--)
1596 dst[i] = src[i];
1597 return ans;
1598 }
1599
1600 int
1601 scm_bigcomp (SCM x, SCM y)
1602 {
1603 int xsign = SCM_BIGSIGN (x);
1604 int ysign = SCM_BIGSIGN (y);
1605 size_t xlen, ylen;
1606
1607 /* Look at the signs, first. */
1608 if (ysign < xsign)
1609 return 1;
1610 if (ysign > xsign)
1611 return -1;
1612
1613 /* They're the same sign, so see which one has more digits. Note
1614 that, if they are negative, the longer number is the lesser. */
1615 ylen = SCM_NUMDIGS (y);
1616 xlen = SCM_NUMDIGS (x);
1617 if (ylen > xlen)
1618 return (xsign) ? -1 : 1;
1619 if (ylen < xlen)
1620 return (xsign) ? 1 : -1;
1621
1622 /* They have the same number of digits, so find the most significant
1623 digit where they differ. */
1624 while (xlen)
1625 {
1626 --xlen;
1627 if (SCM_BDIGITS (y)[xlen] != SCM_BDIGITS (x)[xlen])
1628 /* Make the discrimination based on the digit that differs. */
1629 return ((SCM_BDIGITS (y)[xlen] > SCM_BDIGITS (x)[xlen])
1630 ? (xsign ? -1 : 1)
1631 : (xsign ? 1 : -1));
1632 }
1633
1634 /* The numbers are identical. */
1635 return 0;
1636 }
1637
1638 #ifndef SCM_DIGSTOOBIG
1639
1640
1641 long
1642 scm_pseudolong (long x)
1643 {
1644 union
1645 {
1646 long l;
1647 SCM_BIGDIG bd[SCM_DIGSPERLONG];
1648 }
1649 p;
1650 size_t i = 0;
1651 if (x < 0)
1652 x = -x;
1653 while (i < SCM_DIGSPERLONG)
1654 {
1655 p.bd[i++] = SCM_BIGLO (x);
1656 x = SCM_BIGDN (x);
1657 }
1658 /* p.bd[0] = SCM_BIGLO(x); p.bd[1] = SCM_BIGDN(x); */
1659 return p.l;
1660 }
1661
1662 #else
1663
1664
1665 void
1666 scm_longdigs (long x, SCM_BIGDIG digs[])
1667 {
1668 size_t i = 0;
1669 if (x < 0)
1670 x = -x;
1671 while (i < SCM_DIGSPERLONG)
1672 {
1673 digs[i++] = SCM_BIGLO (x);
1674 x = SCM_BIGDN (x);
1675 }
1676 }
1677 #endif
1678
1679
1680
1681 SCM
1682 scm_addbig (SCM_BIGDIG *x, size_t nx, int xsgn, SCM bigy, int sgny)
1683 {
1684 /* Assumes nx <= SCM_NUMDIGS(bigy) */
1685 /* Assumes xsgn and sgny scm_equal either 0 or SCM_BIGSIGNFLAG */
1686 long num = 0;
1687 size_t i = 0, ny = SCM_NUMDIGS (bigy);
1688 SCM z = scm_i_copybig (bigy, SCM_BIGSIGN (bigy) ^ sgny);
1689 SCM_BIGDIG *zds = SCM_BDIGITS (z);
1690 if (xsgn ^ SCM_BIGSIGN (z))
1691 {
1692 do
1693 {
1694 num += (long) zds[i] - x[i];
1695 if (num < 0)
1696 {
1697 zds[i] = num + SCM_BIGRAD;
1698 num = -1;
1699 }
1700 else
1701 {
1702 zds[i] = SCM_BIGLO (num);
1703 num = 0;
1704 }
1705 }
1706 while (++i < nx);
1707 if (num && nx == ny)
1708 {
1709 num = 1;
1710 i = 0;
1711 SCM_SET_CELL_WORD_0 (z, SCM_CELL_WORD_0 (z) ^ SCM_BIGSIGNFLAG);
1712 do
1713 {
1714 num += (SCM_BIGRAD - 1) - zds[i];
1715 zds[i++] = SCM_BIGLO (num);
1716 num = SCM_BIGDN (num);
1717 }
1718 while (i < ny);
1719 }
1720 else
1721 while (i < ny)
1722 {
1723 num += zds[i];
1724 if (num < 0)
1725 {
1726 zds[i++] = num + SCM_BIGRAD;
1727 num = -1;
1728 }
1729 else
1730 {
1731 zds[i++] = SCM_BIGLO (num);
1732 num = 0;
1733 }
1734 }
1735 }
1736 else
1737 {
1738 do
1739 {
1740 num += (long) zds[i] + x[i];
1741 zds[i++] = SCM_BIGLO (num);
1742 num = SCM_BIGDN (num);
1743 }
1744 while (i < nx);
1745 if (!num)
1746 return z;
1747 while (i < ny)
1748 {
1749 num += zds[i];
1750 zds[i++] = SCM_BIGLO (num);
1751 num = SCM_BIGDN (num);
1752 if (!num)
1753 return z;
1754 }
1755 if (num)
1756 {
1757 z = scm_i_adjbig (z, ny + 1);
1758 SCM_BDIGITS (z)[ny] = num;
1759 return z;
1760 }
1761 }
1762 return scm_i_normbig (z);
1763 }
1764
1765
1766 SCM
1767 scm_mulbig (SCM_BIGDIG *x, size_t nx, SCM_BIGDIG *y, size_t ny, int sgn)
1768 {
1769 size_t i = 0, j = nx + ny;
1770 unsigned long n = 0;
1771 SCM z = scm_i_mkbig (j, sgn);
1772 SCM_BIGDIG *zds = SCM_BDIGITS (z);
1773 while (j--)
1774 zds[j] = 0;
1775 do
1776 {
1777 j = 0;
1778 if (x[i])
1779 {
1780 do
1781 {
1782 n += zds[i + j] + ((unsigned long) x[i] * y[j]);
1783 zds[i + j++] = SCM_BIGLO (n);
1784 n = SCM_BIGDN (n);
1785 }
1786 while (j < ny);
1787 if (n)
1788 {
1789 zds[i + j] = n;
1790 n = 0;
1791 }
1792 }
1793 }
1794 while (++i < nx);
1795 return scm_i_normbig (z);
1796 }
1797
1798
1799 unsigned int
1800 scm_divbigdig (SCM_BIGDIG * ds, size_t h, SCM_BIGDIG div)
1801 {
1802 register unsigned long t2 = 0;
1803 while (h--)
1804 {
1805 t2 = SCM_BIGUP (t2) + ds[h];
1806 ds[h] = t2 / div;
1807 t2 %= div;
1808 }
1809 return t2;
1810 }
1811
1812
1813
1814 static SCM
1815 scm_divbigint (SCM x, long z, int sgn, int mode)
1816 {
1817 if (z < 0)
1818 z = -z;
1819 if (z < SCM_BIGRAD)
1820 {
1821 register unsigned long t2 = 0;
1822 register SCM_BIGDIG *ds = SCM_BDIGITS (x);
1823 size_t nd = SCM_NUMDIGS (x);
1824 while (nd--)
1825 t2 = (SCM_BIGUP (t2) + ds[nd]) % z;
1826 if (mode && t2)
1827 t2 = z - t2;
1828 return SCM_MAKINUM (sgn ? -t2 : t2);
1829 }
1830 {
1831 #ifndef SCM_DIGSTOOBIG
1832 unsigned long t2 = scm_pseudolong (z);
1833 return scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
1834 (SCM_BIGDIG *) & t2, SCM_DIGSPERLONG,
1835 sgn, mode);
1836 #else
1837 SCM_BIGDIG t2[SCM_DIGSPERLONG];
1838 scm_longdigs (z, t2);
1839 return scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
1840 t2, SCM_DIGSPERLONG,
1841 sgn, mode);
1842 #endif
1843 }
1844 }
1845
1846
1847 static SCM
1848 scm_divbigbig (SCM_BIGDIG *x, size_t nx, SCM_BIGDIG *y, size_t ny, int sgn, int modes)
1849 {
1850 /* modes description
1851 0 remainder
1852 1 scm_modulo
1853 2 quotient
1854 3 quotient but returns SCM_UNDEFINED if division is not exact. */
1855 size_t i = 0, j = 0;
1856 long num = 0;
1857 unsigned long t2 = 0;
1858 SCM z, newy;
1859 SCM_BIGDIG d = 0, qhat, *zds, *yds;
1860 /* algorithm requires nx >= ny */
1861 if (nx < ny)
1862 switch (modes)
1863 {
1864 case 0: /* remainder -- just return x */
1865 z = scm_i_mkbig (nx, sgn);
1866 zds = SCM_BDIGITS (z);
1867 do
1868 {
1869 zds[i] = x[i];
1870 }
1871 while (++i < nx);
1872 return z;
1873 case 1: /* scm_modulo -- return y-x */
1874 z = scm_i_mkbig (ny, sgn);
1875 zds = SCM_BDIGITS (z);
1876 do
1877 {
1878 num += (long) y[i] - x[i];
1879 if (num < 0)
1880 {
1881 zds[i] = num + SCM_BIGRAD;
1882 num = -1;
1883 }
1884 else
1885 {
1886 zds[i] = num;
1887 num = 0;
1888 }
1889 }
1890 while (++i < nx);
1891 while (i < ny)
1892 {
1893 num += y[i];
1894 if (num < 0)
1895 {
1896 zds[i++] = num + SCM_BIGRAD;
1897 num = -1;
1898 }
1899 else
1900 {
1901 zds[i++] = num;
1902 num = 0;
1903 }
1904 }
1905 goto doadj;
1906 case 2:
1907 return SCM_INUM0; /* quotient is zero */
1908 case 3:
1909 return SCM_UNDEFINED; /* the division is not exact */
1910 }
1911
1912 z = scm_i_mkbig (nx == ny ? nx + 2 : nx + 1, sgn);
1913 zds = SCM_BDIGITS (z);
1914 if (nx == ny)
1915 zds[nx + 1] = 0;
1916 while (!y[ny - 1])
1917 ny--; /* in case y came in as a psuedolong */
1918 if (y[ny - 1] < (SCM_BIGRAD >> 1))
1919 { /* normalize operands */
1920 d = SCM_BIGRAD / (y[ny - 1] + 1);
1921 newy = scm_i_mkbig (ny, 0);
1922 yds = SCM_BDIGITS (newy);
1923 while (j < ny)
1924 {
1925 t2 += (unsigned long) y[j] * d;
1926 yds[j++] = SCM_BIGLO (t2);
1927 t2 = SCM_BIGDN (t2);
1928 }
1929 y = yds;
1930 j = 0;
1931 t2 = 0;
1932 while (j < nx)
1933 {
1934 t2 += (unsigned long) x[j] * d;
1935 zds[j++] = SCM_BIGLO (t2);
1936 t2 = SCM_BIGDN (t2);
1937 }
1938 zds[j] = t2;
1939 }
1940 else
1941 {
1942 zds[j = nx] = 0;
1943 while (j--)
1944 zds[j] = x[j];
1945 }
1946 j = nx == ny ? nx + 1 : nx; /* dividend needs more digits than divisor */
1947 do
1948 { /* loop over digits of quotient */
1949 if (zds[j] == y[ny - 1])
1950 qhat = SCM_BIGRAD - 1;
1951 else
1952 qhat = (SCM_BIGUP (zds[j]) + zds[j - 1]) / y[ny - 1];
1953 if (!qhat)
1954 continue;
1955 i = 0;
1956 num = 0;
1957 t2 = 0;
1958 do
1959 { /* multiply and subtract */
1960 t2 += (unsigned long) y[i] * qhat;
1961 num += zds[j - ny + i] - SCM_BIGLO (t2);
1962 if (num < 0)
1963 {
1964 zds[j - ny + i] = num + SCM_BIGRAD;
1965 num = -1;
1966 }
1967 else
1968 {
1969 zds[j - ny + i] = num;
1970 num = 0;
1971 }
1972 t2 = SCM_BIGDN (t2);
1973 }
1974 while (++i < ny);
1975 num += zds[j - ny + i] - t2; /* borrow from high digit; don't update */
1976 while (num)
1977 { /* "add back" required */
1978 i = 0;
1979 num = 0;
1980 qhat--;
1981 do
1982 {
1983 num += (long) zds[j - ny + i] + y[i];
1984 zds[j - ny + i] = SCM_BIGLO (num);
1985 num = SCM_BIGDN (num);
1986 }
1987 while (++i < ny);
1988 num--;
1989 }
1990 if (modes & 2)
1991 zds[j] = qhat;
1992 }
1993 while (--j >= ny);
1994 switch (modes)
1995 {
1996 case 3: /* check that remainder==0 */
1997 for (j = ny; j && !zds[j - 1]; --j);
1998 if (j)
1999 return SCM_UNDEFINED;
2000 case 2: /* move quotient down in z */
2001 j = (nx == ny ? nx + 2 : nx + 1) - ny;
2002 for (i = 0; i < j; i++)
2003 zds[i] = zds[i + ny];
2004 ny = i;
2005 break;
2006 case 1: /* subtract for scm_modulo */
2007 i = 0;
2008 num = 0;
2009 j = 0;
2010 do
2011 {
2012 num += y[i] - zds[i];
2013 j = j | zds[i];
2014 if (num < 0)
2015 {
2016 zds[i] = num + SCM_BIGRAD;
2017 num = -1;
2018 }
2019 else
2020 {
2021 zds[i] = num;
2022 num = 0;
2023 }
2024 }
2025 while (++i < ny);
2026 if (!j)
2027 return SCM_INUM0;
2028 case 0: /* just normalize remainder */
2029 if (d)
2030 scm_divbigdig (zds, ny, d);
2031 }
2032 doadj:
2033 for (j = ny; j && !zds[j - 1]; --j);
2034 if (j * SCM_BITSPERDIG <= sizeof (SCM) * SCM_CHAR_BIT)
2035 if (SCM_INUMP (z = scm_i_big2inum (z, j)))
2036 return z;
2037 return scm_i_adjbig (z, j);
2038 }
2039 #endif
2040 \f
2041
2042
2043
2044
2045 /*** NUMBERS -> STRINGS ***/
2046 int scm_dblprec;
2047 static const double fx[] =
2048 { 0.0, 5e-1, 5e-2, 5e-3, 5e-4, 5e-5,
2049 5e-6, 5e-7, 5e-8, 5e-9, 5e-10,
2050 5e-11, 5e-12, 5e-13, 5e-14, 5e-15,
2051 5e-16, 5e-17, 5e-18, 5e-19, 5e-20};
2052
2053
2054
2055
2056 static size_t
2057 idbl2str (double f, char *a)
2058 {
2059 int efmt, dpt, d, i, wp = scm_dblprec;
2060 size_t ch = 0;
2061 int exp = 0;
2062
2063 if (f == 0.0)
2064 {
2065 #ifdef HAVE_COPYSIGN
2066 double sgn = copysign (1.0, f);
2067
2068 if (sgn < 0.0)
2069 a[ch++] = '-';
2070 #endif
2071
2072 goto zero; /*{a[0]='0'; a[1]='.'; a[2]='0'; return 3;} */
2073 }
2074
2075 if (xisinf (f))
2076 {
2077 if (f < 0)
2078 strcpy (a, "-inf.0");
2079 else
2080 strcpy (a, "+inf.0");
2081 return ch+6;
2082 }
2083 else if (xisnan (f))
2084 {
2085 strcpy (a, "+nan.0");
2086 return ch+6;
2087 }
2088
2089 if (f < 0.0)
2090 {
2091 f = -f;
2092 a[ch++] = '-';
2093 }
2094
2095 #ifdef DBL_MIN_10_EXP /* Prevent unnormalized values, as from
2096 make-uniform-vector, from causing infinite loops. */
2097 while (f < 1.0)
2098 {
2099 f *= 10.0;
2100 if (exp-- < DBL_MIN_10_EXP)
2101 {
2102 a[ch++] = '#';
2103 a[ch++] = '.';
2104 a[ch++] = '#';
2105 return ch;
2106 }
2107 }
2108 while (f > 10.0)
2109 {
2110 f *= 0.10;
2111 if (exp++ > DBL_MAX_10_EXP)
2112 {
2113 a[ch++] = '#';
2114 a[ch++] = '.';
2115 a[ch++] = '#';
2116 return ch;
2117 }
2118 }
2119 #else
2120 while (f < 1.0)
2121 {
2122 f *= 10.0;
2123 exp--;
2124 }
2125 while (f > 10.0)
2126 {
2127 f /= 10.0;
2128 exp++;
2129 }
2130 #endif
2131 if (f + fx[wp] >= 10.0)
2132 {
2133 f = 1.0;
2134 exp++;
2135 }
2136 zero:
2137 #ifdef ENGNOT
2138 dpt = (exp + 9999) % 3;
2139 exp -= dpt++;
2140 efmt = 1;
2141 #else
2142 efmt = (exp < -3) || (exp > wp + 2);
2143 if (!efmt)
2144 {
2145 if (exp < 0)
2146 {
2147 a[ch++] = '0';
2148 a[ch++] = '.';
2149 dpt = exp;
2150 while (++dpt)
2151 a[ch++] = '0';
2152 }
2153 else
2154 dpt = exp + 1;
2155 }
2156 else
2157 dpt = 1;
2158 #endif
2159
2160 do
2161 {
2162 d = f;
2163 f -= d;
2164 a[ch++] = d + '0';
2165 if (f < fx[wp])
2166 break;
2167 if (f + fx[wp] >= 1.0)
2168 {
2169 a[ch - 1]++;
2170 break;
2171 }
2172 f *= 10.0;
2173 if (!(--dpt))
2174 a[ch++] = '.';
2175 }
2176 while (wp--);
2177
2178 if (dpt > 0)
2179 {
2180 #ifndef ENGNOT
2181 if ((dpt > 4) && (exp > 6))
2182 {
2183 d = (a[0] == '-' ? 2 : 1);
2184 for (i = ch++; i > d; i--)
2185 a[i] = a[i - 1];
2186 a[d] = '.';
2187 efmt = 1;
2188 }
2189 else
2190 #endif
2191 {
2192 while (--dpt)
2193 a[ch++] = '0';
2194 a[ch++] = '.';
2195 }
2196 }
2197 if (a[ch - 1] == '.')
2198 a[ch++] = '0'; /* trailing zero */
2199 if (efmt && exp)
2200 {
2201 a[ch++] = 'e';
2202 if (exp < 0)
2203 {
2204 exp = -exp;
2205 a[ch++] = '-';
2206 }
2207 for (i = 10; i <= exp; i *= 10);
2208 for (i /= 10; i; i /= 10)
2209 {
2210 a[ch++] = exp / i + '0';
2211 exp %= i;
2212 }
2213 }
2214 return ch;
2215 }
2216
2217
2218 static size_t
2219 iflo2str (SCM flt, char *str)
2220 {
2221 size_t i;
2222 if (SCM_REALP (flt))
2223 i = idbl2str (SCM_REAL_VALUE (flt), str);
2224 else
2225 {
2226 i = idbl2str (SCM_COMPLEX_REAL (flt), str);
2227 if (SCM_COMPLEX_IMAG (flt) != 0.0)
2228 {
2229 double imag = SCM_COMPLEX_IMAG (flt);
2230 /* Don't output a '+' for negative numbers or for Inf and
2231 NaN. They will provide their own sign. */
2232 if (0 <= imag && !xisinf (imag) && !xisnan (imag))
2233 str[i++] = '+';
2234 i += idbl2str (imag, &str[i]);
2235 str[i++] = 'i';
2236 }
2237 }
2238 return i;
2239 }
2240
2241 /* convert a long to a string (unterminated). returns the number of
2242 characters in the result.
2243 rad is output base
2244 p is destination: worst case (base 2) is SCM_INTBUFLEN */
2245 size_t
2246 scm_iint2str (long num, int rad, char *p)
2247 {
2248 size_t j = 1;
2249 size_t i;
2250 unsigned long n = (num < 0) ? -num : num;
2251
2252 for (n /= rad; n > 0; n /= rad)
2253 j++;
2254
2255 i = j;
2256 if (num < 0)
2257 {
2258 *p++ = '-';
2259 j++;
2260 n = -num;
2261 }
2262 else
2263 n = num;
2264 while (i--)
2265 {
2266 int d = n % rad;
2267
2268 n /= rad;
2269 p[i] = d + ((d < 10) ? '0' : 'a' - 10);
2270 }
2271 return j;
2272 }
2273
2274
2275 #ifdef SCM_BIGDIG
2276
2277 static SCM
2278 big2str (SCM b, unsigned int radix)
2279 {
2280 SCM t = scm_i_copybig (b, 0); /* sign of temp doesn't matter */
2281 register SCM_BIGDIG *ds = SCM_BDIGITS (t);
2282 size_t i = SCM_NUMDIGS (t);
2283 size_t j = radix == 16 ? (SCM_BITSPERDIG * i) / 4 + 2
2284 : radix >= 10 ? (SCM_BITSPERDIG * i * 241L) / 800 + 2
2285 : (SCM_BITSPERDIG * i) + 2;
2286 size_t k = 0;
2287 size_t radct = 0;
2288 SCM_BIGDIG radpow = 1, radmod = 0;
2289 SCM ss = scm_allocate_string (j);
2290 char *s = SCM_STRING_CHARS (ss), c;
2291
2292 if (i == 0)
2293 {
2294 return scm_makfrom0str ("0");
2295 }
2296
2297 while ((long) radpow * radix < SCM_BIGRAD)
2298 {
2299 radpow *= radix;
2300 radct++;
2301 }
2302 while ((i || radmod) && j)
2303 {
2304 if (k == 0)
2305 {
2306 radmod = (SCM_BIGDIG) scm_divbigdig (ds, i, radpow);
2307 k = radct;
2308 if (!ds[i - 1])
2309 i--;
2310 }
2311 c = radmod % radix;
2312 radmod /= radix;
2313 k--;
2314 s[--j] = c < 10 ? c + '0' : c + 'a' - 10;
2315 }
2316
2317 if (SCM_BIGSIGN (b))
2318 s[--j] = '-';
2319
2320 if (j > 0)
2321 {
2322 /* The pre-reserved string length was too large. */
2323 unsigned long int length = SCM_STRING_LENGTH (ss);
2324 ss = scm_substring (ss, SCM_MAKINUM (j), SCM_MAKINUM (length));
2325 }
2326
2327 return scm_return_first (ss, t);
2328 }
2329 #endif
2330
2331
2332 SCM_DEFINE (scm_number_to_string, "number->string", 1, 1, 0,
2333 (SCM n, SCM radix),
2334 "Return a string holding the external representation of the\n"
2335 "number @var{n} in the given @var{radix}. If @var{n} is\n"
2336 "inexact, a radix of 10 will be used.")
2337 #define FUNC_NAME s_scm_number_to_string
2338 {
2339 int base;
2340
2341 if (SCM_UNBNDP (radix)) {
2342 base = 10;
2343 } else {
2344 SCM_VALIDATE_INUM (2, radix);
2345 base = SCM_INUM (radix);
2346 SCM_ASSERT_RANGE (2, radix, base >= 2);
2347 }
2348
2349 if (SCM_INUMP (n)) {
2350 char num_buf [SCM_INTBUFLEN];
2351 size_t length = scm_iint2str (SCM_INUM (n), base, num_buf);
2352 return scm_mem2string (num_buf, length);
2353 } else if (SCM_BIGP (n)) {
2354 return big2str (n, (unsigned int) base);
2355 } else if (SCM_INEXACTP (n)) {
2356 char num_buf [FLOBUFLEN];
2357 return scm_mem2string (num_buf, iflo2str (n, num_buf));
2358 } else {
2359 SCM_WRONG_TYPE_ARG (1, n);
2360 }
2361 }
2362 #undef FUNC_NAME
2363
2364
2365 /* These print routines are stubbed here so that scm_repl.c doesn't need
2366 SCM_BIGDIG conditionals */
2367
2368 int
2369 scm_print_real (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
2370 {
2371 char num_buf[FLOBUFLEN];
2372 scm_lfwrite (num_buf, iflo2str (sexp, num_buf), port);
2373 return !0;
2374 }
2375
2376 int
2377 scm_print_complex (SCM sexp, SCM port, scm_print_state *pstate SCM_UNUSED)
2378 {
2379 char num_buf[FLOBUFLEN];
2380 scm_lfwrite (num_buf, iflo2str (sexp, num_buf), port);
2381 return !0;
2382 }
2383
2384 int
2385 scm_bigprint (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
2386 {
2387 #ifdef SCM_BIGDIG
2388 exp = big2str (exp, (unsigned int) 10);
2389 scm_lfwrite (SCM_STRING_CHARS (exp), (size_t) SCM_STRING_LENGTH (exp), port);
2390 #else
2391 scm_ipruk ("bignum", exp, port);
2392 #endif
2393 return !0;
2394 }
2395 /*** END nums->strs ***/
2396
2397
2398 /*** STRINGS -> NUMBERS ***/
2399
2400 /* The following functions implement the conversion from strings to numbers.
2401 * The implementation somehow follows the grammar for numbers as it is given
2402 * in R5RS. Thus, the functions resemble syntactic units (<ureal R>,
2403 * <uinteger R>, ...) that are used to build up numbers in the grammar. Some
2404 * points should be noted about the implementation:
2405 * * Each function keeps a local index variable 'idx' that points at the
2406 * current position within the parsed string. The global index is only
2407 * updated if the function could parse the corresponding syntactic unit
2408 * successfully.
2409 * * Similarly, the functions keep track of indicators of inexactness ('#',
2410 * '.' or exponents) using local variables ('hash_seen', 'x'). Again, the
2411 * global exactness information is only updated after each part has been
2412 * successfully parsed.
2413 * * Sequences of digits are parsed into temporary variables holding fixnums.
2414 * Only if these fixnums would overflow, the result variables are updated
2415 * using the standard functions scm_add, scm_product, scm_divide etc. Then,
2416 * the temporary variables holding the fixnums are cleared, and the process
2417 * starts over again. If for example fixnums were able to store five decimal
2418 * digits, a number 1234567890 would be parsed in two parts 12345 and 67890,
2419 * and the result was computed as 12345 * 100000 + 67890. In other words,
2420 * only every five digits two bignum operations were performed.
2421 */
2422
2423 enum t_exactness {NO_EXACTNESS, INEXACT, EXACT};
2424
2425 /* R5RS, section 7.1.1, lexical structure of numbers: <uinteger R>. */
2426
2427 /* In non ASCII-style encodings the following macro might not work. */
2428 #define XDIGIT2UINT(d) (isdigit (d) ? (d) - '0' : tolower (d) - 'a' + 10)
2429
2430 static SCM
2431 mem2uinteger (const char* mem, size_t len, unsigned int *p_idx,
2432 unsigned int radix, enum t_exactness *p_exactness)
2433 {
2434 unsigned int idx = *p_idx;
2435 unsigned int hash_seen = 0;
2436 scm_t_bits shift = 1;
2437 scm_t_bits add = 0;
2438 unsigned int digit_value;
2439 SCM result;
2440 char c;
2441
2442 if (idx == len)
2443 return SCM_BOOL_F;
2444
2445 c = mem[idx];
2446 if (!isxdigit (c))
2447 return SCM_BOOL_F;
2448 digit_value = XDIGIT2UINT (c);
2449 if (digit_value >= radix)
2450 return SCM_BOOL_F;
2451
2452 idx++;
2453 result = SCM_MAKINUM (digit_value);
2454 while (idx != len)
2455 {
2456 char c = mem[idx];
2457 if (isxdigit (c))
2458 {
2459 if (hash_seen)
2460 break;
2461 digit_value = XDIGIT2UINT (c);
2462 if (digit_value >= radix)
2463 break;
2464 }
2465 else if (c == '#')
2466 {
2467 hash_seen = 1;
2468 digit_value = 0;
2469 }
2470 else
2471 break;
2472
2473 idx++;
2474 if (SCM_MOST_POSITIVE_FIXNUM / radix < shift)
2475 {
2476 result = scm_product (result, SCM_MAKINUM (shift));
2477 if (add > 0)
2478 result = scm_sum (result, SCM_MAKINUM (add));
2479
2480 shift = radix;
2481 add = digit_value;
2482 }
2483 else
2484 {
2485 shift = shift * radix;
2486 add = add * radix + digit_value;
2487 }
2488 };
2489
2490 if (shift > 1)
2491 result = scm_product (result, SCM_MAKINUM (shift));
2492 if (add > 0)
2493 result = scm_sum (result, SCM_MAKINUM (add));
2494
2495 *p_idx = idx;
2496 if (hash_seen)
2497 *p_exactness = INEXACT;
2498
2499 return result;
2500 }
2501
2502
2503 /* R5RS, section 7.1.1, lexical structure of numbers: <decimal 10>. Only
2504 * covers the parts of the rules that start at a potential point. The value
2505 * of the digits up to the point have been parsed by the caller and are given
2506 * in variable result. The content of *p_exactness indicates, whether a hash
2507 * has already been seen in the digits before the point.
2508 */
2509
2510 /* In non ASCII-style encodings the following macro might not work. */
2511 #define DIGIT2UINT(d) ((d) - '0')
2512
2513 static SCM
2514 mem2decimal_from_point (SCM result, const char* mem, size_t len,
2515 unsigned int *p_idx, enum t_exactness *p_exactness)
2516 {
2517 unsigned int idx = *p_idx;
2518 enum t_exactness x = *p_exactness;
2519
2520 if (idx == len)
2521 return result;
2522
2523 if (mem[idx] == '.')
2524 {
2525 scm_t_bits shift = 1;
2526 scm_t_bits add = 0;
2527 unsigned int digit_value;
2528 SCM big_shift = SCM_MAKINUM (1);
2529
2530 idx++;
2531 while (idx != len)
2532 {
2533 char c = mem[idx];
2534 if (isdigit (c))
2535 {
2536 if (x == INEXACT)
2537 return SCM_BOOL_F;
2538 else
2539 digit_value = DIGIT2UINT (c);
2540 }
2541 else if (c == '#')
2542 {
2543 x = INEXACT;
2544 digit_value = 0;
2545 }
2546 else
2547 break;
2548
2549 idx++;
2550 if (SCM_MOST_POSITIVE_FIXNUM / 10 < shift)
2551 {
2552 big_shift = scm_product (big_shift, SCM_MAKINUM (shift));
2553 result = scm_product (result, SCM_MAKINUM (shift));
2554 if (add > 0)
2555 result = scm_sum (result, SCM_MAKINUM (add));
2556
2557 shift = 10;
2558 add = digit_value;
2559 }
2560 else
2561 {
2562 shift = shift * 10;
2563 add = add * 10 + digit_value;
2564 }
2565 };
2566
2567 if (add > 0)
2568 {
2569 big_shift = scm_product (big_shift, SCM_MAKINUM (shift));
2570 result = scm_product (result, SCM_MAKINUM (shift));
2571 result = scm_sum (result, SCM_MAKINUM (add));
2572 }
2573
2574 result = scm_divide (result, big_shift);
2575
2576 /* We've seen a decimal point, thus the value is implicitly inexact. */
2577 x = INEXACT;
2578 }
2579
2580 if (idx != len)
2581 {
2582 int sign = 1;
2583 unsigned int start;
2584 char c;
2585 int exponent;
2586 SCM e;
2587
2588 /* R5RS, section 7.1.1, lexical structure of numbers: <suffix> */
2589
2590 switch (mem[idx])
2591 {
2592 case 'd': case 'D':
2593 case 'e': case 'E':
2594 case 'f': case 'F':
2595 case 'l': case 'L':
2596 case 's': case 'S':
2597 idx++;
2598 start = idx;
2599 c = mem[idx];
2600 if (c == '-')
2601 {
2602 idx++;
2603 sign = -1;
2604 c = mem[idx];
2605 }
2606 else if (c == '+')
2607 {
2608 idx++;
2609 sign = 1;
2610 c = mem[idx];
2611 }
2612 else
2613 sign = 1;
2614
2615 if (!isdigit (c))
2616 return SCM_BOOL_F;
2617
2618 idx++;
2619 exponent = DIGIT2UINT (c);
2620 while (idx != len)
2621 {
2622 char c = mem[idx];
2623 if (isdigit (c))
2624 {
2625 idx++;
2626 if (exponent <= SCM_MAXEXP)
2627 exponent = exponent * 10 + DIGIT2UINT (c);
2628 }
2629 else
2630 break;
2631 }
2632
2633 if (exponent > SCM_MAXEXP)
2634 {
2635 size_t exp_len = idx - start;
2636 SCM exp_string = scm_mem2string (&mem[start], exp_len);
2637 SCM exp_num = scm_string_to_number (exp_string, SCM_UNDEFINED);
2638 scm_out_of_range ("string->number", exp_num);
2639 }
2640
2641 e = scm_integer_expt (SCM_MAKINUM (10), SCM_MAKINUM (exponent));
2642 if (sign == 1)
2643 result = scm_product (result, e);
2644 else
2645 result = scm_divide (result, e);
2646
2647 /* We've seen an exponent, thus the value is implicitly inexact. */
2648 x = INEXACT;
2649
2650 break;
2651
2652 default:
2653 break;
2654 }
2655 }
2656
2657 *p_idx = idx;
2658 if (x == INEXACT)
2659 *p_exactness = x;
2660
2661 return result;
2662 }
2663
2664
2665 /* R5RS, section 7.1.1, lexical structure of numbers: <ureal R> */
2666
2667 static SCM
2668 mem2ureal (const char* mem, size_t len, unsigned int *p_idx,
2669 unsigned int radix, enum t_exactness *p_exactness)
2670 {
2671 unsigned int idx = *p_idx;
2672 SCM result;
2673
2674 if (idx == len)
2675 return SCM_BOOL_F;
2676
2677 if (idx+5 <= len && !strncmp (mem+idx, "inf.0", 5))
2678 {
2679 *p_idx = idx+5;
2680 return scm_inf ();
2681 }
2682
2683 if (idx+4 < len && !strncmp (mem+idx, "nan.", 4))
2684 {
2685 enum t_exactness x = EXACT;
2686
2687 /* Cobble up the fraction. We might want to set the NaN's
2688 mantissa from it. */
2689 idx += 4;
2690 mem2uinteger (mem, len, &idx, 10, &x);
2691 *p_idx = idx;
2692 return scm_nan ();
2693 }
2694
2695 if (mem[idx] == '.')
2696 {
2697 if (radix != 10)
2698 return SCM_BOOL_F;
2699 else if (idx + 1 == len)
2700 return SCM_BOOL_F;
2701 else if (!isdigit (mem[idx + 1]))
2702 return SCM_BOOL_F;
2703 else
2704 result = mem2decimal_from_point (SCM_MAKINUM (0), mem, len,
2705 p_idx, p_exactness);
2706 }
2707 else
2708 {
2709 enum t_exactness x = EXACT;
2710 SCM uinteger;
2711
2712 uinteger = mem2uinteger (mem, len, &idx, radix, &x);
2713 if (SCM_FALSEP (uinteger))
2714 return SCM_BOOL_F;
2715
2716 if (idx == len)
2717 result = uinteger;
2718 else if (mem[idx] == '/')
2719 {
2720 SCM divisor;
2721
2722 idx++;
2723
2724 divisor = mem2uinteger (mem, len, &idx, radix, &x);
2725 if (SCM_FALSEP (divisor))
2726 return SCM_BOOL_F;
2727
2728 result = scm_divide (uinteger, divisor);
2729 }
2730 else if (radix == 10)
2731 {
2732 result = mem2decimal_from_point (uinteger, mem, len, &idx, &x);
2733 if (SCM_FALSEP (result))
2734 return SCM_BOOL_F;
2735 }
2736 else
2737 result = uinteger;
2738
2739 *p_idx = idx;
2740 if (x == INEXACT)
2741 *p_exactness = x;
2742 }
2743
2744 /* When returning an inexact zero, make sure it is represented as a
2745 floating point value so that we can change its sign.
2746 */
2747 if (SCM_EQ_P (result, SCM_MAKINUM(0)) && *p_exactness == INEXACT)
2748 result = scm_make_real (0.0);
2749
2750 return result;
2751 }
2752
2753
2754 /* R5RS, section 7.1.1, lexical structure of numbers: <complex R> */
2755
2756 static SCM
2757 mem2complex (const char* mem, size_t len, unsigned int idx,
2758 unsigned int radix, enum t_exactness *p_exactness)
2759 {
2760 char c;
2761 int sign = 0;
2762 SCM ureal;
2763
2764 if (idx == len)
2765 return SCM_BOOL_F;
2766
2767 c = mem[idx];
2768 if (c == '+')
2769 {
2770 idx++;
2771 sign = 1;
2772 }
2773 else if (c == '-')
2774 {
2775 idx++;
2776 sign = -1;
2777 }
2778
2779 if (idx == len)
2780 return SCM_BOOL_F;
2781
2782 ureal = mem2ureal (mem, len, &idx, radix, p_exactness);
2783 if (SCM_FALSEP (ureal))
2784 {
2785 /* input must be either +i or -i */
2786
2787 if (sign == 0)
2788 return SCM_BOOL_F;
2789
2790 if (mem[idx] == 'i' || mem[idx] == 'I')
2791 {
2792 idx++;
2793 if (idx != len)
2794 return SCM_BOOL_F;
2795
2796 return scm_make_rectangular (SCM_MAKINUM (0), SCM_MAKINUM (sign));
2797 }
2798 else
2799 return SCM_BOOL_F;
2800 }
2801 else
2802 {
2803 if (sign == -1 && SCM_FALSEP (scm_nan_p (ureal)))
2804 ureal = scm_difference (ureal, SCM_UNDEFINED);
2805
2806 if (idx == len)
2807 return ureal;
2808
2809 c = mem[idx];
2810 switch (c)
2811 {
2812 case 'i': case 'I':
2813 /* either +<ureal>i or -<ureal>i */
2814
2815 idx++;
2816 if (sign == 0)
2817 return SCM_BOOL_F;
2818 if (idx != len)
2819 return SCM_BOOL_F;
2820 return scm_make_rectangular (SCM_MAKINUM (0), ureal);
2821
2822 case '@':
2823 /* polar input: <real>@<real>. */
2824
2825 idx++;
2826 if (idx == len)
2827 return SCM_BOOL_F;
2828 else
2829 {
2830 int sign;
2831 SCM angle;
2832 SCM result;
2833
2834 c = mem[idx];
2835 if (c == '+')
2836 {
2837 idx++;
2838 sign = 1;
2839 }
2840 else if (c == '-')
2841 {
2842 idx++;
2843 sign = -1;
2844 }
2845 else
2846 sign = 1;
2847
2848 angle = mem2ureal (mem, len, &idx, radix, p_exactness);
2849 if (SCM_FALSEP (angle))
2850 return SCM_BOOL_F;
2851 if (idx != len)
2852 return SCM_BOOL_F;
2853
2854 if (sign == -1 && SCM_FALSEP (scm_nan_p (ureal)))
2855 angle = scm_difference (angle, SCM_UNDEFINED);
2856
2857 result = scm_make_polar (ureal, angle);
2858 return result;
2859 }
2860 case '+':
2861 case '-':
2862 /* expecting input matching <real>[+-]<ureal>?i */
2863
2864 idx++;
2865 if (idx == len)
2866 return SCM_BOOL_F;
2867 else
2868 {
2869 int sign = (c == '+') ? 1 : -1;
2870 SCM imag = mem2ureal (mem, len, &idx, radix, p_exactness);
2871
2872 if (SCM_FALSEP (imag))
2873 imag = SCM_MAKINUM (sign);
2874 else if (sign == -1 && SCM_FALSEP (scm_nan_p (ureal)))
2875 imag = scm_difference (imag, SCM_UNDEFINED);
2876
2877 if (idx == len)
2878 return SCM_BOOL_F;
2879 if (mem[idx] != 'i' && mem[idx] != 'I')
2880 return SCM_BOOL_F;
2881
2882 idx++;
2883 if (idx != len)
2884 return SCM_BOOL_F;
2885
2886 return scm_make_rectangular (ureal, imag);
2887 }
2888 default:
2889 return SCM_BOOL_F;
2890 }
2891 }
2892 }
2893
2894
2895 /* R5RS, section 7.1.1, lexical structure of numbers: <number> */
2896
2897 enum t_radix {NO_RADIX=0, DUAL=2, OCT=8, DEC=10, HEX=16};
2898
2899 SCM
2900 scm_i_mem2number (const char* mem, size_t len, unsigned int default_radix)
2901 {
2902 unsigned int idx = 0;
2903 unsigned int radix = NO_RADIX;
2904 enum t_exactness forced_x = NO_EXACTNESS;
2905 enum t_exactness implicit_x = EXACT;
2906 SCM result;
2907
2908 /* R5RS, section 7.1.1, lexical structure of numbers: <prefix R> */
2909 while (idx + 2 < len && mem[idx] == '#')
2910 {
2911 switch (mem[idx + 1])
2912 {
2913 case 'b': case 'B':
2914 if (radix != NO_RADIX)
2915 return SCM_BOOL_F;
2916 radix = DUAL;
2917 break;
2918 case 'd': case 'D':
2919 if (radix != NO_RADIX)
2920 return SCM_BOOL_F;
2921 radix = DEC;
2922 break;
2923 case 'i': case 'I':
2924 if (forced_x != NO_EXACTNESS)
2925 return SCM_BOOL_F;
2926 forced_x = INEXACT;
2927 break;
2928 case 'e': case 'E':
2929 if (forced_x != NO_EXACTNESS)
2930 return SCM_BOOL_F;
2931 forced_x = EXACT;
2932 break;
2933 case 'o': case 'O':
2934 if (radix != NO_RADIX)
2935 return SCM_BOOL_F;
2936 radix = OCT;
2937 break;
2938 case 'x': case 'X':
2939 if (radix != NO_RADIX)
2940 return SCM_BOOL_F;
2941 radix = HEX;
2942 break;
2943 default:
2944 return SCM_BOOL_F;
2945 }
2946 idx += 2;
2947 }
2948
2949 /* R5RS, section 7.1.1, lexical structure of numbers: <complex R> */
2950 if (radix == NO_RADIX)
2951 result = mem2complex (mem, len, idx, default_radix, &implicit_x);
2952 else
2953 result = mem2complex (mem, len, idx, (unsigned int) radix, &implicit_x);
2954
2955 if (SCM_FALSEP (result))
2956 return SCM_BOOL_F;
2957
2958 switch (forced_x)
2959 {
2960 case EXACT:
2961 if (SCM_INEXACTP (result))
2962 /* FIXME: This may change the value. */
2963 return scm_inexact_to_exact (result);
2964 else
2965 return result;
2966 case INEXACT:
2967 if (SCM_INEXACTP (result))
2968 return result;
2969 else
2970 return scm_exact_to_inexact (result);
2971 case NO_EXACTNESS:
2972 default:
2973 if (implicit_x == INEXACT)
2974 {
2975 if (SCM_INEXACTP (result))
2976 return result;
2977 else
2978 return scm_exact_to_inexact (result);
2979 }
2980 else
2981 return result;
2982 }
2983 }
2984
2985
2986 SCM_DEFINE (scm_string_to_number, "string->number", 1, 1, 0,
2987 (SCM string, SCM radix),
2988 "Return a number of the maximally precise representation\n"
2989 "expressed by the given @var{string}. @var{radix} must be an\n"
2990 "exact integer, either 2, 8, 10, or 16. If supplied, @var{radix}\n"
2991 "is a default radix that may be overridden by an explicit radix\n"
2992 "prefix in @var{string} (e.g. \"#o177\"). If @var{radix} is not\n"
2993 "supplied, then the default radix is 10. If string is not a\n"
2994 "syntactically valid notation for a number, then\n"
2995 "@code{string->number} returns @code{#f}.")
2996 #define FUNC_NAME s_scm_string_to_number
2997 {
2998 SCM answer;
2999 int base;
3000 SCM_VALIDATE_STRING (1, string);
3001 SCM_VALIDATE_INUM_MIN_DEF_COPY (2, radix,2,10, base);
3002 answer = scm_i_mem2number (SCM_STRING_CHARS (string),
3003 SCM_STRING_LENGTH (string),
3004 base);
3005 return scm_return_first (answer, string);
3006 }
3007 #undef FUNC_NAME
3008
3009
3010 /*** END strs->nums ***/
3011
3012
3013 SCM
3014 scm_make_real (double x)
3015 {
3016 SCM z = scm_double_cell (scm_tc16_real, 0, 0, 0);
3017
3018 SCM_REAL_VALUE (z) = x;
3019 return z;
3020 }
3021
3022
3023 SCM
3024 scm_make_complex (double x, double y)
3025 {
3026 if (y == 0.0) {
3027 return scm_make_real (x);
3028 } else {
3029 SCM z;
3030 SCM_NEWSMOB (z, scm_tc16_complex, scm_gc_malloc (2*sizeof (double),
3031 "complex"));
3032 SCM_COMPLEX_REAL (z) = x;
3033 SCM_COMPLEX_IMAG (z) = y;
3034 return z;
3035 }
3036 }
3037
3038
3039 SCM
3040 scm_bigequal (SCM x, SCM y)
3041 {
3042 #ifdef SCM_BIGDIG
3043 if (0 == scm_bigcomp (x, y))
3044 return SCM_BOOL_T;
3045 #endif
3046 return SCM_BOOL_F;
3047 }
3048
3049 SCM
3050 scm_real_equalp (SCM x, SCM y)
3051 {
3052 return SCM_BOOL (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
3053 }
3054
3055 SCM
3056 scm_complex_equalp (SCM x, SCM y)
3057 {
3058 return SCM_BOOL (SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y)
3059 && SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y));
3060 }
3061
3062
3063
3064 SCM_REGISTER_PROC (s_number_p, "number?", 1, 0, 0, scm_number_p);
3065 /* "Return @code{#t} if @var{x} is a number, @code{#f}\n"
3066 * "else. Note that the sets of complex, real, rational and\n"
3067 * "integer values form subsets of the set of numbers, i. e. the\n"
3068 * "predicate will be fulfilled for any number."
3069 */
3070 SCM_DEFINE (scm_number_p, "complex?", 1, 0, 0,
3071 (SCM x),
3072 "Return @code{#t} if @var{x} is a complex number, @code{#f}\n"
3073 "otherwise. Note that the sets of real, rational and integer\n"
3074 "values form subsets of the set of complex numbers, i. e. the\n"
3075 "predicate will also be fulfilled if @var{x} is a real,\n"
3076 "rational or integer number.")
3077 #define FUNC_NAME s_scm_number_p
3078 {
3079 return SCM_BOOL (SCM_NUMBERP (x));
3080 }
3081 #undef FUNC_NAME
3082
3083
3084 SCM_REGISTER_PROC (s_real_p, "real?", 1, 0, 0, scm_real_p);
3085 /* "Return @code{#t} if @var{x} is a real number, @code{#f} else.\n"
3086 * "Note that the sets of integer and rational values form a subset\n"
3087 * "of the set of real numbers, i. e. the predicate will also\n"
3088 * "be fulfilled if @var{x} is an integer or a rational number."
3089 */
3090 SCM_DEFINE (scm_real_p, "rational?", 1, 0, 0,
3091 (SCM x),
3092 "Return @code{#t} if @var{x} is a rational number, @code{#f}\n"
3093 "otherwise. Note that the set of integer values forms a subset of\n"
3094 "the set of rational numbers, i. e. the predicate will also be\n"
3095 "fulfilled if @var{x} is an integer number. Real numbers\n"
3096 "will also satisfy this predicate, because of their limited\n"
3097 "precision.")
3098 #define FUNC_NAME s_scm_real_p
3099 {
3100 if (SCM_INUMP (x)) {
3101 return SCM_BOOL_T;
3102 } else if (SCM_IMP (x)) {
3103 return SCM_BOOL_F;
3104 } else if (SCM_REALP (x)) {
3105 return SCM_BOOL_T;
3106 } else if (SCM_BIGP (x)) {
3107 return SCM_BOOL_T;
3108 } else {
3109 return SCM_BOOL_F;
3110 }
3111 }
3112 #undef FUNC_NAME
3113
3114
3115 SCM_DEFINE (scm_integer_p, "integer?", 1, 0, 0,
3116 (SCM x),
3117 "Return @code{#t} if @var{x} is an integer number, @code{#f}\n"
3118 "else.")
3119 #define FUNC_NAME s_scm_integer_p
3120 {
3121 double r;
3122 if (SCM_INUMP (x))
3123 return SCM_BOOL_T;
3124 if (SCM_IMP (x))
3125 return SCM_BOOL_F;
3126 if (SCM_BIGP (x))
3127 return SCM_BOOL_T;
3128 if (!SCM_INEXACTP (x))
3129 return SCM_BOOL_F;
3130 if (SCM_COMPLEXP (x))
3131 return SCM_BOOL_F;
3132 r = SCM_REAL_VALUE (x);
3133 if (r == floor (r))
3134 return SCM_BOOL_T;
3135 return SCM_BOOL_F;
3136 }
3137 #undef FUNC_NAME
3138
3139
3140 SCM_DEFINE (scm_inexact_p, "inexact?", 1, 0, 0,
3141 (SCM x),
3142 "Return @code{#t} if @var{x} is an inexact number, @code{#f}\n"
3143 "else.")
3144 #define FUNC_NAME s_scm_inexact_p
3145 {
3146 return SCM_BOOL (SCM_INEXACTP (x));
3147 }
3148 #undef FUNC_NAME
3149
3150
3151 SCM_GPROC1 (s_eq_p, "=", scm_tc7_rpsubr, scm_num_eq_p, g_eq_p);
3152 /* "Return @code{#t} if all parameters are numerically equal." */
3153 SCM
3154 scm_num_eq_p (SCM x, SCM y)
3155 {
3156 if (SCM_INUMP (x)) {
3157 long xx = SCM_INUM (x);
3158 if (SCM_INUMP (y)) {
3159 long yy = SCM_INUM (y);
3160 return SCM_BOOL (xx == yy);
3161 } else if (SCM_BIGP (y)) {
3162 return SCM_BOOL_F;
3163 } else if (SCM_REALP (y)) {
3164 return SCM_BOOL ((double) xx == SCM_REAL_VALUE (y));
3165 } else if (SCM_COMPLEXP (y)) {
3166 return SCM_BOOL (((double) xx == SCM_COMPLEX_REAL (y))
3167 && (0.0 == SCM_COMPLEX_IMAG (y)));
3168 } else {
3169 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
3170 }
3171 } else if (SCM_BIGP (x)) {
3172 if (SCM_INUMP (y)) {
3173 return SCM_BOOL_F;
3174 } else if (SCM_BIGP (y)) {
3175 return SCM_BOOL (0 == scm_bigcomp (x, y));
3176 } else if (SCM_REALP (y)) {
3177 return SCM_BOOL (scm_i_big2dbl (x) == SCM_REAL_VALUE (y));
3178 } else if (SCM_COMPLEXP (y)) {
3179 return SCM_BOOL ((scm_i_big2dbl (x) == SCM_COMPLEX_REAL (y))
3180 && (0.0 == SCM_COMPLEX_IMAG (y)));
3181 } else {
3182 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
3183 }
3184 } else if (SCM_REALP (x)) {
3185 if (SCM_INUMP (y)) {
3186 return SCM_BOOL (SCM_REAL_VALUE (x) == (double) SCM_INUM (y));
3187 } else if (SCM_BIGP (y)) {
3188 return SCM_BOOL (SCM_REAL_VALUE (x) == scm_i_big2dbl (y));
3189 } else if (SCM_REALP (y)) {
3190 return SCM_BOOL (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
3191 } else if (SCM_COMPLEXP (y)) {
3192 return SCM_BOOL ((SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y))
3193 && (0.0 == SCM_COMPLEX_IMAG (y)));
3194 } else {
3195 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
3196 }
3197 } else if (SCM_COMPLEXP (x)) {
3198 if (SCM_INUMP (y)) {
3199 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == (double) SCM_INUM (y))
3200 && (SCM_COMPLEX_IMAG (x) == 0.0));
3201 } else if (SCM_BIGP (y)) {
3202 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == scm_i_big2dbl (y))
3203 && (SCM_COMPLEX_IMAG (x) == 0.0));
3204 } else if (SCM_REALP (y)) {
3205 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y))
3206 && (SCM_COMPLEX_IMAG (x) == 0.0));
3207 } else if (SCM_COMPLEXP (y)) {
3208 return SCM_BOOL ((SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y))
3209 && (SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y)));
3210 } else {
3211 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
3212 }
3213 } else {
3214 SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARG1, s_eq_p);
3215 }
3216 }
3217
3218
3219 SCM_GPROC1 (s_less_p, "<", scm_tc7_rpsubr, scm_less_p, g_less_p);
3220 /* "Return @code{#t} if the list of parameters is monotonically\n"
3221 * "increasing."
3222 */
3223 SCM
3224 scm_less_p (SCM x, SCM y)
3225 {
3226 if (SCM_INUMP (x)) {
3227 long xx = SCM_INUM (x);
3228 if (SCM_INUMP (y)) {
3229 long yy = SCM_INUM (y);
3230 return SCM_BOOL (xx < yy);
3231 } else if (SCM_BIGP (y)) {
3232 return SCM_BOOL (!SCM_BIGSIGN (y));
3233 } else if (SCM_REALP (y)) {
3234 return SCM_BOOL ((double) xx < SCM_REAL_VALUE (y));
3235 } else {
3236 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
3237 }
3238 } else if (SCM_BIGP (x)) {
3239 if (SCM_INUMP (y)) {
3240 return SCM_BOOL (SCM_BIGSIGN (x));
3241 } else if (SCM_BIGP (y)) {
3242 return SCM_BOOL (1 == scm_bigcomp (x, y));
3243 } else if (SCM_REALP (y)) {
3244 return SCM_BOOL (scm_i_big2dbl (x) < SCM_REAL_VALUE (y));
3245 } else {
3246 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
3247 }
3248 } else if (SCM_REALP (x)) {
3249 if (SCM_INUMP (y)) {
3250 return SCM_BOOL (SCM_REAL_VALUE (x) < (double) SCM_INUM (y));
3251 } else if (SCM_BIGP (y)) {
3252 return SCM_BOOL (SCM_REAL_VALUE (x) < scm_i_big2dbl (y));
3253 } else if (SCM_REALP (y)) {
3254 return SCM_BOOL (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y));
3255 } else {
3256 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
3257 }
3258 } else {
3259 SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARG1, s_less_p);
3260 }
3261 }
3262
3263
3264 SCM_GPROC1 (s_scm_gr_p, ">", scm_tc7_rpsubr, scm_gr_p, g_gr_p);
3265 /* "Return @code{#t} if the list of parameters is monotonically\n"
3266 * "decreasing."
3267 */
3268 #define FUNC_NAME s_scm_gr_p
3269 SCM
3270 scm_gr_p (SCM x, SCM y)
3271 {
3272 if (!SCM_NUMBERP (x))
3273 SCM_WTA_DISPATCH_2 (g_gr_p, x, y, SCM_ARG1, FUNC_NAME);
3274 else if (!SCM_NUMBERP (y))
3275 SCM_WTA_DISPATCH_2 (g_gr_p, x, y, SCM_ARG2, FUNC_NAME);
3276 else
3277 return scm_less_p (y, x);
3278 }
3279 #undef FUNC_NAME
3280
3281
3282 SCM_GPROC1 (s_scm_leq_p, "<=", scm_tc7_rpsubr, scm_leq_p, g_leq_p);
3283 /* "Return @code{#t} if the list of parameters is monotonically\n"
3284 * "non-decreasing."
3285 */
3286 #define FUNC_NAME s_scm_leq_p
3287 SCM
3288 scm_leq_p (SCM x, SCM y)
3289 {
3290 if (!SCM_NUMBERP (x))
3291 SCM_WTA_DISPATCH_2 (g_leq_p, x, y, SCM_ARG1, FUNC_NAME);
3292 else if (!SCM_NUMBERP (y))
3293 SCM_WTA_DISPATCH_2 (g_leq_p, x, y, SCM_ARG2, FUNC_NAME);
3294 else if (SCM_NFALSEP (scm_nan_p (x)) || SCM_NFALSEP (scm_nan_p (y)))
3295 return SCM_BOOL_F;
3296 else
3297 return SCM_BOOL_NOT (scm_less_p (y, x));
3298 }
3299 #undef FUNC_NAME
3300
3301
3302 SCM_GPROC1 (s_scm_geq_p, ">=", scm_tc7_rpsubr, scm_geq_p, g_geq_p);
3303 /* "Return @code{#t} if the list of parameters is monotonically\n"
3304 * "non-increasing."
3305 */
3306 #define FUNC_NAME s_scm_geq_p
3307 SCM
3308 scm_geq_p (SCM x, SCM y)
3309 {
3310 if (!SCM_NUMBERP (x))
3311 SCM_WTA_DISPATCH_2 (g_geq_p, x, y, SCM_ARG1, FUNC_NAME);
3312 else if (!SCM_NUMBERP (y))
3313 SCM_WTA_DISPATCH_2 (g_geq_p, x, y, SCM_ARG2, FUNC_NAME);
3314 else if (SCM_NFALSEP (scm_nan_p (x)) || SCM_NFALSEP (scm_nan_p (y)))
3315 return SCM_BOOL_F;
3316 else
3317 return SCM_BOOL_NOT (scm_less_p (x, y));
3318 }
3319 #undef FUNC_NAME
3320
3321
3322 SCM_GPROC (s_zero_p, "zero?", 1, 0, 0, scm_zero_p, g_zero_p);
3323 /* "Return @code{#t} if @var{z} is an exact or inexact number equal to\n"
3324 * "zero."
3325 */
3326 SCM
3327 scm_zero_p (SCM z)
3328 {
3329 if (SCM_INUMP (z)) {
3330 return SCM_BOOL (SCM_EQ_P (z, SCM_INUM0));
3331 } else if (SCM_BIGP (z)) {
3332 return SCM_BOOL_F;
3333 } else if (SCM_REALP (z)) {
3334 return SCM_BOOL (SCM_REAL_VALUE (z) == 0.0);
3335 } else if (SCM_COMPLEXP (z)) {
3336 return SCM_BOOL (SCM_COMPLEX_REAL (z) == 0.0
3337 && SCM_COMPLEX_IMAG (z) == 0.0);
3338 } else {
3339 SCM_WTA_DISPATCH_1 (g_zero_p, z, SCM_ARG1, s_zero_p);
3340 }
3341 }
3342
3343
3344 SCM_GPROC (s_positive_p, "positive?", 1, 0, 0, scm_positive_p, g_positive_p);
3345 /* "Return @code{#t} if @var{x} is an exact or inexact number greater than\n"
3346 * "zero."
3347 */
3348 SCM
3349 scm_positive_p (SCM x)
3350 {
3351 if (SCM_INUMP (x)) {
3352 return SCM_BOOL (SCM_INUM (x) > 0);
3353 } else if (SCM_BIGP (x)) {
3354 return SCM_BOOL (!SCM_BIGSIGN (x));
3355 } else if (SCM_REALP (x)) {
3356 return SCM_BOOL(SCM_REAL_VALUE (x) > 0.0);
3357 } else {
3358 SCM_WTA_DISPATCH_1 (g_positive_p, x, SCM_ARG1, s_positive_p);
3359 }
3360 }
3361
3362
3363 SCM_GPROC (s_negative_p, "negative?", 1, 0, 0, scm_negative_p, g_negative_p);
3364 /* "Return @code{#t} if @var{x} is an exact or inexact number less than\n"
3365 * "zero."
3366 */
3367 SCM
3368 scm_negative_p (SCM x)
3369 {
3370 if (SCM_INUMP (x)) {
3371 return SCM_BOOL (SCM_INUM (x) < 0);
3372 } else if (SCM_BIGP (x)) {
3373 return SCM_BOOL (SCM_BIGSIGN (x));
3374 } else if (SCM_REALP (x)) {
3375 return SCM_BOOL(SCM_REAL_VALUE (x) < 0.0);
3376 } else {
3377 SCM_WTA_DISPATCH_1 (g_negative_p, x, SCM_ARG1, s_negative_p);
3378 }
3379 }
3380
3381
3382 SCM_GPROC1 (s_max, "max", scm_tc7_asubr, scm_max, g_max);
3383 /* "Return the maximum of all parameter values."
3384 */
3385 SCM
3386 scm_max (SCM x, SCM y)
3387 {
3388 if (SCM_UNBNDP (y)) {
3389 if (SCM_UNBNDP (x)) {
3390 SCM_WTA_DISPATCH_0 (g_max, s_max);
3391 } else if (SCM_NUMBERP (x)) {
3392 return x;
3393 } else {
3394 SCM_WTA_DISPATCH_1 (g_max, x, SCM_ARG1, s_max);
3395 }
3396 }
3397
3398 if (SCM_INUMP (x)) {
3399 long xx = SCM_INUM (x);
3400 if (SCM_INUMP (y)) {
3401 long yy = SCM_INUM (y);
3402 return (xx < yy) ? y : x;
3403 } else if (SCM_BIGP (y)) {
3404 return SCM_BIGSIGN (y) ? x : y;
3405 } else if (SCM_REALP (y)) {
3406 double z = xx;
3407 return (z <= SCM_REAL_VALUE (y)) ? y : scm_make_real (z);
3408 } else {
3409 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
3410 }
3411 } else if (SCM_BIGP (x)) {
3412 if (SCM_INUMP (y)) {
3413 return SCM_BIGSIGN (x) ? y : x;
3414 } else if (SCM_BIGP (y)) {
3415 return (1 == scm_bigcomp (x, y)) ? y : x;
3416 } else if (SCM_REALP (y)) {
3417 double z = scm_i_big2dbl (x);
3418 return (z <= SCM_REAL_VALUE (y)) ? y : scm_make_real (z);
3419 } else {
3420 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
3421 }
3422 } else if (SCM_REALP (x)) {
3423 if (SCM_INUMP (y)) {
3424 double z = SCM_INUM (y);
3425 return (SCM_REAL_VALUE (x) < z) ? scm_make_real (z) : x;
3426 } else if (SCM_BIGP (y)) {
3427 double z = scm_i_big2dbl (y);
3428 return (SCM_REAL_VALUE (x) < z) ? scm_make_real (z) : x;
3429 } else if (SCM_REALP (y)) {
3430 return (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y)) ? y : x;
3431 } else {
3432 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max);
3433 }
3434 } else {
3435 SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARG1, s_max);
3436 }
3437 }
3438
3439
3440 SCM_GPROC1 (s_min, "min", scm_tc7_asubr, scm_min, g_min);
3441 /* "Return the minium of all parameter values."
3442 */
3443 SCM
3444 scm_min (SCM x, SCM y)
3445 {
3446 if (SCM_UNBNDP (y)) {
3447 if (SCM_UNBNDP (x)) {
3448 SCM_WTA_DISPATCH_0 (g_min, s_min);
3449 } else if (SCM_NUMBERP (x)) {
3450 return x;
3451 } else {
3452 SCM_WTA_DISPATCH_1 (g_min, x, SCM_ARG1, s_min);
3453 }
3454 }
3455
3456 if (SCM_INUMP (x)) {
3457 long xx = SCM_INUM (x);
3458 if (SCM_INUMP (y)) {
3459 long yy = SCM_INUM (y);
3460 return (xx < yy) ? x : y;
3461 } else if (SCM_BIGP (y)) {
3462 return SCM_BIGSIGN (y) ? y : x;
3463 } else if (SCM_REALP (y)) {
3464 double z = xx;
3465 return (z < SCM_REAL_VALUE (y)) ? scm_make_real (z) : y;
3466 } else {
3467 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
3468 }
3469 } else if (SCM_BIGP (x)) {
3470 if (SCM_INUMP (y)) {
3471 return SCM_BIGSIGN (x) ? x : y;
3472 } else if (SCM_BIGP (y)) {
3473 return (-1 == scm_bigcomp (x, y)) ? y : x;
3474 } else if (SCM_REALP (y)) {
3475 double z = scm_i_big2dbl (x);
3476 return (z < SCM_REAL_VALUE (y)) ? scm_make_real (z) : y;
3477 } else {
3478 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
3479 }
3480 } else if (SCM_REALP (x)) {
3481 if (SCM_INUMP (y)) {
3482 double z = SCM_INUM (y);
3483 return (SCM_REAL_VALUE (x) <= z) ? x : scm_make_real (z);
3484 } else if (SCM_BIGP (y)) {
3485 double z = scm_i_big2dbl (y);
3486 return (SCM_REAL_VALUE (x) <= z) ? x : scm_make_real (z);
3487 } else if (SCM_REALP (y)) {
3488 return (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y)) ? x : y;
3489 } else {
3490 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min);
3491 }
3492 } else {
3493 SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARG1, s_min);
3494 }
3495 }
3496
3497
3498 SCM_GPROC1 (s_sum, "+", scm_tc7_asubr, scm_sum, g_sum);
3499 /* "Return the sum of all parameter values. Return 0 if called without\n"
3500 * "any parameters."
3501 */
3502 SCM
3503 scm_sum (SCM x, SCM y)
3504 {
3505 if (SCM_UNBNDP (y)) {
3506 if (SCM_UNBNDP (x)) {
3507 return SCM_INUM0;
3508 } else if (SCM_NUMBERP (x)) {
3509 return x;
3510 } else {
3511 SCM_WTA_DISPATCH_1 (g_sum, x, SCM_ARG1, s_sum);
3512 }
3513 }
3514
3515 if (SCM_INUMP (x)) {
3516 long int xx = SCM_INUM (x);
3517 if (SCM_INUMP (y)) {
3518 long int yy = SCM_INUM (y);
3519 long int z = xx + yy;
3520 if (SCM_FIXABLE (z)) {
3521 return SCM_MAKINUM (z);
3522 } else {
3523 #ifdef SCM_BIGDIG
3524 return scm_i_long2big (z);
3525 #else /* SCM_BIGDIG */
3526 return scm_make_real ((double) z);
3527 #endif /* SCM_BIGDIG */
3528 }
3529 } else if (SCM_BIGP (y)) {
3530 intbig:
3531 {
3532 long int xx = SCM_INUM (x);
3533 #ifndef SCM_DIGSTOOBIG
3534 long z = scm_pseudolong (xx);
3535 return scm_addbig ((SCM_BIGDIG *) & z, SCM_DIGSPERLONG,
3536 (xx < 0) ? SCM_BIGSIGNFLAG : 0, y, 0);
3537 #else /* SCM_DIGSTOOBIG */
3538 SCM_BIGDIG zdigs [SCM_DIGSPERLONG];
3539 scm_longdigs (xx, zdigs);
3540 return scm_addbig (zdigs, SCM_DIGSPERLONG,
3541 (xx < 0) ? SCM_BIGSIGNFLAG : 0, y, 0);
3542 #endif /* SCM_DIGSTOOBIG */
3543 }
3544 } else if (SCM_REALP (y)) {
3545 return scm_make_real (xx + SCM_REAL_VALUE (y));
3546 } else if (SCM_COMPLEXP (y)) {
3547 return scm_make_complex (xx + SCM_COMPLEX_REAL (y),
3548 SCM_COMPLEX_IMAG (y));
3549 } else {
3550 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3551 }
3552 } else if (SCM_BIGP (x)) {
3553 if (SCM_INUMP (y)) {
3554 SCM_SWAP (x, y);
3555 goto intbig;
3556 } else if (SCM_BIGP (y)) {
3557 if (SCM_NUMDIGS (x) > SCM_NUMDIGS (y)) {
3558 SCM_SWAP (x, y);
3559 }
3560 return scm_addbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
3561 SCM_BIGSIGN (x), y, 0);
3562 } else if (SCM_REALP (y)) {
3563 return scm_make_real (scm_i_big2dbl (x) + SCM_REAL_VALUE (y));
3564 } else if (SCM_COMPLEXP (y)) {
3565 return scm_make_complex (scm_i_big2dbl (x) + SCM_COMPLEX_REAL (y),
3566 SCM_COMPLEX_IMAG (y));
3567 } else {
3568 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3569 }
3570 } else if (SCM_REALP (x)) {
3571 if (SCM_INUMP (y)) {
3572 return scm_make_real (SCM_REAL_VALUE (x) + SCM_INUM (y));
3573 } else if (SCM_BIGP (y)) {
3574 return scm_make_real (SCM_REAL_VALUE (x) + scm_i_big2dbl (y));
3575 } else if (SCM_REALP (y)) {
3576 return scm_make_real (SCM_REAL_VALUE (x) + SCM_REAL_VALUE (y));
3577 } else if (SCM_COMPLEXP (y)) {
3578 return scm_make_complex (SCM_REAL_VALUE (x) + SCM_COMPLEX_REAL (y),
3579 SCM_COMPLEX_IMAG (y));
3580 } else {
3581 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3582 }
3583 } else if (SCM_COMPLEXP (x)) {
3584 if (SCM_INUMP (y)) {
3585 return scm_make_complex (SCM_COMPLEX_REAL (x) + SCM_INUM (y),
3586 SCM_COMPLEX_IMAG (x));
3587 } else if (SCM_BIGP (y)) {
3588 return scm_make_complex (SCM_COMPLEX_REAL (x) + scm_i_big2dbl (y),
3589 SCM_COMPLEX_IMAG (x));
3590 } else if (SCM_REALP (y)) {
3591 return scm_make_complex (SCM_COMPLEX_REAL (x) + SCM_REAL_VALUE (y),
3592 SCM_COMPLEX_IMAG (x));
3593 } else if (SCM_COMPLEXP (y)) {
3594 return scm_make_complex (SCM_COMPLEX_REAL (x) + SCM_COMPLEX_REAL (y),
3595 SCM_COMPLEX_IMAG (x) + SCM_COMPLEX_IMAG (y));
3596 } else {
3597 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARGn, s_sum);
3598 }
3599 } else {
3600 SCM_WTA_DISPATCH_2 (g_sum, x, y, SCM_ARG1, s_sum);
3601 }
3602 }
3603
3604
3605 SCM_GPROC1 (s_difference, "-", scm_tc7_asubr, scm_difference, g_difference);
3606 /* If called with one argument @var{z1}, -@var{z1} returned. Otherwise
3607 * the sum of all but the first argument are subtracted from the first
3608 * argument. */
3609 #define FUNC_NAME s_difference
3610 SCM
3611 scm_difference (SCM x, SCM y)
3612 {
3613 if (SCM_UNBNDP (y)) {
3614 if (SCM_UNBNDP (x)) {
3615 SCM_WTA_DISPATCH_0 (g_difference, s_difference);
3616 } else if (SCM_INUMP (x)) {
3617 long xx = -SCM_INUM (x);
3618 if (SCM_FIXABLE (xx)) {
3619 return SCM_MAKINUM (xx);
3620 } else {
3621 #ifdef SCM_BIGDIG
3622 return scm_i_long2big (xx);
3623 #else
3624 return scm_make_real ((double) xx);
3625 #endif
3626 }
3627 } else if (SCM_BIGP (x)) {
3628 SCM z = scm_i_copybig (x, !SCM_BIGSIGN (x));
3629 unsigned int digs = SCM_NUMDIGS (z);
3630 unsigned int size = digs * SCM_BITSPERDIG / SCM_CHAR_BIT;
3631 return size <= sizeof (SCM) ? scm_i_big2inum (z, digs) : z;
3632 } else if (SCM_REALP (x)) {
3633 return scm_make_real (-SCM_REAL_VALUE (x));
3634 } else if (SCM_COMPLEXP (x)) {
3635 return scm_make_complex (-SCM_COMPLEX_REAL (x), -SCM_COMPLEX_IMAG (x));
3636 } else {
3637 SCM_WTA_DISPATCH_1 (g_difference, x, SCM_ARG1, s_difference);
3638 }
3639 }
3640
3641 if (SCM_INUMP (x)) {
3642 long int xx = SCM_INUM (x);
3643 if (SCM_INUMP (y)) {
3644 long int yy = SCM_INUM (y);
3645 long int z = xx - yy;
3646 if (SCM_FIXABLE (z)) {
3647 return SCM_MAKINUM (z);
3648 } else {
3649 #ifdef SCM_BIGDIG
3650 return scm_i_long2big (z);
3651 #else
3652 return scm_make_real ((double) z);
3653 #endif
3654 }
3655 } else if (SCM_BIGP (y)) {
3656 #ifndef SCM_DIGSTOOBIG
3657 long z = scm_pseudolong (xx);
3658 return scm_addbig ((SCM_BIGDIG *) & z, SCM_DIGSPERLONG,
3659 (xx < 0) ? SCM_BIGSIGNFLAG : 0, y, SCM_BIGSIGNFLAG);
3660 #else
3661 SCM_BIGDIG zdigs [SCM_DIGSPERLONG];
3662 scm_longdigs (xx, zdigs);
3663 return scm_addbig (zdigs, SCM_DIGSPERLONG,
3664 (xx < 0) ? SCM_BIGSIGNFLAG : 0, y, SCM_BIGSIGNFLAG);
3665 #endif
3666 } else if (SCM_REALP (y)) {
3667 return scm_make_real (xx - SCM_REAL_VALUE (y));
3668 } else if (SCM_COMPLEXP (y)) {
3669 return scm_make_complex (xx - SCM_COMPLEX_REAL (y),
3670 -SCM_COMPLEX_IMAG (y));
3671 } else {
3672 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3673 }
3674 } else if (SCM_BIGP (x)) {
3675 if (SCM_INUMP (y)) {
3676 long int yy = SCM_INUM (y);
3677 #ifndef SCM_DIGSTOOBIG
3678 long z = scm_pseudolong (yy);
3679 return scm_addbig ((SCM_BIGDIG *) & z, SCM_DIGSPERLONG,
3680 (yy < 0) ? 0 : SCM_BIGSIGNFLAG, x, 0);
3681 #else
3682 SCM_BIGDIG zdigs [SCM_DIGSPERLONG];
3683 scm_longdigs (yy, zdigs);
3684 return scm_addbig (zdigs, SCM_DIGSPERLONG,
3685 (yy < 0) ? 0 : SCM_BIGSIGNFLAG, x, 0);
3686 #endif
3687 } else if (SCM_BIGP (y)) {
3688 return (SCM_NUMDIGS (x) < SCM_NUMDIGS (y))
3689 ? scm_addbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
3690 SCM_BIGSIGN (x), y, SCM_BIGSIGNFLAG)
3691 : scm_addbig (SCM_BDIGITS (y), SCM_NUMDIGS (y),
3692 SCM_BIGSIGN (y) ^ SCM_BIGSIGNFLAG, x, 0);
3693 } else if (SCM_REALP (y)) {
3694 return scm_make_real (scm_i_big2dbl (x) - SCM_REAL_VALUE (y));
3695 } else if (SCM_COMPLEXP (y)) {
3696 return scm_make_complex (scm_i_big2dbl (x) - SCM_COMPLEX_REAL (y),
3697 - SCM_COMPLEX_IMAG (y));
3698 } else {
3699 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3700 }
3701 } else if (SCM_REALP (x)) {
3702 if (SCM_INUMP (y)) {
3703 return scm_make_real (SCM_REAL_VALUE (x) - SCM_INUM (y));
3704 } else if (SCM_BIGP (y)) {
3705 return scm_make_real (SCM_REAL_VALUE (x) - scm_i_big2dbl (y));
3706 } else if (SCM_REALP (y)) {
3707 return scm_make_real (SCM_REAL_VALUE (x) - SCM_REAL_VALUE (y));
3708 } else if (SCM_COMPLEXP (y)) {
3709 return scm_make_complex (SCM_REAL_VALUE (x) - SCM_COMPLEX_REAL (y),
3710 -SCM_COMPLEX_IMAG (y));
3711 } else {
3712 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3713 }
3714 } else if (SCM_COMPLEXP (x)) {
3715 if (SCM_INUMP (y)) {
3716 return scm_make_complex (SCM_COMPLEX_REAL (x) - SCM_INUM (y),
3717 SCM_COMPLEX_IMAG (x));
3718 } else if (SCM_BIGP (y)) {
3719 return scm_make_complex (SCM_COMPLEX_REAL (x) - scm_i_big2dbl (y),
3720 SCM_COMPLEX_IMAG (x));
3721 } else if (SCM_REALP (y)) {
3722 return scm_make_complex (SCM_COMPLEX_REAL (x) - SCM_REAL_VALUE (y),
3723 SCM_COMPLEX_IMAG (x));
3724 } else if (SCM_COMPLEXP (y)) {
3725 return scm_make_complex (SCM_COMPLEX_REAL (x) - SCM_COMPLEX_REAL (y),
3726 SCM_COMPLEX_IMAG (x) - SCM_COMPLEX_IMAG (y));
3727 } else {
3728 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARGn, s_difference);
3729 }
3730 } else {
3731 SCM_WTA_DISPATCH_2 (g_difference, x, y, SCM_ARG1, s_difference);
3732 }
3733 }
3734 #undef FUNC_NAME
3735
3736 SCM_GPROC1 (s_product, "*", scm_tc7_asubr, scm_product, g_product);
3737 /* "Return the product of all arguments. If called without arguments,\n"
3738 * "1 is returned."
3739 */
3740 SCM
3741 scm_product (SCM x, SCM y)
3742 {
3743 if (SCM_UNBNDP (y)) {
3744 if (SCM_UNBNDP (x)) {
3745 return SCM_MAKINUM (1L);
3746 } else if (SCM_NUMBERP (x)) {
3747 return x;
3748 } else {
3749 SCM_WTA_DISPATCH_1 (g_product, x, SCM_ARG1, s_product);
3750 }
3751 }
3752
3753 if (SCM_INUMP (x)) {
3754 long xx;
3755
3756 intbig:
3757 xx = SCM_INUM (x);
3758
3759 if (xx == 0) {
3760 return x;
3761 } else if (xx == 1) {
3762 return y;
3763 }
3764
3765 if (SCM_INUMP (y)) {
3766 long yy = SCM_INUM (y);
3767 long kk = xx * yy;
3768 SCM k = SCM_MAKINUM (kk);
3769 if (kk != SCM_INUM (k) || kk / xx != yy) {
3770 #ifdef SCM_BIGDIG
3771 int sgn = (xx < 0) ^ (yy < 0);
3772 #ifndef SCM_DIGSTOOBIG
3773 long i = scm_pseudolong (xx);
3774 long j = scm_pseudolong (yy);
3775 return scm_mulbig ((SCM_BIGDIG *) & i, SCM_DIGSPERLONG,
3776 (SCM_BIGDIG *) & j, SCM_DIGSPERLONG, sgn);
3777 #else /* SCM_DIGSTOOBIG */
3778 SCM_BIGDIG xdigs [SCM_DIGSPERLONG];
3779 SCM_BIGDIG ydigs [SCM_DIGSPERLONG];
3780 scm_longdigs (xx, xdigs);
3781 scm_longdigs (yy, ydigs);
3782 return scm_mulbig (xdigs, SCM_DIGSPERLONG,
3783 ydigs, SCM_DIGSPERLONG,
3784 sgn);
3785 #endif
3786 #else
3787 return scm_make_real (((double) xx) * ((double) yy));
3788 #endif
3789 } else {
3790 return k;
3791 }
3792 } else if (SCM_BIGP (y)) {
3793 #ifndef SCM_DIGSTOOBIG
3794 long z = scm_pseudolong (xx);
3795 return scm_mulbig ((SCM_BIGDIG *) & z, SCM_DIGSPERLONG,
3796 SCM_BDIGITS (y), SCM_NUMDIGS (y),
3797 SCM_BIGSIGN (y) ? (xx > 0) : (xx < 0));
3798 #else
3799 SCM_BIGDIG zdigs [SCM_DIGSPERLONG];
3800 scm_longdigs (xx, zdigs);
3801 return scm_mulbig (zdigs, SCM_DIGSPERLONG,
3802 SCM_BDIGITS (y), SCM_NUMDIGS (y),
3803 SCM_BIGSIGN (y) ? (xx > 0) : (xx < 0));
3804 #endif
3805 } else if (SCM_REALP (y)) {
3806 return scm_make_real (xx * SCM_REAL_VALUE (y));
3807 } else if (SCM_COMPLEXP (y)) {
3808 return scm_make_complex (xx * SCM_COMPLEX_REAL (y),
3809 xx * SCM_COMPLEX_IMAG (y));
3810 } else {
3811 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
3812 }
3813 } else if (SCM_BIGP (x)) {
3814 if (SCM_INUMP (y)) {
3815 SCM_SWAP (x, y);
3816 goto intbig;
3817 } else if (SCM_BIGP (y)) {
3818 return scm_mulbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
3819 SCM_BDIGITS (y), SCM_NUMDIGS (y),
3820 SCM_BIGSIGN (x) ^ SCM_BIGSIGN (y));
3821 } else if (SCM_REALP (y)) {
3822 return scm_make_real (scm_i_big2dbl (x) * SCM_REAL_VALUE (y));
3823 } else if (SCM_COMPLEXP (y)) {
3824 double z = scm_i_big2dbl (x);
3825 return scm_make_complex (z * SCM_COMPLEX_REAL (y),
3826 z * SCM_COMPLEX_IMAG (y));
3827 } else {
3828 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
3829 }
3830 } else if (SCM_REALP (x)) {
3831 if (SCM_INUMP (y)) {
3832 return scm_make_real (SCM_INUM (y) * SCM_REAL_VALUE (x));
3833 } else if (SCM_BIGP (y)) {
3834 return scm_make_real (scm_i_big2dbl (y) * SCM_REAL_VALUE (x));
3835 } else if (SCM_REALP (y)) {
3836 return scm_make_real (SCM_REAL_VALUE (x) * SCM_REAL_VALUE (y));
3837 } else if (SCM_COMPLEXP (y)) {
3838 return scm_make_complex (SCM_REAL_VALUE (x) * SCM_COMPLEX_REAL (y),
3839 SCM_REAL_VALUE (x) * SCM_COMPLEX_IMAG (y));
3840 } else {
3841 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
3842 }
3843 } else if (SCM_COMPLEXP (x)) {
3844 if (SCM_INUMP (y)) {
3845 return scm_make_complex (SCM_INUM (y) * SCM_COMPLEX_REAL (x),
3846 SCM_INUM (y) * SCM_COMPLEX_IMAG (x));
3847 } else if (SCM_BIGP (y)) {
3848 double z = scm_i_big2dbl (y);
3849 return scm_make_complex (z * SCM_COMPLEX_REAL (x),
3850 z * SCM_COMPLEX_IMAG (x));
3851 } else if (SCM_REALP (y)) {
3852 return scm_make_complex (SCM_REAL_VALUE (y) * SCM_COMPLEX_REAL (x),
3853 SCM_REAL_VALUE (y) * SCM_COMPLEX_IMAG (x));
3854 } else if (SCM_COMPLEXP (y)) {
3855 return scm_make_complex (SCM_COMPLEX_REAL (x) * SCM_COMPLEX_REAL (y)
3856 - SCM_COMPLEX_IMAG (x) * SCM_COMPLEX_IMAG (y),
3857 SCM_COMPLEX_REAL (x) * SCM_COMPLEX_IMAG (y)
3858 + SCM_COMPLEX_IMAG (x) * SCM_COMPLEX_REAL (y));
3859 } else {
3860 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
3861 }
3862 } else {
3863 SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARG1, s_product);
3864 }
3865 }
3866
3867
3868 double
3869 scm_num2dbl (SCM a, const char *why)
3870 #define FUNC_NAME why
3871 {
3872 if (SCM_INUMP (a)) {
3873 return (double) SCM_INUM (a);
3874 } else if (SCM_BIGP (a)) {
3875 return scm_i_big2dbl (a);
3876 } else if (SCM_REALP (a)) {
3877 return (SCM_REAL_VALUE (a));
3878 } else {
3879 SCM_WRONG_TYPE_ARG (SCM_ARGn, a);
3880 }
3881 }
3882 #undef FUNC_NAME
3883
3884 #if ((defined (HAVE_ISINF) && defined (HAVE_ISNAN)) \
3885 || (defined (HAVE_FINITE) && defined (HAVE_ISNAN)))
3886 #define ALLOW_DIVIDE_BY_ZERO
3887 /* #define ALLOW_DIVIDE_BY_EXACT_ZERO */
3888 #endif
3889
3890 /* The code below for complex division is adapted from the GNU
3891 libstdc++, which adapted it from f2c's libF77, and is subject to
3892 this copyright: */
3893
3894 /****************************************************************
3895 Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories and Bellcore.
3896
3897 Permission to use, copy, modify, and distribute this software
3898 and its documentation for any purpose and without fee is hereby
3899 granted, provided that the above copyright notice appear in all
3900 copies and that both that the copyright notice and this
3901 permission notice and warranty disclaimer appear in supporting
3902 documentation, and that the names of AT&T Bell Laboratories or
3903 Bellcore or any of their entities not be used in advertising or
3904 publicity pertaining to distribution of the software without
3905 specific, written prior permission.
3906
3907 AT&T and Bellcore disclaim all warranties with regard to this
3908 software, including all implied warranties of merchantability
3909 and fitness. In no event shall AT&T or Bellcore be liable for
3910 any special, indirect or consequential damages or any damages
3911 whatsoever resulting from loss of use, data or profits, whether
3912 in an action of contract, negligence or other tortious action,
3913 arising out of or in connection with the use or performance of
3914 this software.
3915 ****************************************************************/
3916
3917 SCM_GPROC1 (s_divide, "/", scm_tc7_asubr, scm_divide, g_divide);
3918 /* Divide the first argument by the product of the remaining
3919 arguments. If called with one argument @var{z1}, 1/@var{z1} is
3920 returned. */
3921 #define FUNC_NAME s_divide
3922 SCM
3923 scm_divide (SCM x, SCM y)
3924 {
3925 double a;
3926
3927 if (SCM_UNBNDP (y)) {
3928 if (SCM_UNBNDP (x)) {
3929 SCM_WTA_DISPATCH_0 (g_divide, s_divide);
3930 } else if (SCM_INUMP (x)) {
3931 long xx = SCM_INUM (x);
3932 if (xx == 1 || xx == -1) {
3933 return x;
3934 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
3935 } else if (xx == 0) {
3936 scm_num_overflow (s_divide);
3937 #endif
3938 } else {
3939 return scm_make_real (1.0 / (double) xx);
3940 }
3941 } else if (SCM_BIGP (x)) {
3942 return scm_make_real (1.0 / scm_i_big2dbl (x));
3943 } else if (SCM_REALP (x)) {
3944 double xx = SCM_REAL_VALUE (x);
3945 #ifndef ALLOW_DIVIDE_BY_ZERO
3946 if (xx == 0.0)
3947 scm_num_overflow (s_divide);
3948 else
3949 #endif
3950 return scm_make_real (1.0 / xx);
3951 } else if (SCM_COMPLEXP (x)) {
3952 double r = SCM_COMPLEX_REAL (x);
3953 double i = SCM_COMPLEX_IMAG (x);
3954 if (r <= i) {
3955 double t = r / i;
3956 double d = i * (1.0 + t * t);
3957 return scm_make_complex (t / d, -1.0 / d);
3958 } else {
3959 double t = i / r;
3960 double d = r * (1.0 + t * t);
3961 return scm_make_complex (1.0 / d, -t / d);
3962 }
3963 } else {
3964 SCM_WTA_DISPATCH_1 (g_divide, x, SCM_ARG1, s_divide);
3965 }
3966 }
3967
3968 if (SCM_INUMP (x)) {
3969 long xx = SCM_INUM (x);
3970 if (SCM_INUMP (y)) {
3971 long yy = SCM_INUM (y);
3972 if (yy == 0) {
3973 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
3974 scm_num_overflow (s_divide);
3975 #else
3976 return scm_make_real ((double) xx / (double) yy);
3977 #endif
3978 } else if (xx % yy != 0) {
3979 return scm_make_real ((double) xx / (double) yy);
3980 } else {
3981 long z = xx / yy;
3982 if (SCM_FIXABLE (z)) {
3983 return SCM_MAKINUM (z);
3984 } else {
3985 #ifdef SCM_BIGDIG
3986 return scm_i_long2big (z);
3987 #else
3988 return scm_make_real ((double) xx / (double) yy);
3989 #endif
3990 }
3991 }
3992 } else if (SCM_BIGP (y)) {
3993 return scm_make_real ((double) xx / scm_i_big2dbl (y));
3994 } else if (SCM_REALP (y)) {
3995 double yy = SCM_REAL_VALUE (y);
3996 #ifndef ALLOW_DIVIDE_BY_ZERO
3997 if (yy == 0.0)
3998 scm_num_overflow (s_divide);
3999 else
4000 #endif
4001 return scm_make_real ((double) xx / yy);
4002 } else if (SCM_COMPLEXP (y)) {
4003 a = xx;
4004 complex_div: /* y _must_ be a complex number */
4005 {
4006 double r = SCM_COMPLEX_REAL (y);
4007 double i = SCM_COMPLEX_IMAG (y);
4008 if (r <= i) {
4009 double t = r / i;
4010 double d = i * (1.0 + t * t);
4011 return scm_make_complex ((a * t) / d, -a / d);
4012 } else {
4013 double t = i / r;
4014 double d = r * (1.0 + t * t);
4015 return scm_make_complex (a / d, -(a * t) / d);
4016 }
4017 }
4018 } else {
4019 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
4020 }
4021 } else if (SCM_BIGP (x)) {
4022 if (SCM_INUMP (y)) {
4023 long int yy = SCM_INUM (y);
4024 if (yy == 0) {
4025 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4026 scm_num_overflow (s_divide);
4027 #else
4028 if (scm_bigcomp (x, scm_i_int2big (0)) == 0)
4029 return scm_nan ();
4030 else
4031 return scm_inf ();
4032 #endif
4033 } else if (yy == 1) {
4034 return x;
4035 } else {
4036 long z = yy < 0 ? -yy : yy;
4037 if (z < SCM_BIGRAD) {
4038 SCM w = scm_i_copybig (x, SCM_BIGSIGN (x) ? (yy > 0) : (yy < 0));
4039 return scm_divbigdig (SCM_BDIGITS (w), SCM_NUMDIGS (w),
4040 (SCM_BIGDIG) z)
4041 ? scm_make_real (scm_i_big2dbl (x) / (double) yy)
4042 : scm_i_normbig (w);
4043 } else {
4044 SCM w;
4045 #ifndef SCM_DIGSTOOBIG
4046 z = scm_pseudolong (z);
4047 w = scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
4048 (SCM_BIGDIG *) & z, SCM_DIGSPERLONG,
4049 SCM_BIGSIGN (x) ? (yy > 0) : (yy < 0), 3);
4050 #else
4051 SCM_BIGDIG zdigs[SCM_DIGSPERLONG];
4052 scm_longdigs (z, zdigs);
4053 w = scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
4054 zdigs, SCM_DIGSPERLONG,
4055 SCM_BIGSIGN (x) ? (yy > 0) : (yy < 0), 3);
4056 #endif
4057 return (!SCM_UNBNDP (w))
4058 ? w
4059 : scm_make_real (scm_i_big2dbl (x) / (double) yy);
4060 }
4061 }
4062 } else if (SCM_BIGP (y)) {
4063 SCM w = scm_divbigbig (SCM_BDIGITS (x), SCM_NUMDIGS (x),
4064 SCM_BDIGITS (y), SCM_NUMDIGS (y),
4065 SCM_BIGSIGN (x) ^ SCM_BIGSIGN (y), 3);
4066 return (!SCM_UNBNDP (w))
4067 ? w
4068 : scm_make_real (scm_i_big2dbl (x) / scm_i_big2dbl (y));
4069 } else if (SCM_REALP (y)) {
4070 double yy = SCM_REAL_VALUE (y);
4071 #ifndef ALLOW_DIVIDE_BY_ZERO
4072 if (yy == 0.0)
4073 scm_num_overflow (s_divide);
4074 else
4075 #endif
4076 return scm_make_real (scm_i_big2dbl (x) / yy);
4077 } else if (SCM_COMPLEXP (y)) {
4078 a = scm_i_big2dbl (x);
4079 goto complex_div;
4080 } else {
4081 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
4082 }
4083 } else if (SCM_REALP (x)) {
4084 double rx = SCM_REAL_VALUE (x);
4085 if (SCM_INUMP (y)) {
4086 long int yy = SCM_INUM (y);
4087 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4088 if (yy == 0)
4089 scm_num_overflow (s_divide);
4090 else
4091 #endif
4092 return scm_make_real (rx / (double) yy);
4093 } else if (SCM_BIGP (y)) {
4094 return scm_make_real (rx / scm_i_big2dbl (y));
4095 } else if (SCM_REALP (y)) {
4096 double yy = SCM_REAL_VALUE (y);
4097 #ifndef ALLOW_DIVIDE_BY_ZERO
4098 if (yy == 0.0)
4099 scm_num_overflow (s_divide);
4100 else
4101 #endif
4102 return scm_make_real (rx / yy);
4103 } else if (SCM_COMPLEXP (y)) {
4104 a = rx;
4105 goto complex_div;
4106 } else {
4107 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
4108 }
4109 } else if (SCM_COMPLEXP (x)) {
4110 double rx = SCM_COMPLEX_REAL (x);
4111 double ix = SCM_COMPLEX_IMAG (x);
4112 if (SCM_INUMP (y)) {
4113 long int yy = SCM_INUM (y);
4114 #ifndef ALLOW_DIVIDE_BY_EXACT_ZERO
4115 if (yy == 0)
4116 scm_num_overflow (s_divide);
4117 else
4118 #endif
4119 {
4120 double d = yy;
4121 return scm_make_complex (rx / d, ix / d);
4122 }
4123 } else if (SCM_BIGP (y)) {
4124 double d = scm_i_big2dbl (y);
4125 return scm_make_complex (rx / d, ix / d);
4126 } else if (SCM_REALP (y)) {
4127 double yy = SCM_REAL_VALUE (y);
4128 #ifndef ALLOW_DIVIDE_BY_ZERO
4129 if (yy == 0.0)
4130 scm_num_overflow (s_divide);
4131 else
4132 #endif
4133 return scm_make_complex (rx / yy, ix / yy);
4134 } else if (SCM_COMPLEXP (y)) {
4135 double ry = SCM_COMPLEX_REAL (y);
4136 double iy = SCM_COMPLEX_IMAG (y);
4137 if (ry <= iy) {
4138 double t = ry / iy;
4139 double d = iy * (1.0 + t * t);
4140 return scm_make_complex ((rx * t + ix) / d, (ix * t - rx) / d);
4141 } else {
4142 double t = iy / ry;
4143 double d = ry * (1.0 + t * t);
4144 return scm_make_complex ((rx + ix * t) / d, (ix - rx * t) / d);
4145 }
4146 } else {
4147 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARGn, s_divide);
4148 }
4149 } else {
4150 SCM_WTA_DISPATCH_2 (g_divide, x, y, SCM_ARG1, s_divide);
4151 }
4152 }
4153 #undef FUNC_NAME
4154
4155 SCM_GPROC1 (s_asinh, "$asinh", scm_tc7_cxr, (SCM (*)()) scm_asinh, g_asinh);
4156 /* "Return the inverse hyperbolic sine of @var{x}."
4157 */
4158 double
4159 scm_asinh (double x)
4160 {
4161 return log (x + sqrt (x * x + 1));
4162 }
4163
4164
4165
4166
4167 SCM_GPROC1 (s_acosh, "$acosh", scm_tc7_cxr, (SCM (*)()) scm_acosh, g_acosh);
4168 /* "Return the inverse hyperbolic cosine of @var{x}."
4169 */
4170 double
4171 scm_acosh (double x)
4172 {
4173 return log (x + sqrt (x * x - 1));
4174 }
4175
4176
4177
4178
4179 SCM_GPROC1 (s_atanh, "$atanh", scm_tc7_cxr, (SCM (*)()) scm_atanh, g_atanh);
4180 /* "Return the inverse hyperbolic tangent of @var{x}."
4181 */
4182 double
4183 scm_atanh (double x)
4184 {
4185 return 0.5 * log ((1 + x) / (1 - x));
4186 }
4187
4188
4189
4190
4191 SCM_GPROC1 (s_truncate, "truncate", scm_tc7_cxr, (SCM (*)()) scm_truncate, g_truncate);
4192 /* "Round the inexact number @var{x} towards zero."
4193 */
4194 double
4195 scm_truncate (double x)
4196 {
4197 if (x < 0.0)
4198 return -floor (-x);
4199 return floor (x);
4200 }
4201
4202
4203
4204 SCM_GPROC1 (s_round, "round", scm_tc7_cxr, (SCM (*)()) scm_round, g_round);
4205 /* "Round the inexact number @var{x}. If @var{x} is halfway between two\n"
4206 * "numbers, round towards even."
4207 */
4208 double
4209 scm_round (double x)
4210 {
4211 double plus_half = x + 0.5;
4212 double result = floor (plus_half);
4213 /* Adjust so that the scm_round is towards even. */
4214 return (plus_half == result && plus_half / 2 != floor (plus_half / 2))
4215 ? result - 1 : result;
4216 }
4217
4218
4219 SCM_GPROC1 (s_i_floor, "floor", scm_tc7_cxr, (SCM (*)()) floor, g_i_floor);
4220 /* "Round the number @var{x} towards minus infinity."
4221 */
4222 SCM_GPROC1 (s_i_ceil, "ceiling", scm_tc7_cxr, (SCM (*)()) ceil, g_i_ceil);
4223 /* "Round the number @var{x} towards infinity."
4224 */
4225 SCM_GPROC1 (s_i_sqrt, "$sqrt", scm_tc7_cxr, (SCM (*)()) sqrt, g_i_sqrt);
4226 /* "Return the square root of the real number @var{x}."
4227 */
4228 SCM_GPROC1 (s_i_abs, "$abs", scm_tc7_cxr, (SCM (*)()) fabs, g_i_abs);
4229 /* "Return the absolute value of the real number @var{x}."
4230 */
4231 SCM_GPROC1 (s_i_exp, "$exp", scm_tc7_cxr, (SCM (*)()) exp, g_i_exp);
4232 /* "Return the @var{x}th power of e."
4233 */
4234 SCM_GPROC1 (s_i_log, "$log", scm_tc7_cxr, (SCM (*)()) log, g_i_log);
4235 /* "Return the natural logarithm of the real number @var{x}."
4236 */
4237 SCM_GPROC1 (s_i_sin, "$sin", scm_tc7_cxr, (SCM (*)()) sin, g_i_sin);
4238 /* "Return the sine of the real number @var{x}."
4239 */
4240 SCM_GPROC1 (s_i_cos, "$cos", scm_tc7_cxr, (SCM (*)()) cos, g_i_cos);
4241 /* "Return the cosine of the real number @var{x}."
4242 */
4243 SCM_GPROC1 (s_i_tan, "$tan", scm_tc7_cxr, (SCM (*)()) tan, g_i_tan);
4244 /* "Return the tangent of the real number @var{x}."
4245 */
4246 SCM_GPROC1 (s_i_asin, "$asin", scm_tc7_cxr, (SCM (*)()) asin, g_i_asin);
4247 /* "Return the arc sine of the real number @var{x}."
4248 */
4249 SCM_GPROC1 (s_i_acos, "$acos", scm_tc7_cxr, (SCM (*)()) acos, g_i_acos);
4250 /* "Return the arc cosine of the real number @var{x}."
4251 */
4252 SCM_GPROC1 (s_i_atan, "$atan", scm_tc7_cxr, (SCM (*)()) atan, g_i_atan);
4253 /* "Return the arc tangent of the real number @var{x}."
4254 */
4255 SCM_GPROC1 (s_i_sinh, "$sinh", scm_tc7_cxr, (SCM (*)()) sinh, g_i_sinh);
4256 /* "Return the hyperbolic sine of the real number @var{x}."
4257 */
4258 SCM_GPROC1 (s_i_cosh, "$cosh", scm_tc7_cxr, (SCM (*)()) cosh, g_i_cosh);
4259 /* "Return the hyperbolic cosine of the real number @var{x}."
4260 */
4261 SCM_GPROC1 (s_i_tanh, "$tanh", scm_tc7_cxr, (SCM (*)()) tanh, g_i_tanh);
4262 /* "Return the hyperbolic tangent of the real number @var{x}."
4263 */
4264
4265 struct dpair
4266 {
4267 double x, y;
4268 };
4269
4270 static void scm_two_doubles (SCM x,
4271 SCM y,
4272 const char *sstring,
4273 struct dpair * xy);
4274
4275 static void
4276 scm_two_doubles (SCM x, SCM y, const char *sstring, struct dpair *xy)
4277 {
4278 if (SCM_INUMP (x)) {
4279 xy->x = SCM_INUM (x);
4280 } else if (SCM_BIGP (x)) {
4281 xy->x = scm_i_big2dbl (x);
4282 } else if (SCM_REALP (x)) {
4283 xy->x = SCM_REAL_VALUE (x);
4284 } else {
4285 scm_wrong_type_arg (sstring, SCM_ARG1, x);
4286 }
4287
4288 if (SCM_INUMP (y)) {
4289 xy->y = SCM_INUM (y);
4290 } else if (SCM_BIGP (y)) {
4291 xy->y = scm_i_big2dbl (y);
4292 } else if (SCM_REALP (y)) {
4293 xy->y = SCM_REAL_VALUE (y);
4294 } else {
4295 scm_wrong_type_arg (sstring, SCM_ARG2, y);
4296 }
4297 }
4298
4299
4300 SCM_DEFINE (scm_sys_expt, "$expt", 2, 0, 0,
4301 (SCM x, SCM y),
4302 "Return @var{x} raised to the power of @var{y}. This\n"
4303 "procedure does not accept complex arguments.")
4304 #define FUNC_NAME s_scm_sys_expt
4305 {
4306 struct dpair xy;
4307 scm_two_doubles (x, y, FUNC_NAME, &xy);
4308 return scm_make_real (pow (xy.x, xy.y));
4309 }
4310 #undef FUNC_NAME
4311
4312
4313 SCM_DEFINE (scm_sys_atan2, "$atan2", 2, 0, 0,
4314 (SCM x, SCM y),
4315 "Return the arc tangent of the two arguments @var{x} and\n"
4316 "@var{y}. This is similar to calculating the arc tangent of\n"
4317 "@var{x} / @var{y}, except that the signs of both arguments\n"
4318 "are used to determine the quadrant of the result. This\n"
4319 "procedure does not accept complex arguments.")
4320 #define FUNC_NAME s_scm_sys_atan2
4321 {
4322 struct dpair xy;
4323 scm_two_doubles (x, y, FUNC_NAME, &xy);
4324 return scm_make_real (atan2 (xy.x, xy.y));
4325 }
4326 #undef FUNC_NAME
4327
4328
4329 SCM_DEFINE (scm_make_rectangular, "make-rectangular", 2, 0, 0,
4330 (SCM real, SCM imaginary),
4331 "Return a complex number constructed of the given @var{real} and\n"
4332 "@var{imaginary} parts.")
4333 #define FUNC_NAME s_scm_make_rectangular
4334 {
4335 struct dpair xy;
4336 scm_two_doubles (real, imaginary, FUNC_NAME, &xy);
4337 return scm_make_complex (xy.x, xy.y);
4338 }
4339 #undef FUNC_NAME
4340
4341
4342
4343 SCM_DEFINE (scm_make_polar, "make-polar", 2, 0, 0,
4344 (SCM x, SCM y),
4345 "Return the complex number @var{x} * e^(i * @var{y}).")
4346 #define FUNC_NAME s_scm_make_polar
4347 {
4348 struct dpair xy;
4349 scm_two_doubles (x, y, FUNC_NAME, &xy);
4350 return scm_make_complex (xy.x * cos (xy.y), xy.x * sin (xy.y));
4351 }
4352 #undef FUNC_NAME
4353
4354
4355 SCM_GPROC (s_real_part, "real-part", 1, 0, 0, scm_real_part, g_real_part);
4356 /* "Return the real part of the number @var{z}."
4357 */
4358 SCM
4359 scm_real_part (SCM z)
4360 {
4361 if (SCM_INUMP (z)) {
4362 return z;
4363 } else if (SCM_BIGP (z)) {
4364 return z;
4365 } else if (SCM_REALP (z)) {
4366 return z;
4367 } else if (SCM_COMPLEXP (z)) {
4368 return scm_make_real (SCM_COMPLEX_REAL (z));
4369 } else {
4370 SCM_WTA_DISPATCH_1 (g_real_part, z, SCM_ARG1, s_real_part);
4371 }
4372 }
4373
4374
4375 SCM_GPROC (s_imag_part, "imag-part", 1, 0, 0, scm_imag_part, g_imag_part);
4376 /* "Return the imaginary part of the number @var{z}."
4377 */
4378 SCM
4379 scm_imag_part (SCM z)
4380 {
4381 if (SCM_INUMP (z)) {
4382 return SCM_INUM0;
4383 } else if (SCM_BIGP (z)) {
4384 return SCM_INUM0;
4385 } else if (SCM_REALP (z)) {
4386 return scm_flo0;
4387 } else if (SCM_COMPLEXP (z)) {
4388 return scm_make_real (SCM_COMPLEX_IMAG (z));
4389 } else {
4390 SCM_WTA_DISPATCH_1 (g_imag_part, z, SCM_ARG1, s_imag_part);
4391 }
4392 }
4393
4394
4395 SCM_GPROC (s_magnitude, "magnitude", 1, 0, 0, scm_magnitude, g_magnitude);
4396 /* "Return the magnitude of the number @var{z}. This is the same as\n"
4397 * "@code{abs} for real arguments, but also allows complex numbers."
4398 */
4399 SCM
4400 scm_magnitude (SCM z)
4401 {
4402 if (SCM_INUMP (z)) {
4403 long int zz = SCM_INUM (z);
4404 if (zz >= 0) {
4405 return z;
4406 } else if (SCM_POSFIXABLE (-zz)) {
4407 return SCM_MAKINUM (-zz);
4408 } else {
4409 #ifdef SCM_BIGDIG
4410 return scm_i_long2big (-zz);
4411 #else
4412 scm_num_overflow (s_magnitude);
4413 #endif
4414 }
4415 } else if (SCM_BIGP (z)) {
4416 if (!SCM_BIGSIGN (z)) {
4417 return z;
4418 } else {
4419 return scm_i_copybig (z, 0);
4420 }
4421 } else if (SCM_REALP (z)) {
4422 return scm_make_real (fabs (SCM_REAL_VALUE (z)));
4423 } else if (SCM_COMPLEXP (z)) {
4424 double r = SCM_COMPLEX_REAL (z);
4425 double i = SCM_COMPLEX_IMAG (z);
4426 return scm_make_real (sqrt (i * i + r * r));
4427 } else {
4428 SCM_WTA_DISPATCH_1 (g_magnitude, z, SCM_ARG1, s_magnitude);
4429 }
4430 }
4431
4432
4433 SCM_GPROC (s_angle, "angle", 1, 0, 0, scm_angle, g_angle);
4434 /* "Return the angle of the complex number @var{z}."
4435 */
4436 SCM
4437 scm_angle (SCM z)
4438 {
4439 if (SCM_INUMP (z)) {
4440 if (SCM_INUM (z) >= 0) {
4441 return scm_make_real (atan2 (0.0, 1.0));
4442 } else {
4443 return scm_make_real (atan2 (0.0, -1.0));
4444 }
4445 } else if (SCM_BIGP (z)) {
4446 if (SCM_BIGSIGN (z)) {
4447 return scm_make_real (atan2 (0.0, -1.0));
4448 } else {
4449 return scm_make_real (atan2 (0.0, 1.0));
4450 }
4451 } else if (SCM_REALP (z)) {
4452 return scm_make_real (atan2 (0.0, SCM_REAL_VALUE (z)));
4453 } else if (SCM_COMPLEXP (z)) {
4454 return scm_make_real (atan2 (SCM_COMPLEX_IMAG (z), SCM_COMPLEX_REAL (z)));
4455 } else {
4456 SCM_WTA_DISPATCH_1 (g_angle, z, SCM_ARG1, s_angle);
4457 }
4458 }
4459
4460
4461 SCM_GPROC (s_exact_to_inexact, "exact->inexact", 1, 0, 0, scm_exact_to_inexact, g_exact_to_inexact);
4462 /* Convert the number @var{x} to its inexact representation.\n"
4463 */
4464 SCM
4465 scm_exact_to_inexact (SCM z)
4466 {
4467 if (SCM_INUMP (z))
4468 return scm_make_real ((double) SCM_INUM (z));
4469 else if (SCM_BIGP (z))
4470 return scm_make_real (scm_i_big2dbl (z));
4471 else if (SCM_INEXACTP (z))
4472 return z;
4473 else
4474 SCM_WTA_DISPATCH_1 (g_exact_to_inexact, z, 1, s_exact_to_inexact);
4475 }
4476
4477
4478 SCM_DEFINE (scm_inexact_to_exact, "inexact->exact", 1, 0, 0,
4479 (SCM z),
4480 "Return an exact number that is numerically closest to @var{z}.")
4481 #define FUNC_NAME s_scm_inexact_to_exact
4482 {
4483 if (SCM_INUMP (z)) {
4484 return z;
4485 } else if (SCM_BIGP (z)) {
4486 return z;
4487 } else if (SCM_REALP (z)) {
4488 double u = floor (SCM_REAL_VALUE (z) + 0.5);
4489 long lu = (long) u;
4490 if (SCM_FIXABLE (lu)) {
4491 return SCM_MAKINUM (lu);
4492 #ifdef SCM_BIGDIG
4493 } else if (isfinite (u) && !xisnan (u)) {
4494 return scm_i_dbl2big (u);
4495 #endif
4496 } else {
4497 scm_num_overflow (s_scm_inexact_to_exact);
4498 }
4499 } else {
4500 SCM_WRONG_TYPE_ARG (1, z);
4501 }
4502 }
4503 #undef FUNC_NAME
4504
4505
4506 #ifdef SCM_BIGDIG
4507 /* d must be integer */
4508
4509 SCM
4510 scm_i_dbl2big (double d)
4511 {
4512 size_t i = 0;
4513 long c;
4514 SCM_BIGDIG *digits;
4515 SCM ans;
4516 double u = (d < 0) ? -d : d;
4517 while (0 != floor (u))
4518 {
4519 u /= SCM_BIGRAD;
4520 i++;
4521 }
4522 ans = scm_i_mkbig (i, d < 0);
4523 digits = SCM_BDIGITS (ans);
4524 while (i--)
4525 {
4526 u *= SCM_BIGRAD;
4527 c = floor (u);
4528 u -= c;
4529 digits[i] = c;
4530 }
4531 if (u != 0)
4532 scm_num_overflow ("dbl2big");
4533 return ans;
4534 }
4535
4536 double
4537 scm_i_big2dbl (SCM b)
4538 {
4539 double ans = 0.0;
4540 size_t i = SCM_NUMDIGS (b);
4541 SCM_BIGDIG *digits = SCM_BDIGITS (b);
4542 while (i--)
4543 ans = digits[i] + SCM_BIGRAD * ans;
4544 if (SCM_BIGSIGN (b))
4545 return - ans;
4546 return ans;
4547 }
4548
4549 #endif
4550
4551 #ifdef HAVE_LONG_LONGS
4552 # ifndef LLONG_MAX
4553 # define ULLONG_MAX ((unsigned long long) (-1))
4554 # define LLONG_MAX ((long long) (ULLONG_MAX >> 1))
4555 # define LLONG_MIN (~LLONG_MAX)
4556 # endif
4557 #endif
4558
4559 /* Parameters for creating integer conversion routines.
4560
4561 Define the following preprocessor macros before including
4562 "libguile/num2integral.i.c":
4563
4564 NUM2INTEGRAL - the name of the function for converting from a
4565 Scheme object to the integral type. This function
4566 will be defined when including "num2integral.i.c".
4567
4568 INTEGRAL2NUM - the name of the function for converting from the
4569 integral type to a Scheme object. This function
4570 will be defined.
4571
4572 INTEGRAL2BIG - the name of an internal function that createas a
4573 bignum from the integral type. This function will
4574 be defined. The name should start with "scm_i_".
4575
4576 ITYPE - the name of the integral type.
4577
4578 UNSIGNED - Define this when ITYPE is an unsigned type. Do not
4579 define it otherwise.
4580
4581 UNSIGNED_ITYPE
4582 - the name of the the unsigned variant of the
4583 integral type. If you don't define this, it defaults
4584 to "unsigned ITYPE" for signed types and simply "ITYPE"
4585 for unsigned ones.
4586
4587 SIZEOF_ITYPE - an expression giving the size of the integral type in
4588 bytes. This expression must be computable by the
4589 preprocessor. If you don't know a value for this,
4590 don't define it. The purpose of this parameter is
4591 mainly to suppress some warnings. The generated
4592 code will work correctly without it.
4593 */
4594
4595 #define NUM2INTEGRAL scm_num2short
4596 #define INTEGRAL2NUM scm_short2num
4597 #define INTEGRAL2BIG scm_i_short2big
4598 #define ITYPE short
4599 #define SIZEOF_ITYPE SIZEOF_SHORT
4600 #include "libguile/num2integral.i.c"
4601
4602 #define NUM2INTEGRAL scm_num2ushort
4603 #define INTEGRAL2NUM scm_ushort2num
4604 #define INTEGRAL2BIG scm_i_ushort2big
4605 #define UNSIGNED
4606 #define ITYPE unsigned short
4607 #define SIZEOF_ITYPE SIZEOF_SHORT
4608 #include "libguile/num2integral.i.c"
4609
4610 #define NUM2INTEGRAL scm_num2int
4611 #define INTEGRAL2NUM scm_int2num
4612 #define INTEGRAL2BIG scm_i_int2big
4613 #define ITYPE int
4614 #define SIZEOF_ITYPE SIZEOF_INT
4615 #include "libguile/num2integral.i.c"
4616
4617 #define NUM2INTEGRAL scm_num2uint
4618 #define INTEGRAL2NUM scm_uint2num
4619 #define INTEGRAL2BIG scm_i_uint2big
4620 #define UNSIGNED
4621 #define ITYPE unsigned int
4622 #define SIZEOF_ITYPE SIZEOF_INT
4623 #include "libguile/num2integral.i.c"
4624
4625 #define NUM2INTEGRAL scm_num2long
4626 #define INTEGRAL2NUM scm_long2num
4627 #define INTEGRAL2BIG scm_i_long2big
4628 #define ITYPE long
4629 #define SIZEOF_ITYPE SIZEOF_LONG
4630 #include "libguile/num2integral.i.c"
4631
4632 #define NUM2INTEGRAL scm_num2ulong
4633 #define INTEGRAL2NUM scm_ulong2num
4634 #define INTEGRAL2BIG scm_i_ulong2big
4635 #define UNSIGNED
4636 #define ITYPE unsigned long
4637 #define SIZEOF_ITYPE SIZEOF_LONG
4638 #include "libguile/num2integral.i.c"
4639
4640 #define NUM2INTEGRAL scm_num2ptrdiff
4641 #define INTEGRAL2NUM scm_ptrdiff2num
4642 #define INTEGRAL2BIG scm_i_ptrdiff2big
4643 #define ITYPE ptrdiff_t
4644 #define UNSIGNED_ITYPE size_t
4645 #define SIZEOF_ITYPE SIZEOF_PTRDIFF_T
4646 #include "libguile/num2integral.i.c"
4647
4648 #define NUM2INTEGRAL scm_num2size
4649 #define INTEGRAL2NUM scm_size2num
4650 #define INTEGRAL2BIG scm_i_size2big
4651 #define UNSIGNED
4652 #define ITYPE size_t
4653 #define SIZEOF_ITYPE SIZEOF_SIZE_T
4654 #include "libguile/num2integral.i.c"
4655
4656 #ifdef HAVE_LONG_LONGS
4657
4658 #ifndef ULONG_LONG_MAX
4659 #define ULONG_LONG_MAX (~0ULL)
4660 #endif
4661
4662 #define NUM2INTEGRAL scm_num2long_long
4663 #define INTEGRAL2NUM scm_long_long2num
4664 #define INTEGRAL2BIG scm_i_long_long2big
4665 #define ITYPE long long
4666 #define SIZEOF_ITYPE SIZEOF_LONG_LONG
4667 #include "libguile/num2integral.i.c"
4668
4669 #define NUM2INTEGRAL scm_num2ulong_long
4670 #define INTEGRAL2NUM scm_ulong_long2num
4671 #define INTEGRAL2BIG scm_i_ulong_long2big
4672 #define UNSIGNED
4673 #define ITYPE unsigned long long
4674 #define SIZEOF_ITYPE SIZEOF_LONG_LONG
4675 #include "libguile/num2integral.i.c"
4676
4677 #endif /* HAVE_LONG_LONGS */
4678
4679 #define NUM2FLOAT scm_num2float
4680 #define FLOAT2NUM scm_float2num
4681 #define FTYPE float
4682 #include "libguile/num2float.i.c"
4683
4684 #define NUM2FLOAT scm_num2double
4685 #define FLOAT2NUM scm_double2num
4686 #define FTYPE double
4687 #include "libguile/num2float.i.c"
4688
4689 #ifdef GUILE_DEBUG
4690
4691 #ifndef SIZE_MAX
4692 #define SIZE_MAX ((size_t) (-1))
4693 #endif
4694 #ifndef PTRDIFF_MIN
4695 #define PTRDIFF_MIN \
4696 ((ptrdiff_t) ((ptrdiff_t) 1 << (sizeof (ptrdiff_t) * 8 - 1)))
4697 #endif
4698 #ifndef PTRDIFF_MAX
4699 #define PTRDIFF_MAX (~ PTRDIFF_MIN)
4700 #endif
4701
4702 #define CHECK(type, v) \
4703 do { \
4704 if ((v) != scm_num2##type (scm_##type##2num (v), 1, "check_sanity")) \
4705 abort (); \
4706 } while (0);
4707
4708 static void
4709 check_sanity ()
4710 {
4711 CHECK (short, 0);
4712 CHECK (ushort, 0U);
4713 CHECK (int, 0);
4714 CHECK (uint, 0U);
4715 CHECK (long, 0L);
4716 CHECK (ulong, 0UL);
4717 CHECK (size, 0);
4718 CHECK (ptrdiff, 0);
4719
4720 CHECK (short, -1);
4721 CHECK (int, -1);
4722 CHECK (long, -1L);
4723 CHECK (ptrdiff, -1);
4724
4725 CHECK (short, SHRT_MAX);
4726 CHECK (short, SHRT_MIN);
4727 CHECK (ushort, USHRT_MAX);
4728 CHECK (int, INT_MAX);
4729 CHECK (int, INT_MIN);
4730 CHECK (uint, UINT_MAX);
4731 CHECK (long, LONG_MAX);
4732 CHECK (long, LONG_MIN);
4733 CHECK (ulong, ULONG_MAX);
4734 CHECK (size, SIZE_MAX);
4735 CHECK (ptrdiff, PTRDIFF_MAX);
4736 CHECK (ptrdiff, PTRDIFF_MIN);
4737
4738 #ifdef HAVE_LONG_LONGS
4739 CHECK (long_long, 0LL);
4740 CHECK (ulong_long, 0ULL);
4741 CHECK (long_long, -1LL);
4742 CHECK (long_long, LLONG_MAX);
4743 CHECK (long_long, LLONG_MIN);
4744 CHECK (ulong_long, ULLONG_MAX);
4745 #endif
4746 }
4747
4748 #undef CHECK
4749
4750 #define CHECK \
4751 scm_internal_catch (SCM_BOOL_T, check_body, &data, check_handler, &data); \
4752 if (!SCM_FALSEP (data)) abort();
4753
4754 static SCM
4755 check_body (void *data)
4756 {
4757 SCM num = *(SCM *) data;
4758 scm_num2ulong (num, 1, NULL);
4759
4760 return SCM_UNSPECIFIED;
4761 }
4762
4763 static SCM
4764 check_handler (void *data, SCM tag, SCM throw_args)
4765 {
4766 SCM *num = (SCM *) data;
4767 *num = SCM_BOOL_F;
4768
4769 return SCM_UNSPECIFIED;
4770 }
4771
4772 SCM_DEFINE (scm_sys_check_number_conversions, "%check-number-conversions", 0, 0, 0,
4773 (void),
4774 "Number conversion sanity checking.")
4775 #define FUNC_NAME s_scm_sys_check_number_conversions
4776 {
4777 SCM data = SCM_MAKINUM (-1);
4778 CHECK;
4779 data = scm_int2num (INT_MIN);
4780 CHECK;
4781 data = scm_ulong2num (ULONG_MAX);
4782 data = scm_difference (SCM_INUM0, data);
4783 CHECK;
4784 data = scm_ulong2num (ULONG_MAX);
4785 data = scm_sum (SCM_MAKINUM (1), data); data = scm_difference (SCM_INUM0, data);
4786 CHECK;
4787 data = scm_int2num (-10000); data = scm_product (data, data); data = scm_product (data, data);
4788 CHECK;
4789
4790 return SCM_UNSPECIFIED;
4791 }
4792 #undef FUNC_NAME
4793
4794 #endif
4795
4796 void
4797 scm_init_numbers ()
4798 {
4799 abs_most_negative_fixnum = scm_i_long2big (- SCM_MOST_NEGATIVE_FIXNUM);
4800 scm_permanent_object (abs_most_negative_fixnum);
4801
4802 /* It may be possible to tune the performance of some algorithms by using
4803 * the following constants to avoid the creation of bignums. Please, before
4804 * using these values, remember the two rules of program optimization:
4805 * 1st Rule: Don't do it. 2nd Rule (experts only): Don't do it yet. */
4806 scm_c_define ("most-positive-fixnum",
4807 SCM_MAKINUM (SCM_MOST_POSITIVE_FIXNUM));
4808 scm_c_define ("most-negative-fixnum",
4809 SCM_MAKINUM (SCM_MOST_NEGATIVE_FIXNUM));
4810
4811 scm_add_feature ("complex");
4812 scm_add_feature ("inexact");
4813 scm_flo0 = scm_make_real (0.0);
4814 #ifdef DBL_DIG
4815 scm_dblprec = (DBL_DIG > 20) ? 20 : DBL_DIG;
4816 #else
4817 { /* determine floating point precision */
4818 double f = 0.1;
4819 double fsum = 1.0 + f;
4820 while (fsum != 1.0) {
4821 if (++scm_dblprec > 20) {
4822 fsum = 1.0;
4823 } else {
4824 f /= 10.0;
4825 fsum = f + 1.0;
4826 }
4827 }
4828 scm_dblprec = scm_dblprec - 1;
4829 }
4830 #endif /* DBL_DIG */
4831
4832 #ifdef GUILE_DEBUG
4833 check_sanity ();
4834 #endif
4835
4836 #include "libguile/numbers.x"
4837 }
4838
4839 /*
4840 Local Variables:
4841 c-file-style: "gnu"
4842 End:
4843 */