1 /* Copyright (C) 1995,1996,1997,1998, 1999, 2000 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
60 #define DIGITS '0':case '1':case '2':case '3':case '4':\
61 case '5':case '6':case '7':case '8':case '9'
64 /* IS_INF tests its floating point number for infiniteness
67 #define IS_INF(x) ((x) == (x) / 2)
70 /* Return true if X is not infinite and is not a NaN
73 #define isfinite(x) (!IS_INF (x) && (x) == (x))
79 SCM_DEFINE (scm_exact_p
, "exact?", 1, 0, 0,
82 #define FUNC_NAME s_scm_exact_p
94 SCM_DEFINE (scm_odd_p
, "odd?", 1, 0, 0,
97 #define FUNC_NAME s_scm_odd_p
102 SCM_VALIDATE_BIGINT (1,n
);
103 return SCM_BOOL(1 & SCM_BDIGITS (n
)[0]);
106 SCM_VALIDATE_INUM (1,n
);
108 return SCM_BOOL(4 & (int) n
);
112 SCM_DEFINE (scm_even_p
, "even?", 1, 0, 0,
115 #define FUNC_NAME s_scm_even_p
120 SCM_VALIDATE_BIGINT (1,n
);
121 return SCM_NEGATE_BOOL(1 & SCM_BDIGITS (n
)[0]);
124 SCM_VALIDATE_INUM (1,n
);
126 return SCM_NEGATE_BOOL(4 & (int) n
);
130 SCM_GPROC (s_abs
, "abs", 1, 0, 0, scm_abs
, g_abs
);
139 SCM_GASSERT1 (SCM_BIGP (x
), g_abs
, x
, SCM_ARG1
, s_abs
);
140 if (!SCM_BIGSIGN (x
))
142 return scm_copybig (x
, 0);
145 SCM_GASSERT1 (SCM_INUMP (x
), g_abs
, x
, SCM_ARG1
, s_abs
);
147 if (SCM_INUM (x
) >= 0)
150 if (!SCM_POSFIXABLE (cx
))
152 return scm_long2big (cx
);
154 scm_num_overflow (s_abs
);
156 return SCM_MAKINUM (cx
);
159 SCM_GPROC (s_quotient
, "quotient", 2, 0, 0, scm_quotient
, g_quotient
);
162 scm_quotient (SCM x
, SCM y
)
168 SCM_GASSERT2 (SCM_BIGP (x
),
169 g_quotient
, x
, y
, SCM_ARG1
, s_quotient
);
172 SCM_ASRTGO (SCM_BIGP (y
), bady
);
173 return scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
174 SCM_BDIGITS (y
), SCM_NUMDIGS (y
),
175 SCM_BIGSIGN (x
) ^ SCM_BIGSIGN (y
), 2);
185 SCM sw
= scm_copybig (x
,
187 ? (SCM_UNPACK (y
) > 0)
188 : (SCM_UNPACK (y
) < 0));
189 scm_divbigdig (SCM_BDIGITS (sw
), SCM_NUMDIGS (sw
), (SCM_BIGDIG
) z
);
190 return scm_normbig (sw
);
193 #ifndef SCM_DIGSTOOBIG
194 long w
= scm_pseudolong (z
);
195 return scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
196 (SCM_BIGDIG
*) & w
, SCM_DIGSPERLONG
,
197 SCM_BIGSIGN (x
) ? (y
> 0) : (y
< 0), 2);
199 SCM_BIGDIG zdigs
[SCM_DIGSPERLONG
];
200 scm_longdigs (z
, zdigs
);
201 return scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
202 zdigs
, SCM_DIGSPERLONG
,
203 SCM_BIGSIGN (x
) ? (y
> 0) : (y
< 0), 2);
212 SCM_WTA_DISPATCH_2 (g_quotient
, x
, y
, SCM_ARG2
, s_quotient
);
217 SCM_GASSERT2 (SCM_INUMP (x
), g_quotient
, x
, y
, SCM_ARG1
, s_quotient
);
218 SCM_GASSERT2 (SCM_INUMP (y
), g_quotient
, x
, y
, SCM_ARG2
, s_quotient
);
220 if ((z
= SCM_INUM (y
)) == 0)
223 scm_num_overflow (s_quotient
);
225 z
= SCM_INUM (x
) / z
;
228 #if (__TURBOC__ == 1)
229 long t
= ((y
< 0) ? -SCM_INUM (x
) : SCM_INUM (x
)) % SCM_INUM (y
);
231 long t
= SCM_INUM (x
) % SCM_INUM (y
);
242 if (!SCM_FIXABLE (z
))
244 return scm_long2big (z
);
246 scm_num_overflow (s_quotient
);
248 return SCM_MAKINUM (z
);
251 SCM_GPROC (s_remainder
, "remainder", 2, 0, 0, scm_remainder
, g_remainder
);
254 scm_remainder (SCM x
, SCM y
)
260 SCM_GASSERT2 (SCM_BIGP (x
),
261 g_remainder
, x
, y
, SCM_ARG1
, s_remainder
);
264 SCM_ASRTGO (SCM_BIGP (y
), bady
);
265 return scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
266 SCM_BDIGITS (y
), SCM_NUMDIGS (y
),
269 if (!(z
= SCM_INUM (y
)))
271 return scm_divbigint (x
, z
, SCM_BIGSIGN (x
), 0);
278 SCM_WTA_DISPATCH_2 (g_remainder
, x
, y
, SCM_ARG2
, s_remainder
);
283 SCM_GASSERT2 (SCM_INUMP (x
), g_remainder
, x
, y
, SCM_ARG1
, s_remainder
);
284 SCM_GASSERT2 (SCM_INUMP (y
), g_remainder
, x
, y
, SCM_ARG2
, s_remainder
);
286 if (!(z
= SCM_INUM (y
)))
289 scm_num_overflow (s_remainder
);
291 #if (__TURBOC__ == 1)
295 z
= SCM_INUM (x
) % z
;
305 return SCM_MAKINUM (z
);
308 SCM_GPROC (s_modulo
, "modulo", 2, 0, 0, scm_modulo
, g_modulo
);
311 scm_modulo (SCM x
, SCM y
)
317 SCM_GASSERT2 (SCM_BIGP (x
),
318 g_modulo
, x
, y
, SCM_ARG1
, s_modulo
);
321 SCM_ASRTGO (SCM_BIGP (y
), bady
);
322 return scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
323 SCM_BDIGITS (y
), SCM_NUMDIGS (y
),
325 (SCM_BIGSIGN (x
) ^ SCM_BIGSIGN (y
)) ? 1 : 0);
327 if (!(z
= SCM_INUM (y
)))
329 return scm_divbigint (x
, z
, y
< 0,
330 (SCM_BIGSIGN (x
) ? (y
> 0) : (y
< 0)) ? 1 : 0);
337 SCM_WTA_DISPATCH_2 (g_modulo
, x
, y
, SCM_ARG2
, s_modulo
);
339 return (SCM_BIGSIGN (y
) ? (x
> 0) : (x
< 0)) ? scm_sum (x
, y
) : x
;
342 SCM_GASSERT1 (SCM_INUMP (x
), g_modulo
, x
, y
, SCM_ARG1
, s_modulo
);
343 SCM_GASSERT2 (SCM_INUMP (y
), g_modulo
, x
, y
, SCM_ARG2
, s_modulo
);
345 if (!(yy
= SCM_INUM (y
)))
348 scm_num_overflow (s_modulo
);
352 z
= ((yy
< 0) ? -z
: z
) % yy
;
354 z
= SCM_INUM (x
) % yy
;
356 return SCM_MAKINUM (((yy
< 0) ? (z
> 0) : (z
< 0)) ? z
+ yy
: z
);
359 SCM_GPROC1 (s_gcd
, "gcd", scm_tc7_asubr
, scm_gcd
, g_gcd
);
362 scm_gcd (SCM x
, SCM y
)
366 return SCM_UNBNDP (x
) ? SCM_INUM0
: x
;
372 SCM_GASSERT2 (SCM_BIGP (x
),
373 g_gcd
, x
, y
, SCM_ARG1
, s_gcd
);
375 x
= scm_copybig (x
, 0);
379 SCM_GASSERT2 (SCM_BIGP (y
),
380 g_gcd
, x
, y
, SCM_ARGn
, s_gcd
);
382 y
= scm_copybig (y
, 0);
383 switch (scm_bigcomp (x
, y
))
388 SCM t
= scm_remainder (x
, y
);
396 y
= scm_remainder (y
, x
);
399 /* instead of the switch, we could just
400 return scm_gcd (y, scm_modulo (x, y)); */
414 SCM_GASSERT2 (SCM_INUMP (x
), g_gcd
, x
, y
, SCM_ARG1
, s_gcd
);
415 SCM_GASSERT2 (SCM_INUMP (y
), g_gcd
, x
, y
, SCM_ARGn
, s_gcd
);
430 for (k
= 1; !(1 & ((int) u
| (int) v
)); k
<<= 1, u
>>= 1, v
>>= 1);
449 if (!SCM_POSFIXABLE (u
))
451 return scm_long2big (u
);
453 scm_num_overflow (s_gcd
);
455 return SCM_MAKINUM (u
);
458 SCM_GPROC1 (s_lcm
, "lcm", scm_tc7_asubr
, scm_lcm
, g_lcm
);
461 scm_lcm (SCM n1
, SCM n2
)
465 SCM_GASSERT2 (SCM_INUMP (n1
) || SCM_UNBNDP (n1
),
466 g_lcm
, n1
, n2
, SCM_ARG1
, s_lcm
);
467 SCM_GASSERT2 (SCM_INUMP (n2
) || SCM_UNBNDP (n2
),
468 g_lcm
, n1
, n2
, SCM_ARGn
, s_lcm
);
470 SCM_GASSERT2 (SCM_INUMP (n1
)
473 g_lcm
, n1
, n2
, SCM_ARG1
, s_lcm
);
474 SCM_GASSERT2 (SCM_INUMP (n2
)
477 g_lcm
, n1
, n2
, SCM_ARGn
, s_lcm
);
481 n2
= SCM_MAKINUM (1L);
486 d
= scm_gcd (n1
, n2
);
489 return scm_abs (scm_product (n1
, scm_quotient (n2
, d
)));
493 #define SCM_LOGOP_RETURN(x) scm_ulong2num(x)
495 #define SCM_LOGOP_RETURN(x) SCM_MAKINUM(x)
499 /* Emulating 2's complement bignums with sign magnitude arithmetic:
504 + + + x (map digit:logand X Y)
505 + - + x (map digit:logand X (lognot (+ -1 Y)))
506 - + + y (map digit:logand (lognot (+ -1 X)) Y)
507 - - - (+ 1 (map digit:logior (+ -1 X) (+ -1 Y)))
512 + + + (map digit:logior X Y)
513 + - - y (+ 1 (map digit:logand (lognot X) (+ -1 Y)))
514 - + - x (+ 1 (map digit:logand (+ -1 X) (lognot Y)))
515 - - - x (+ 1 (map digit:logand (+ -1 X) (+ -1 Y)))
520 + + + (map digit:logxor X Y)
521 + - - (+ 1 (map digit:logxor X (+ -1 Y)))
522 - + - (+ 1 (map digit:logxor (+ -1 X) Y))
523 - - + (map digit:logxor (+ -1 X) (+ -1 Y))
528 + + (any digit:logand X Y)
529 + - (any digit:logand X (lognot (+ -1 Y)))
530 - + (any digit:logand (lognot (+ -1 X)) Y)
537 SCM
scm_copy_big_dec(SCM b
, int sign
);
538 SCM
scm_copy_smaller(SCM_BIGDIG
*x
, scm_sizet nx
, int zsgn
);
539 SCM
scm_big_ior(SCM_BIGDIG
*x
, scm_sizet nx
, int xsgn
, SCM bigy
);
540 SCM
scm_big_xor(SCM_BIGDIG
*x
, scm_sizet nx
, int xsgn
, SCM bigy
);
541 SCM
scm_big_and(SCM_BIGDIG
*x
, scm_sizet nx
, int xsgn
, SCM bigy
, int zsgn
);
542 SCM
scm_big_test(SCM_BIGDIG
*x
, scm_sizet nx
, int xsgn
, SCM bigy
);
544 SCM
scm_copy_big_dec(SCM b
, int sign
)
547 scm_sizet nx
= SCM_NUMDIGS(b
);
549 SCM ans
= scm_mkbig(nx
, sign
);
550 SCM_BIGDIG
*src
= SCM_BDIGITS(b
), *dst
= SCM_BDIGITS(ans
);
551 if SCM_BIGSIGN(b
) do {
553 if (num
< 0) {dst
[i
] = num
+ SCM_BIGRAD
; num
= -1;}
554 else {dst
[i
] = SCM_BIGLO(num
); num
= 0;}
557 while (nx
--) dst
[nx
] = src
[nx
];
561 SCM
scm_copy_smaller(SCM_BIGDIG
*x
, scm_sizet nx
, int zsgn
)
565 SCM z
= scm_mkbig(nx
, zsgn
);
566 SCM_BIGDIG
*zds
= SCM_BDIGITS(z
);
569 if (num
< 0) {zds
[i
] = num
+ SCM_BIGRAD
; num
= -1;}
570 else {zds
[i
] = SCM_BIGLO(num
); num
= 0;}
572 else do zds
[i
] = x
[i
]; while (++i
< nx
);
576 SCM
scm_big_ior(SCM_BIGDIG
*x
, scm_sizet nx
, int xsgn
, SCM bigy
)
577 /* Assumes nx <= SCM_NUMDIGS(bigy) */
578 /* Assumes xsgn equals either 0 or SCM_BIGSIGNFLAG */
581 scm_sizet i
= 0, ny
= SCM_NUMDIGS(bigy
);
582 SCM z
= scm_copy_big_dec (bigy
, xsgn
& SCM_BIGSIGN (bigy
));
583 SCM_BIGDIG
*zds
= SCM_BDIGITS(z
);
587 if (num
< 0) {zds
[i
] |= num
+ SCM_BIGRAD
; num
= -1;}
588 else {zds
[i
] |= SCM_BIGLO(num
); num
= 0;}
590 /* ========= Need to increment zds now =========== */
594 zds
[i
++] = SCM_BIGLO(num
);
595 num
= SCM_BIGDN(num
);
598 scm_adjbig(z
, 1 + ny
); /* OOPS, overflowed into next digit. */
599 SCM_BDIGITS(z
)[ny
] = 1;
602 else do zds
[i
] = zds
[i
] | x
[i
]; while (++i
< nx
);
606 SCM
scm_big_xor(SCM_BIGDIG
*x
, scm_sizet nx
, int xsgn
, SCM bigy
)
607 /* Assumes nx <= SCM_NUMDIGS(bigy) */
608 /* Assumes xsgn equals either 0 or SCM_BIGSIGNFLAG */
611 scm_sizet i
= 0, ny
= SCM_NUMDIGS(bigy
);
612 SCM z
= scm_copy_big_dec(bigy
, xsgn
^ SCM_BIGSIGN(bigy
));
613 SCM_BIGDIG
*zds
= SCM_BDIGITS(z
);
616 if (num
< 0) {zds
[i
] ^= num
+ SCM_BIGRAD
; num
= -1;}
617 else {zds
[i
] ^= SCM_BIGLO(num
); num
= 0;}
620 zds
[i
] = zds
[i
] ^ x
[i
];
623 if (xsgn
^ SCM_BIGSIGN(bigy
)) {
624 /* ========= Need to increment zds now =========== */
628 zds
[i
++] = SCM_BIGLO(num
);
629 num
= SCM_BIGDN(num
);
630 if (!num
) return scm_normbig(z
);
633 return scm_normbig(z
);
636 SCM
scm_big_and(SCM_BIGDIG
*x
, scm_sizet nx
, int xsgn
, SCM bigy
, int zsgn
)
637 /* Assumes nx <= SCM_NUMDIGS(bigy) */
638 /* Assumes xsgn equals either 0 or SCM_BIGSIGNFLAG */
639 /* return sign equals either 0 or SCM_BIGSIGNFLAG */
646 z
= scm_copy_smaller(x
, nx
, zsgn
);
647 x
= SCM_BDIGITS(bigy
);
648 xsgn
= SCM_BIGSIGN(bigy
);
650 else z
= scm_copy_big_dec(bigy
, zsgn
);
651 zds
= SCM_BDIGITS(z
);
656 if (num
< 0) {zds
[i
] &= num
+ SCM_BIGRAD
; num
= -1;}
657 else {zds
[i
] &= SCM_BIGLO(num
); num
= 0;}
659 else do zds
[i
] = zds
[i
] & ~x
[i
]; while (++i
< nx
);
660 /* ========= need to increment zds now =========== */
664 zds
[i
++] = SCM_BIGLO(num
);
665 num
= SCM_BIGDN(num
);
666 if (!num
) return scm_normbig(z
);
671 if (num
< 0) {zds
[i
] &= num
+ SCM_BIGRAD
; num
= -1;}
672 else {zds
[i
] &= ~SCM_BIGLO(num
); num
= 0;}
674 else do zds
[i
] = zds
[i
] & x
[i
]; while (++i
< nx
);
675 return scm_normbig(z
);
678 SCM
scm_big_test(SCM_BIGDIG
*x
, scm_sizet nx
, int xsgn
, SCM bigy
)
679 /* Assumes nx <= SCM_NUMDIGS(bigy) */
680 /* Assumes xsgn equals either 0 or SCM_BIGSIGNFLAG */
685 if (SCM_BIGSIGN(bigy
) & xsgn
) return SCM_BOOL_T
;
686 if (SCM_NUMDIGS(bigy
) != nx
&& xsgn
) return SCM_BOOL_T
;
687 y
= SCM_BDIGITS(bigy
);
692 if (y
[i
] & ~(num
+ SCM_BIGRAD
)) return SCM_BOOL_T
;
696 if (y
[i
] & ~SCM_BIGLO(num
)) return SCM_BOOL_T
;
700 else if SCM_BIGSIGN(bigy
)
704 if (x
[i
] & ~(num
+ SCM_BIGRAD
)) return SCM_BOOL_T
;
708 if (x
[i
] & ~SCM_BIGLO(num
)) return SCM_BOOL_T
;
713 do if (x
[i
] & y
[i
]) return SCM_BOOL_T
;
720 SCM_DEFINE1 (scm_logand
, "logand", scm_tc7_asubr
,
722 "Returns the integer which is the bit-wise AND of the two integer\n"
726 "(number->string (logand #b1100 #b1010) 2)\n"
727 " @result{} \"1000\"")
728 #define FUNC_NAME s_scm_logand
733 return SCM_MAKINUM (-1);
735 if (!(SCM_NUMBERP (n1
)))
736 badx
: SCM_WTA (SCM_ARG1
, n1
);
743 SCM_ASRTGO(SCM_NIMP(n1
) && SCM_BIGP(n1
), badx
);
744 if SCM_INUMP(n2
) {t
= n1
; n1
= n2
; n2
= t
; goto intbig
;}
745 SCM_ASRTGO(SCM_NIMP(n2
) && SCM_BIGP(n2
), bady
);
746 if (SCM_NUMDIGS(n1
) > SCM_NUMDIGS(n2
)) {t
= n1
; n1
= n2
; n2
= t
;}
747 if ((SCM_BIGSIGN(n1
)) && SCM_BIGSIGN(n2
))
748 return scm_big_ior (SCM_BDIGITS(n1
),
752 return scm_big_and (SCM_BDIGITS(n1
),
759 # ifndef SCM_RECKLESS
760 if (!(SCM_NIMP(n2
) && SCM_BIGP(n2
)))
761 bady
: SCM_WTA (SCM_ARG2
, n2
);
764 # ifndef SCM_DIGSTOOBIG
765 long z
= scm_pseudolong(SCM_INUM(n1
));
766 if ((n1
< 0) && SCM_BIGSIGN(n2
))
767 return scm_big_ior((SCM_BIGDIG
*)&z
, SCM_DIGSPERLONG
, SCM_BIGSIGNFLAG
, n2
);
768 return scm_big_and((SCM_BIGDIG
*)&z
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
, 0);
770 SCM_BIGDIG zdigs
[SCM_DIGSPERLONG
];
771 scm_longdigs(SCM_INUM(n1
), zdigs
);
772 if ((n1
< 0) && SCM_BIGSIGN(n2
))
773 return scm_big_ior(zdigs
, SCM_DIGSPERLONG
, SCM_BIGSIGNFLAG
, n2
);
774 return scm_big_and(zdigs
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
, 0);
778 SCM_ASRTGO(SCM_INUMP(n1
), badx
);
779 SCM_ASSERT(SCM_INUMP(n2
), n2
, SCM_ARG2
, FUNC_NAME
);
781 return SCM_MAKINUM(SCM_INUM(n1
) & SCM_INUM(n2
));
785 SCM_DEFINE1 (scm_logior
, "logior", scm_tc7_asubr
,
787 "Returns the integer which is the bit-wise OR of the two integer\n"
791 "(number->string (logior #b1100 #b1010) 2)\n"
792 " @result{} \"1110\"\n"
794 #define FUNC_NAME s_scm_logior
801 if (!(SCM_NUMBERP(n1
)))
802 badx
: SCM_WTA(SCM_ARG1
, n1
);
809 SCM_ASRTGO(SCM_NIMP(n1
) && SCM_BIGP(n1
), badx
);
810 if SCM_INUMP(n2
) {t
= n1
; n1
= n2
; n2
= t
; goto intbig
;}
811 SCM_ASRTGO(SCM_NIMP(n2
) && SCM_BIGP(n2
), bady
);
812 if (SCM_NUMDIGS(n1
) > SCM_NUMDIGS(n2
)) {t
= n1
; n1
= n2
; n2
= t
;}
813 if ((!SCM_BIGSIGN(n1
)) && !SCM_BIGSIGN(n2
))
814 return scm_big_ior(SCM_BDIGITS(n1
), SCM_NUMDIGS(n1
), SCM_BIGSIGN(n1
), n2
);
815 return scm_big_and(SCM_BDIGITS(n1
), SCM_NUMDIGS(n1
), SCM_BIGSIGN(n1
), n2
, SCM_BIGSIGNFLAG
);
818 # ifndef SCM_RECKLESS
819 if (!(SCM_NIMP(n2
) && SCM_BIGP(n2
)))
820 bady
: SCM_WTA(SCM_ARG2
, n2
);
823 # ifndef SCM_DIGSTOOBIG
824 long z
= scm_pseudolong(SCM_INUM(n1
));
825 if ((!(n1
< 0)) && !SCM_BIGSIGN(n2
))
826 return scm_big_ior((SCM_BIGDIG
*)&z
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
);
827 return scm_big_and((SCM_BIGDIG
*)&z
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
, SCM_BIGSIGNFLAG
);
829 BIGDIG zdigs
[DIGSPERLONG
];
830 scm_longdigs(SCM_INUM(n1
), zdigs
);
831 if ((!(n1
< 0)) && !SCM_BIGSIGN(n2
))
832 return scm_big_ior(zdigs
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
);
833 return scm_big_and(zdigs
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
, SCM_BIGSIGNFLAG
);
837 SCM_ASRTGO(SCM_INUMP(n1
), badx
);
838 SCM_ASSERT(SCM_INUMP(n2
), n2
, SCM_ARG2
, FUNC_NAME
);
840 return SCM_MAKINUM(SCM_INUM(n1
) | SCM_INUM(n2
));
844 SCM_DEFINE1 (scm_logxor
, "logxor", scm_tc7_asubr
,
846 "Returns the integer which is the bit-wise XOR of the two integer\n"
850 "(number->string (logxor #b1100 #b1010) 2)\n"
851 " @result{} \"110\"\n"
853 #define FUNC_NAME s_scm_logxor
860 if (!(SCM_NUMBERP(n1
)))
861 badx
: SCM_WTA(SCM_ARG1
, n1
);
868 SCM_ASRTGO(SCM_NIMP(n1
) && SCM_BIGP(n1
), badx
);
876 SCM_ASRTGO(SCM_NIMP(n2
) && SCM_BIGP(n2
), bady
);
877 if (SCM_NUMDIGS(n1
) > SCM_NUMDIGS(n2
))
883 return scm_big_xor(SCM_BDIGITS(n1
), SCM_NUMDIGS(n1
), SCM_BIGSIGN(n1
), n2
);
886 # ifndef SCM_RECKLESS
887 if (!(SCM_NIMP(n2
) && SCM_BIGP(n2
)))
888 bady
: SCM_WTA (SCM_ARG2
, n2
);
892 # ifndef SCM_DIGSTOOBIG
893 long z
= scm_pseudolong(SCM_INUM(n1
));
894 return scm_big_xor((SCM_BIGDIG
*)&z
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
);
896 SCM_BIGDIG zdigs
[SCM_DIGSPERLONG
];
897 scm_longdigs(SCM_INUM(n1
), zdigs
);
898 return scm_big_xor(zdigs
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
);
903 SCM_ASRTGO(INUMP(n1
), badx
);
904 SCM_ASSERT(INUMP(n2
), n2
, SCM_ARG2
, FUNC_NAME
);
906 return SCM_MAKINUM(SCM_INUM(n1
) ^ SCM_INUM(n2
));
910 SCM_DEFINE (scm_logtest
, "logtest", 2, 0, 0,
913 "(logtest j k) @equiv{} (not (zero? (logand j k)))\n\n"
914 "(logtest #b0100 #b1011) @result{} #f\n"
915 "(logtest #b0100 #b0111) @result{} #t\n"
917 #define FUNC_NAME s_scm_logtest
920 if (!(SCM_NUMBERP(n1
)))
921 badx
: SCM_WTA(SCM_ARG1
, n1
);
926 SCM_ASRTGO(SCM_NIMP(n1
) && SCM_BIGP(n1
), badx
);
927 if SCM_INUMP(n2
) {t
= n1
; n1
= n2
; n2
= t
; goto intbig
;}
928 SCM_ASRTGO(SCM_NIMP(n2
) && SCM_BIGP(n2
), bady
);
929 if (SCM_NUMDIGS(n1
) > SCM_NUMDIGS(n2
)) {t
= n1
; n1
= n2
; n2
= t
;}
930 return scm_big_test(SCM_BDIGITS(n1
), SCM_NUMDIGS(n1
), SCM_BIGSIGN(n1
), n2
);
933 # ifndef SCM_RECKLESS
934 if (!(SCM_NIMP(n2
) && SCM_BIGP(n2
)))
935 bady
: SCM_WTA(SCM_ARG2
, n2
);
938 # ifndef SCM_DIGSTOOBIG
939 long z
= scm_pseudolong(SCM_INUM(n1
));
940 return scm_big_test((SCM_BIGDIG
*)&z
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
);
942 SCM_BIGDIG zdigs
[SCM_DIGSPERLONG
];
943 scm_longdigs(SCM_INUM(n1
), zdigs
);
944 return scm_big_test(zdigs
, SCM_DIGSPERLONG
, (n1
< 0) ? SCM_BIGSIGNFLAG
: 0, n2
);
948 SCM_ASRTGO(SCM_INUMP(n1
), badx
);
949 SCM_ASSERT(SCM_INUMP(n2
), n2
, SCM_ARG2
, FUNC_NAME
);
951 return (SCM_INUM(n1
) & SCM_INUM(n2
)) ? SCM_BOOL_T
: SCM_BOOL_F
;
956 SCM_DEFINE (scm_logbit_p
, "logbit?", 2, 0, 0,
959 "(logbit? index j) @equiv{} (logtest (integer-expt 2 index) j)\n\n"
960 "(logbit? 0 #b1101) @result{} #t\n"
961 "(logbit? 1 #b1101) @result{} #f\n"
962 "(logbit? 2 #b1101) @result{} #t\n"
963 "(logbit? 3 #b1101) @result{} #t\n"
964 "(logbit? 4 #b1101) @result{} #f\n"
966 #define FUNC_NAME s_scm_logbit_p
968 SCM_ASSERT(SCM_INUMP(index
) && SCM_INUM(index
) >= 0, index
, SCM_ARG1
, FUNC_NAME
);
971 SCM_ASSERT(SCM_NIMP(j
) && SCM_BIGP(j
), j
, SCM_ARG2
, FUNC_NAME
);
972 if (SCM_NUMDIGS(j
) * SCM_BITSPERDIG
< SCM_INUM(index
)) return SCM_BOOL_F
;
973 else if SCM_BIGSIGN(j
) {
976 SCM_BIGDIG
*x
= SCM_BDIGITS(j
);
977 scm_sizet nx
= SCM_INUM(index
)/SCM_BITSPERDIG
;
981 return ((1L << (SCM_INUM(index
)%SCM_BITSPERDIG
)) & num
) ? SCM_BOOL_F
: SCM_BOOL_T
;
982 if (num
< 0) num
= -1;
986 else return (SCM_BDIGITS(j
)[SCM_INUM(index
)/SCM_BITSPERDIG
] &
987 (1L << (SCM_INUM(index
)%SCM_BITSPERDIG
))) ? SCM_BOOL_T
: SCM_BOOL_F
;
990 SCM_ASSERT(SCM_INUMP(j
), j
, SCM_ARG2
, FUNC_NAME
);
992 return ((1L << SCM_INUM(index
)) & SCM_INUM(j
)) ? SCM_BOOL_T
: SCM_BOOL_F
;
996 SCM_DEFINE (scm_lognot
, "lognot", 1, 0, 0,
998 "Returns the integer which is the 2s-complement of the integer argument.\n\n"
1001 "(number->string (lognot #b10000000) 2)\n"
1002 " @result{} \"-10000001\"\n"
1003 "(number->string (lognot #b0) 2)\n"
1004 " @result{} \"-1\"\n"
1007 #define FUNC_NAME s_scm_lognot
1009 return scm_difference (SCM_MAKINUM (-1L), n
);
1013 SCM_DEFINE (scm_integer_expt
, "integer-expt", 2, 0, 0,
1015 "Returns @var{n} raised to the non-negative integer exponent @var{k}.\n\n"
1018 "(integer-expt 2 5)\n"
1020 "(integer-expt -3 3)\n"
1023 #define FUNC_NAME s_scm_integer_expt
1025 SCM acc
= SCM_MAKINUM (1L);
1028 if (SCM_INUM0
== n
|| acc
== n
)
1030 else if (SCM_MAKINUM (-1L) == n
)
1031 return SCM_BOOL_F
== scm_even_p (k
) ? n
: acc
;
1033 SCM_VALIDATE_ULONG_COPY (2,k
,i2
);
1037 n
= scm_divide (n
, SCM_UNDEFINED
);
1044 return scm_product (acc
, n
);
1046 acc
= scm_product (acc
, n
);
1047 n
= scm_product (n
, n
);
1053 SCM_DEFINE (scm_ash
, "ash", 2, 0, 0,
1055 "Returns an integer equivalent to\n"
1056 "@code{(inexact->exact (floor (* @var{int} (expt 2 @var{count}))))}.@refill\n\n"
1059 "(number->string (ash #b1 3) 2)\n"
1060 " @result{} \"1000\""
1061 "(number->string (ash #b1010 -1) 2)"
1062 " @result{} \"101\""
1064 #define FUNC_NAME s_scm_ash
1066 /* GJB:FIXME:: what is going on here? */
1067 SCM res
= SCM_PACK (SCM_INUM (n
));
1068 SCM_VALIDATE_INUM (2,cnt
);
1072 res
= scm_integer_expt (SCM_MAKINUM (2), SCM_MAKINUM (-SCM_INUM (cnt
)));
1073 if (SCM_NFALSEP (scm_negative_p (n
)))
1074 return scm_sum (SCM_MAKINUM (-1L),
1075 scm_quotient (scm_sum (SCM_MAKINUM (1L), n
), res
));
1077 return scm_quotient (n
, res
);
1080 return scm_product (n
, scm_integer_expt (SCM_MAKINUM (2), cnt
));
1082 SCM_VALIDATE_INUM (1,n
)
1083 cnt
= SCM_INUM (cnt
);
1085 return SCM_MAKINUM (SCM_SRS (res
, -cnt
));
1086 res
= SCM_MAKINUM (res
<< cnt
);
1087 if (SCM_INUM (res
) >> cnt
!= SCM_INUM (n
))
1088 scm_num_overflow (FUNC_NAME
);
1094 /* GJB:FIXME: do not use SCMs as integers! */
1095 SCM_DEFINE (scm_bit_extract
, "bit-extract", 3, 0, 0,
1096 (SCM n
, SCM start
, SCM end
),
1097 "Returns the integer composed of the @var{start} (inclusive) through\n"
1098 "@var{end} (exclusive) bits of @var{n}. The @var{start}th bit becomes\n"
1099 "the 0-th bit in the result.@refill\n\n"
1102 "(number->string (bit-extract #b1101101010 0 4) 2)\n"
1103 " @result{} \"1010\"\n"
1104 "(number->string (bit-extract #b1101101010 4 9) 2)\n"
1105 " @result{} \"10110\"\n"
1107 #define FUNC_NAME s_scm_bit_extract
1110 SCM_VALIDATE_INUM (1,n
);
1111 SCM_VALIDATE_INUM_MIN_COPY (2,start
,0,istart
);
1112 SCM_VALIDATE_INUM_MIN_COPY (3, end
, 0, iend
);
1113 SCM_ASSERT_RANGE (3, end
, (iend
>= istart
));
1117 scm_logand (scm_difference (scm_integer_expt (SCM_MAKINUM (2),
1118 SCM_MAKINUM (iend
- istart
)),
1120 scm_ash (n
, SCM_MAKINUM (-istart
)));
1122 SCM_VALIDATE_INUM (1,n
);
1124 return SCM_MAKINUM ((SCM_INUM (n
) >> istart
) & ((1L << (iend
- istart
)) - 1));
1128 static const char scm_logtab
[] = {
1129 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
1132 SCM_DEFINE (scm_logcount
, "logcount", 1, 0, 0,
1134 "Returns the number of bits in integer @var{n}. If integer is positive,\n"
1135 "the 1-bits in its binary representation are counted. If negative, the\n"
1136 "0-bits in its two's-complement binary representation are counted. If 0,\n"
1137 "0 is returned.\n\n"
1140 "(logcount #b10101010)\n"
1147 #define FUNC_NAME s_scm_logcount
1149 register unsigned long c
= 0;
1156 SCM_VALIDATE_BIGINT (1,n
);
1157 if (SCM_BIGSIGN (n
))
1158 return scm_logcount (scm_difference (SCM_MAKINUM (-1L), n
));
1159 ds
= SCM_BDIGITS (n
);
1160 for (i
= SCM_NUMDIGS (n
); i
--;)
1161 for (d
= ds
[i
]; d
; d
>>= 4)
1162 c
+= scm_logtab
[15 & d
];
1163 return SCM_MAKINUM (c
);
1166 SCM_VALIDATE_INUM (1,n
);
1168 if ((nn
= SCM_INUM (n
)) < 0)
1170 for (; nn
; nn
>>= 4)
1171 c
+= scm_logtab
[15 & nn
];
1172 return SCM_MAKINUM (c
);
1177 static const char scm_ilentab
[] = {
1178 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
1181 SCM_DEFINE (scm_integer_length
, "integer-length", 1, 0, 0,
1183 "Returns the number of bits neccessary to represent @var{n}.\n\n"
1186 "(integer-length #b10101010)\n"
1188 "(integer-length 0)\n"
1190 "(integer-length #b1111)\n"
1193 #define FUNC_NAME s_scm_integer_length
1195 register unsigned long c
= 0;
1202 SCM_VALIDATE_BIGINT (1,n
);
1203 if (SCM_BIGSIGN (n
))
1204 return scm_integer_length (scm_difference (SCM_MAKINUM (-1L), n
));
1205 ds
= SCM_BDIGITS (n
);
1206 d
= ds
[c
= SCM_NUMDIGS (n
) - 1];
1207 for (c
*= SCM_BITSPERDIG
; d
; d
>>= 4)
1210 l
= scm_ilentab
[15 & d
];
1212 return SCM_MAKINUM (c
- 4 + l
);
1215 SCM_VALIDATE_INUM (1,n
);
1217 if ((nn
= SCM_INUM (n
)) < 0)
1219 for (; nn
; nn
>>= 4)
1222 l
= scm_ilentab
[15 & nn
];
1224 return SCM_MAKINUM (c
- 4 + l
);
1230 static const char s_bignum
[] = "bignum";
1233 scm_mkbig (scm_sizet nlen
, int sign
)
1236 /* Cast to long int to avoid signed/unsigned comparison warnings. */
1237 if ((( ((long int) nlen
) << SCM_BIGSIZEFIELD
) >> SCM_BIGSIZEFIELD
)
1239 scm_wta (SCM_MAKINUM (nlen
), (char *) SCM_NALLOC
, s_bignum
);
1243 SCM_SETCHARS (v
, scm_must_malloc ((long) (nlen
* sizeof (SCM_BIGDIG
)),
1245 SCM_SETNUMDIGS (v
, nlen
, sign
);
1252 scm_big2inum (SCM b
, scm_sizet l
)
1254 unsigned long num
= 0;
1255 SCM_BIGDIG
*tmp
= SCM_BDIGITS (b
);
1257 num
= SCM_BIGUP (num
) + tmp
[l
];
1258 if (!SCM_BIGSIGN (b
))
1260 if (SCM_POSFIXABLE (num
))
1261 return SCM_MAKINUM (num
);
1263 else if (SCM_UNEGFIXABLE (num
))
1264 return SCM_MAKINUM (-num
);
1269 static const char s_adjbig
[] = "scm_adjbig";
1272 scm_adjbig (SCM b
, scm_sizet nlen
)
1274 scm_sizet nsiz
= nlen
;
1275 if (((nsiz
<< SCM_BIGSIZEFIELD
) >> SCM_BIGSIZEFIELD
) != nlen
)
1276 scm_wta (scm_ulong2num (nsiz
), (char *) SCM_NALLOC
, s_adjbig
);
1282 scm_must_realloc ((char *) SCM_CHARS (b
),
1283 (long) (SCM_NUMDIGS (b
) * sizeof (SCM_BIGDIG
)),
1284 (long) (nsiz
* sizeof (SCM_BIGDIG
)), s_adjbig
));
1286 SCM_SETCHARS (b
, digits
);
1287 SCM_SETNUMDIGS (b
, nsiz
, SCM_BIGSIGN (b
));
1299 scm_sizet nlen
= SCM_NUMDIGS (b
);
1301 int nlen
= SCM_NUMDIGS (b
); /* unsigned nlen breaks on Cray when nlen => 0 */
1303 SCM_BIGDIG
*zds
= SCM_BDIGITS (b
);
1304 while (nlen
-- && !zds
[nlen
]);
1306 if (nlen
* SCM_BITSPERDIG
/ SCM_CHAR_BIT
<= sizeof (SCM
))
1307 if (SCM_INUMP (b
= scm_big2inum (b
, (scm_sizet
) nlen
)))
1309 if (SCM_NUMDIGS (b
) == nlen
)
1311 return scm_adjbig (b
, (scm_sizet
) nlen
);
1317 scm_copybig (SCM b
, int sign
)
1319 scm_sizet i
= SCM_NUMDIGS (b
);
1320 SCM ans
= scm_mkbig (i
, sign
);
1321 SCM_BIGDIG
*src
= SCM_BDIGITS (b
), *dst
= SCM_BDIGITS (ans
);
1330 scm_long2big (long n
)
1334 SCM ans
= scm_mkbig (SCM_DIGSPERLONG
, n
< 0);
1335 digits
= SCM_BDIGITS (ans
);
1338 while (i
< SCM_DIGSPERLONG
)
1340 digits
[i
++] = SCM_BIGLO (n
);
1341 n
= SCM_BIGDN ((unsigned long) n
);
1346 #ifdef HAVE_LONG_LONGS
1349 scm_long_long2big (long_long n
)
1359 if ((long long) tn
== n
)
1360 return scm_long2big (tn
);
1366 for (tn
= n
, n_digits
= 0;
1368 ++n_digits
, tn
= SCM_BIGDN ((ulong_long
) tn
))
1373 ans
= scm_mkbig (n_digits
, n
< 0);
1374 digits
= SCM_BDIGITS (ans
);
1377 while (i
< n_digits
)
1379 digits
[i
++] = SCM_BIGLO (n
);
1380 n
= SCM_BIGDN ((ulong_long
) n
);
1388 scm_2ulong2big (unsigned long *np
)
1395 ans
= scm_mkbig (2 * SCM_DIGSPERLONG
, 0);
1396 digits
= SCM_BDIGITS (ans
);
1399 for (i
= 0; i
< SCM_DIGSPERLONG
; ++i
)
1401 digits
[i
] = SCM_BIGLO (n
);
1402 n
= SCM_BIGDN ((unsigned long) n
);
1405 for (i
= 0; i
< SCM_DIGSPERLONG
; ++i
)
1407 digits
[i
+ SCM_DIGSPERLONG
] = SCM_BIGLO (n
);
1408 n
= SCM_BIGDN ((unsigned long) n
);
1416 scm_ulong2big (unsigned long n
)
1420 SCM ans
= scm_mkbig (SCM_DIGSPERLONG
, 0);
1421 digits
= SCM_BDIGITS (ans
);
1422 while (i
< SCM_DIGSPERLONG
)
1424 digits
[i
++] = SCM_BIGLO (n
);
1433 scm_bigcomp (SCM x
, SCM y
)
1435 int xsign
= SCM_BIGSIGN (x
);
1436 int ysign
= SCM_BIGSIGN (y
);
1437 scm_sizet xlen
, ylen
;
1439 /* Look at the signs, first. */
1445 /* They're the same sign, so see which one has more digits. Note
1446 that, if they are negative, the longer number is the lesser. */
1447 ylen
= SCM_NUMDIGS (y
);
1448 xlen
= SCM_NUMDIGS (x
);
1450 return (xsign
) ? -1 : 1;
1452 return (xsign
) ? 1 : -1;
1454 /* They have the same number of digits, so find the most significant
1455 digit where they differ. */
1459 if (SCM_BDIGITS (y
)[xlen
] != SCM_BDIGITS (x
)[xlen
])
1460 /* Make the discrimination based on the digit that differs. */
1461 return ((SCM_BDIGITS (y
)[xlen
] > SCM_BDIGITS (x
)[xlen
])
1463 : (xsign
? 1 : -1));
1466 /* The numbers are identical. */
1470 #ifndef SCM_DIGSTOOBIG
1474 scm_pseudolong (long x
)
1479 SCM_BIGDIG bd
[SCM_DIGSPERLONG
];
1485 while (i
< SCM_DIGSPERLONG
)
1487 p
.bd
[i
++] = SCM_BIGLO (x
);
1490 /* p.bd[0] = SCM_BIGLO(x); p.bd[1] = SCM_BIGDN(x); */
1498 scm_longdigs (long x
, SCM_BIGDIG digs
[])
1503 while (i
< SCM_DIGSPERLONG
)
1505 digs
[i
++] = SCM_BIGLO (x
);
1514 scm_addbig (SCM_BIGDIG
*x
, scm_sizet nx
, int xsgn
, SCM bigy
, int sgny
)
1516 /* Assumes nx <= SCM_NUMDIGS(bigy) */
1517 /* Assumes xsgn and sgny scm_equal either 0 or SCM_BIGSIGNFLAG */
1519 scm_sizet i
= 0, ny
= SCM_NUMDIGS (bigy
);
1520 SCM z
= scm_copybig (bigy
, SCM_BIGSIGN (bigy
) ^ sgny
);
1521 SCM_BIGDIG
*zds
= SCM_BDIGITS (z
);
1522 if (xsgn
^ SCM_BIGSIGN (z
))
1526 num
+= (long) zds
[i
] - x
[i
];
1529 zds
[i
] = num
+ SCM_BIGRAD
;
1534 zds
[i
] = SCM_BIGLO (num
);
1539 if (num
&& nx
== ny
)
1543 SCM_SETCAR (z
, SCM_UNPACK_CAR (z
) ^ SCM_BIGSIGNFLAG
);
1546 num
+= (SCM_BIGRAD
- 1) - zds
[i
];
1547 zds
[i
++] = SCM_BIGLO (num
);
1548 num
= SCM_BIGDN (num
);
1558 zds
[i
++] = num
+ SCM_BIGRAD
;
1563 zds
[i
++] = SCM_BIGLO (num
);
1572 num
+= (long) zds
[i
] + x
[i
];
1573 zds
[i
++] = SCM_BIGLO (num
);
1574 num
= SCM_BIGDN (num
);
1582 zds
[i
++] = SCM_BIGLO (num
);
1583 num
= SCM_BIGDN (num
);
1589 z
= scm_adjbig (z
, ny
+ 1);
1590 SCM_BDIGITS (z
)[ny
] = num
;
1594 return scm_normbig (z
);
1599 scm_mulbig (SCM_BIGDIG
*x
, scm_sizet nx
, SCM_BIGDIG
*y
, scm_sizet ny
, int sgn
)
1601 scm_sizet i
= 0, j
= nx
+ ny
;
1602 unsigned long n
= 0;
1603 SCM z
= scm_mkbig (j
, sgn
);
1604 SCM_BIGDIG
*zds
= SCM_BDIGITS (z
);
1614 n
+= zds
[i
+ j
] + ((unsigned long) x
[i
] * y
[j
]);
1615 zds
[i
+ j
++] = SCM_BIGLO (n
);
1627 return scm_normbig (z
);
1631 /* Sun's compiler complains about the fact that this function has an
1632 ANSI prototype in numbers.h, but a K&R declaration here, and the
1633 two specify different promotions for the third argument. I'm going
1634 to turn this into an ANSI declaration, and see if anyone complains
1635 about it not being K&R. */
1638 scm_divbigdig (SCM_BIGDIG
* ds
,
1642 register unsigned long t2
= 0;
1645 t2
= SCM_BIGUP (t2
) + ds
[h
];
1655 scm_divbigint (SCM x
, long z
, int sgn
, int mode
)
1661 register unsigned long t2
= 0;
1662 register SCM_BIGDIG
*ds
= SCM_BDIGITS (x
);
1663 scm_sizet nd
= SCM_NUMDIGS (x
);
1665 t2
= (SCM_BIGUP (t2
) + ds
[nd
]) % z
;
1668 return SCM_MAKINUM (sgn
? -t2
: t2
);
1671 #ifndef SCM_DIGSTOOBIG
1672 unsigned long t2
= scm_pseudolong (z
);
1673 return scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
1674 (SCM_BIGDIG
*) & t2
, SCM_DIGSPERLONG
,
1677 SCM_BIGDIG t2
[SCM_DIGSPERLONG
];
1678 scm_longdigs (z
, t2
);
1679 return scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
1680 t2
, SCM_DIGSPERLONG
,
1688 scm_divbigbig (SCM_BIGDIG
*x
, scm_sizet nx
, SCM_BIGDIG
*y
, scm_sizet ny
, int sgn
, int modes
)
1690 /* modes description
1694 3 quotient but returns 0 if division is not exact. */
1695 scm_sizet i
= 0, j
= 0;
1697 unsigned long t2
= 0;
1699 SCM_BIGDIG d
= 0, qhat
, *zds
, *yds
;
1700 /* algorithm requires nx >= ny */
1704 case 0: /* remainder -- just return x */
1705 z
= scm_mkbig (nx
, sgn
);
1706 zds
= SCM_BDIGITS (z
);
1713 case 1: /* scm_modulo -- return y-x */
1714 z
= scm_mkbig (ny
, sgn
);
1715 zds
= SCM_BDIGITS (z
);
1718 num
+= (long) y
[i
] - x
[i
];
1721 zds
[i
] = num
+ SCM_BIGRAD
;
1736 zds
[i
++] = num
+ SCM_BIGRAD
;
1747 return SCM_INUM0
; /* quotient is zero */
1749 return 0; /* the division is not exact */
1752 z
= scm_mkbig (nx
== ny
? nx
+ 2 : nx
+ 1, sgn
);
1753 zds
= SCM_BDIGITS (z
);
1757 ny
--; /* in case y came in as a psuedolong */
1758 if (y
[ny
- 1] < (SCM_BIGRAD
>> 1))
1759 { /* normalize operands */
1760 d
= SCM_BIGRAD
/ (y
[ny
- 1] + 1);
1761 newy
= scm_mkbig (ny
, 0);
1762 yds
= SCM_BDIGITS (newy
);
1765 t2
+= (unsigned long) y
[j
] * d
;
1766 yds
[j
++] = SCM_BIGLO (t2
);
1767 t2
= SCM_BIGDN (t2
);
1774 t2
+= (unsigned long) x
[j
] * d
;
1775 zds
[j
++] = SCM_BIGLO (t2
);
1776 t2
= SCM_BIGDN (t2
);
1786 j
= nx
== ny
? nx
+ 1 : nx
; /* dividend needs more digits than divisor */
1788 { /* loop over digits of quotient */
1789 if (zds
[j
] == y
[ny
- 1])
1790 qhat
= SCM_BIGRAD
- 1;
1792 qhat
= (SCM_BIGUP (zds
[j
]) + zds
[j
- 1]) / y
[ny
- 1];
1799 { /* multiply and subtract */
1800 t2
+= (unsigned long) y
[i
] * qhat
;
1801 num
+= zds
[j
- ny
+ i
] - SCM_BIGLO (t2
);
1804 zds
[j
- ny
+ i
] = num
+ SCM_BIGRAD
;
1809 zds
[j
- ny
+ i
] = num
;
1812 t2
= SCM_BIGDN (t2
);
1815 num
+= zds
[j
- ny
+ i
] - t2
; /* borrow from high digit; don't update */
1817 { /* "add back" required */
1823 num
+= (long) zds
[j
- ny
+ i
] + y
[i
];
1824 zds
[j
- ny
+ i
] = SCM_BIGLO (num
);
1825 num
= SCM_BIGDN (num
);
1836 case 3: /* check that remainder==0 */
1837 for (j
= ny
; j
&& !zds
[j
- 1]; --j
);
1840 case 2: /* move quotient down in z */
1841 j
= (nx
== ny
? nx
+ 2 : nx
+ 1) - ny
;
1842 for (i
= 0; i
< j
; i
++)
1843 zds
[i
] = zds
[i
+ ny
];
1846 case 1: /* subtract for scm_modulo */
1852 num
+= y
[i
] - zds
[i
];
1856 zds
[i
] = num
+ SCM_BIGRAD
;
1868 case 0: /* just normalize remainder */
1870 scm_divbigdig (zds
, ny
, d
);
1873 for (j
= ny
; j
&& !zds
[j
- 1]; --j
);
1874 if (j
* SCM_BITSPERDIG
<= sizeof (SCM
) * SCM_CHAR_BIT
)
1875 if (SCM_INUMP (z
= scm_big2inum (z
, j
)))
1877 return scm_adjbig (z
, j
);
1885 /*** NUMBERS -> STRINGS ***/
1887 static const double fx
[] =
1888 { 0.0, 5e-1, 5e-2, 5e-3, 5e-4, 5e-5,
1889 5e-6, 5e-7, 5e-8, 5e-9, 5e-10,
1890 5e-11, 5e-12, 5e-13, 5e-14, 5e-15,
1891 5e-16, 5e-17, 5e-18, 5e-19, 5e-20};
1897 idbl2str (double f
, char *a
)
1899 int efmt
, dpt
, d
, i
, wp
= scm_dblprec
;
1904 goto zero
; /*{a[0]='0'; a[1]='.'; a[2]='0'; return 3;} */
1923 #ifdef DBL_MIN_10_EXP /* Prevent unnormalized values, as from
1924 make-uniform-vector, from causing infinite loops. */
1928 if (exp
-- < DBL_MIN_10_EXP
)
1934 if (exp
++ > DBL_MAX_10_EXP
)
1949 if (f
+ fx
[wp
] >= 10.0)
1956 dpt
= (exp
+ 9999) % 3;
1960 efmt
= (exp
< -3) || (exp
> wp
+ 2);
1985 if (f
+ fx
[wp
] >= 1.0)
1999 if ((dpt
> 4) && (exp
> 6))
2001 d
= (a
[0] == '-' ? 2 : 1);
2002 for (i
= ch
++; i
> d
; i
--)
2015 if (a
[ch
- 1] == '.')
2016 a
[ch
++] = '0'; /* trailing zero */
2025 for (i
= 10; i
<= exp
; i
*= 10);
2026 for (i
/= 10; i
; i
/= 10)
2028 a
[ch
++] = exp
/ i
+ '0';
2037 iflo2str (SCM flt
, char *str
)
2040 if (SCM_SLOPPY_REALP (flt
))
2041 i
= idbl2str (SCM_REAL_VALUE (flt
), str
);
2044 i
= idbl2str (SCM_COMPLEX_REAL (flt
), str
);
2045 if (SCM_COMPLEX_IMAG (flt
) != 0.0)
2047 if (0 <= SCM_COMPLEX_IMAG (flt
))
2049 i
+= idbl2str (SCM_COMPLEX_IMAG (flt
), &str
[i
]);
2056 /* convert a long to a string (unterminated). returns the number of
2057 characters in the result.
2059 p is destination: worst case (base 2) is SCM_INTBUFLEN */
2061 scm_iint2str (long num
, int rad
, char *p
)
2065 unsigned long n
= (num
< 0) ? -num
: num
;
2067 for (n
/= rad
; n
> 0; n
/= rad
)
2084 p
[i
] = d
+ ((d
< 10) ? '0' : 'a' - 10);
2093 big2str (SCM b
, unsigned int radix
)
2095 SCM t
= scm_copybig (b
, 0); /* sign of temp doesn't matter */
2096 register SCM_BIGDIG
*ds
= SCM_BDIGITS (t
);
2097 scm_sizet i
= SCM_NUMDIGS (t
);
2098 scm_sizet j
= radix
== 16 ? (SCM_BITSPERDIG
* i
) / 4 + 2
2099 : radix
>= 10 ? (SCM_BITSPERDIG
* i
* 241L) / 800 + 2
2100 : (SCM_BITSPERDIG
* i
) + 2;
2102 scm_sizet radct
= 0;
2103 scm_sizet ch
; /* jeh */
2104 SCM_BIGDIG radpow
= 1, radmod
= 0;
2105 SCM ss
= scm_makstr ((long) j
, 0);
2106 char *s
= SCM_CHARS (ss
), c
;
2107 while ((long) radpow
* radix
< SCM_BIGRAD
)
2112 s
[0] = SCM_BIGSIGN (b
) ? '-' : '+';
2113 while ((i
|| radmod
) && j
)
2117 radmod
= (SCM_BIGDIG
) scm_divbigdig (ds
, i
, radpow
);
2125 s
[--j
] = c
< 10 ? c
+ '0' : c
+ 'a' - 10;
2127 ch
= s
[0] == '-' ? 1 : 0; /* jeh */
2130 for (i
= j
; j
< SCM_LENGTH (ss
); j
++)
2131 s
[ch
+ j
- i
] = s
[j
]; /* jeh */
2132 scm_vector_set_length_x (ss
, /* jeh */
2133 (SCM
) SCM_MAKINUM (ch
+ SCM_LENGTH (ss
) - i
));
2136 return scm_return_first (ss
, t
);
2141 SCM_DEFINE (scm_number_to_string
, "number->string", 1, 1, 0,
2144 #define FUNC_NAME s_scm_number_to_string
2147 SCM_VALIDATE_INUM_MIN_DEF_COPY (2,radix
,2,10,base
);
2150 char num_buf
[SCM_FLOBUFLEN
];
2152 SCM_ASRTGO (SCM_NIMP (x
), badx
);
2154 return big2str (x
, (unsigned int) base
);
2155 #ifndef SCM_RECKLESS
2156 if (!SCM_SLOPPY_INEXACTP (x
))
2163 SCM_ASSERT (SCM_SLOPPY_INEXACTP (x
),
2164 x
, SCM_ARG1
, s_number_to_string
);
2166 return scm_makfromstr (num_buf
, iflo2str (x
, num_buf
), 0);
2169 char num_buf
[SCM_INTBUFLEN
];
2170 return scm_makfromstr (num_buf
,
2171 scm_iint2str (SCM_INUM (x
),
2180 /* These print routines are stubbed here so that scm_repl.c doesn't need
2181 SCM_BIGDIG conditionals */
2184 scm_print_real (SCM sexp
, SCM port
, scm_print_state
*pstate
)
2186 char num_buf
[SCM_FLOBUFLEN
];
2187 scm_lfwrite (num_buf
, iflo2str (sexp
, num_buf
), port
);
2192 scm_print_complex (SCM sexp
, SCM port
, scm_print_state
*pstate
)
2194 char num_buf
[SCM_FLOBUFLEN
];
2195 scm_lfwrite (num_buf
, iflo2str (sexp
, num_buf
), port
);
2200 scm_bigprint (SCM exp
, SCM port
, scm_print_state
*pstate
)
2203 exp
= big2str (exp
, (unsigned int) 10);
2204 scm_lfwrite (SCM_CHARS (exp
), (scm_sizet
) SCM_LENGTH (exp
), port
);
2206 scm_ipruk ("bignum", exp
, port
);
2210 /*** END nums->strs ***/
2212 /*** STRINGS -> NUMBERS ***/
2215 scm_small_istr2int (char *str
, long len
, long radix
)
2217 register long n
= 0, ln
;
2222 return SCM_BOOL_F
; /* zero scm_length */
2224 { /* leading sign */
2229 return SCM_BOOL_F
; /* bad if lone `+' or `-' */
2234 switch (c
= str
[i
++])
2256 return SCM_BOOL_F
; /* bad digit for radix */
2259 /* Negation is a workaround for HP700 cc bug */
2260 if (n
> ln
|| (-n
> -SCM_MOST_NEGATIVE_FIXNUM
))
2264 return SCM_BOOL_F
; /* not a digit */
2269 if ((n
= -n
) > SCM_MOST_POSITIVE_FIXNUM
)
2271 return SCM_MAKINUM (n
);
2272 ovfl
: /* overflow scheme integer */
2279 scm_istr2int (char *str
, long len
, long radix
)
2282 register scm_sizet k
, blen
= 1;
2286 register SCM_BIGDIG
*ds
;
2287 register unsigned long t2
;
2290 return SCM_BOOL_F
; /* zero scm_length */
2292 /* Short numbers we parse directly into an int, to avoid the overhead
2293 of creating a bignum. */
2295 return scm_small_istr2int (str
, len
, radix
);
2298 j
= 1 + (4 * len
* sizeof (char)) / (SCM_BITSPERDIG
);
2299 else if (10 <= radix
)
2300 j
= 1 + (84 * len
* sizeof (char)) / (SCM_BITSPERDIG
* 25);
2302 j
= 1 + (len
* sizeof (char)) / (SCM_BITSPERDIG
);
2304 { /* leading sign */
2307 if (++i
== (unsigned) len
)
2308 return SCM_BOOL_F
; /* bad if lone `+' or `-' */
2310 res
= scm_mkbig (j
, '-' == str
[0]);
2311 ds
= SCM_BDIGITS (res
);
2316 switch (c
= str
[i
++])
2338 return SCM_BOOL_F
; /* bad digit for radix */
2344 /* printf ("k = %d, blen = %d, t2 = %ld, ds[k] = %d\n", k, blen, t2, ds[k]); */
2345 t2
+= ds
[k
] * radix
;
2346 ds
[k
++] = SCM_BIGLO (t2
);
2347 t2
= SCM_BIGDN (t2
);
2350 scm_num_overflow ("bignum");
2358 return SCM_BOOL_F
; /* not a digit */
2361 while (i
< (unsigned) len
);
2362 if (blen
* SCM_BITSPERDIG
/ SCM_CHAR_BIT
<= sizeof (SCM
))
2363 if (SCM_INUMP (res
= scm_big2inum (res
, blen
)))
2367 return scm_adjbig (res
, blen
);
2371 scm_istr2flo (char *str
, long len
, long radix
)
2373 register int c
, i
= 0;
2375 double res
= 0.0, tmp
= 0.0;
2381 return SCM_BOOL_F
; /* zero scm_length */
2384 { /* leading sign */
2397 return SCM_BOOL_F
; /* bad if lone `+' or `-' */
2399 if (str
[i
] == 'i' || str
[i
] == 'I')
2400 { /* handle `+i' and `-i' */
2401 if (lead_sgn
== 0.0)
2402 return SCM_BOOL_F
; /* must have leading sign */
2404 return SCM_BOOL_F
; /* `i' not last character */
2405 return scm_makdbl (0.0, lead_sgn
);
2408 { /* check initial digits */
2418 goto out1
; /* must be exponent */
2435 return SCM_BOOL_F
; /* bad digit for radix */
2436 res
= res
* radix
+ c
;
2437 flg
= 1; /* res is valid */
2446 /* if true, then we did see a digit above, and res is valid */
2450 /* By here, must have seen a digit,
2451 or must have next char be a `.' with radix==10 */
2453 if (!(str
[i
] == '.' && radix
== 10))
2456 while (str
[i
] == '#')
2457 { /* optional sharps */
2490 tmp
= tmp
* radix
+ c
;
2498 return SCM_BOOL_F
; /* `slash zero' not allowed */
2500 while (str
[i
] == '#')
2501 { /* optional sharps */
2511 { /* decimal point notation */
2513 return SCM_BOOL_F
; /* must be radix 10 */
2520 res
= res
* 10.0 + c
- '0';
2529 return SCM_BOOL_F
; /* no digits before or after decimal point */
2532 while (str
[i
] == '#')
2533 { /* ignore remaining sharps */
2552 int expsgn
= 1, expon
= 0;
2554 return SCM_BOOL_F
; /* only in radix 10 */
2556 return SCM_BOOL_F
; /* bad exponent */
2563 return SCM_BOOL_F
; /* bad exponent */
2565 if (str
[i
] < '0' || str
[i
] > '9')
2566 return SCM_BOOL_F
; /* bad exponent */
2572 expon
= expon
* 10 + c
- '0';
2573 if (expon
> SCM_MAXEXP
)
2574 return SCM_BOOL_F
; /* exponent too large */
2582 point
+= expsgn
* expon
;
2600 /* at this point, we have a legitimate floating point result */
2601 if (lead_sgn
== -1.0)
2604 return scm_makdbl (res
, 0.0);
2606 if (str
[i
] == 'i' || str
[i
] == 'I')
2607 { /* pure imaginary number */
2608 if (lead_sgn
== 0.0)
2609 return SCM_BOOL_F
; /* must have leading sign */
2611 return SCM_BOOL_F
; /* `i' not last character */
2612 return scm_makdbl (0.0, res
);
2624 { /* polar input for complex number */
2625 /* get a `real' for scm_angle */
2626 second
= scm_istr2flo (&str
[i
], (long) (len
- i
), radix
);
2627 if (!SCM_SLOPPY_INEXACTP (second
))
2628 return SCM_BOOL_F
; /* not `real' */
2629 if (SCM_SLOPPY_COMPLEXP (second
))
2630 return SCM_BOOL_F
; /* not `real' */
2631 tmp
= SCM_REALPART (second
);
2632 return scm_makdbl (res
* cos (tmp
), res
* sin (tmp
));
2638 /* at this point, last char must be `i' */
2639 if (str
[len
- 1] != 'i' && str
[len
- 1] != 'I')
2641 /* handles `x+i' and `x-i' */
2643 return scm_makdbl (res
, lead_sgn
);
2644 /* get a `ureal' for complex part */
2645 second
= scm_istr2flo (&str
[i
], (long) ((len
- i
) - 1), radix
);
2646 if (!SCM_INEXACTP (second
))
2647 return SCM_BOOL_F
; /* not `ureal' */
2648 if (SCM_SLOPPY_COMPLEXP (second
))
2649 return SCM_BOOL_F
; /* not `ureal' */
2650 tmp
= SCM_REALPART (second
);
2652 return SCM_BOOL_F
; /* not `ureal' */
2653 return scm_makdbl (res
, (lead_sgn
* tmp
));
2659 scm_istring2number (char *str
, long len
, long radix
)
2663 char ex_p
= 0, rx_p
= 0; /* Only allow 1 exactness and 1 radix prefix */
2666 if (*str
== '+' || *str
== '-') /* Catches lone `+' and `-' for speed */
2669 while ((len
- i
) >= 2 && str
[i
] == '#' && ++i
)
2715 return scm_istr2int (&str
[i
], len
- i
, radix
);
2717 res
= scm_istr2int (&str
[i
], len
- i
, radix
);
2718 if (SCM_NFALSEP (res
))
2721 return scm_istr2flo (&str
[i
], len
- i
, radix
);
2727 SCM_DEFINE (scm_string_to_number
, "string->number", 1, 1, 0,
2728 (SCM str
, SCM radix
),
2730 #define FUNC_NAME s_scm_string_to_number
2734 SCM_VALIDATE_ROSTRING (1,str
);
2735 SCM_VALIDATE_INUM_MIN_DEF_COPY (2,radix
,2,10,base
);
2736 answer
= scm_istring2number (SCM_ROCHARS (str
),
2739 return scm_return_first (answer
, str
);
2742 /*** END strs->nums ***/
2745 scm_make_real (double x
)
2753 scm_make_complex (double x
, double y
)
2756 SCM_NEWCOMPLEX (z
, x
, y
);
2761 scm_bigequal (SCM x
, SCM y
)
2764 if (0 == scm_bigcomp (x
, y
))
2771 scm_real_equalp (SCM x
, SCM y
)
2773 return SCM_BOOL (SCM_REAL_VALUE (x
) == SCM_REAL_VALUE (y
));
2777 scm_complex_equalp (SCM x
, SCM y
)
2779 return SCM_BOOL (SCM_COMPLEX_REAL (x
) == SCM_COMPLEX_REAL (y
)
2780 && SCM_COMPLEX_IMAG (x
) == SCM_COMPLEX_IMAG (y
));
2785 SCM_REGISTER_PROC (s_number_p
, "number?", 1, 0, 0, scm_number_p
);
2787 SCM_DEFINE (scm_number_p
, "complex?", 1, 0, 0,
2790 #define FUNC_NAME s_scm_number_p
2802 SCM_REGISTER_PROC (s_real_p
, "real?", 1, 0, 0, scm_real_p
);
2805 SCM_DEFINE (scm_real_p
, "rational?", 1, 0, 0,
2808 #define FUNC_NAME s_scm_real_p
2814 if (SCM_SLOPPY_REALP (x
))
2826 SCM_DEFINE (scm_integer_p
, "integer?", 1, 0, 0,
2829 #define FUNC_NAME s_scm_integer_p
2840 if (!SCM_SLOPPY_INEXACTP (x
))
2842 if (SCM_SLOPPY_COMPLEXP (x
))
2844 r
= SCM_REALPART (x
);
2853 SCM_DEFINE (scm_inexact_p
, "inexact?", 1, 0, 0,
2856 #define FUNC_NAME s_scm_inexact_p
2858 if (SCM_INEXACTP (x
))
2867 SCM_GPROC1 (s_eq_p
, "=", scm_tc7_rpsubr
, scm_num_eq_p
, g_eq_p
);
2870 scm_num_eq_p (SCM x
, SCM y
)
2879 SCM_WTA_DISPATCH_2 (g_eq_p
, x
, y
, SCM_ARG1
, s_eq_p
);
2885 SCM_ASRTGO (SCM_NIMP (y
), bady
);
2887 return SCM_BOOL(0 == scm_bigcomp (x
, y
));
2888 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
2890 return ((SCM_SLOPPY_REALP (y
) && (scm_big2dbl (x
) == SCM_REALPART (y
)))
2894 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x
), badx
);
2896 SCM_GASSERT2 (SCM_SLOPPY_INEXACTP (x
),
2897 g_eq_p
, x
, y
, SCM_ARG1
, s_eq_p
);
2907 SCM_ASRTGO (SCM_NIMP (y
), bady
);
2915 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
2917 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
2919 if (SCM_SLOPPY_REALP (x
))
2921 if (SCM_SLOPPY_REALP (y
))
2922 return SCM_BOOL (SCM_REAL_VALUE (x
) == SCM_REAL_VALUE (y
));
2924 return SCM_BOOL (SCM_REAL_VALUE (x
) == SCM_COMPLEX_REAL (y
)
2925 && 0.0 == SCM_COMPLEX_IMAG (y
));
2929 if (SCM_SLOPPY_REALP (y
))
2930 return SCM_BOOL (SCM_COMPLEX_REAL (x
) == SCM_REAL_VALUE (y
)
2931 && SCM_COMPLEX_IMAG (x
) == 0.0);
2933 return SCM_BOOL (SCM_COMPLEX_REAL (x
) == SCM_COMPLEX_REAL (y
)
2934 && SCM_COMPLEX_IMAG (x
) == SCM_COMPLEX_IMAG (y
));
2940 SCM_ASRTGO (SCM_NIMP (y
), bady
);
2943 if (!SCM_SLOPPY_INEXACTP (y
))
2946 SCM_WTA_DISPATCH_2 (g_eq_p
, x
, y
, SCM_ARGn
, s_eq_p
);
2949 if (!SCM_SLOPPY_INEXACTP (y
))
2952 SCM_WTA_DISPATCH_2 (g_eq_p
, x
, y
, SCM_ARGn
, s_eq_p
);
2956 if (SCM_SLOPPY_REALP (y
))
2957 return SCM_BOOL ((double) SCM_INUM (x
) == SCM_REAL_VALUE (y
));
2959 return SCM_BOOL ((double) SCM_INUM (x
) == SCM_COMPLEX_REAL (y
)
2960 && 0.0 == SCM_COMPLEX_IMAG (y
));
2962 return SCM_BOOL((long) x
== (long) y
);
2967 SCM_GPROC1 (s_less_p
, "<", scm_tc7_rpsubr
, scm_less_p
, g_less_p
);
2970 scm_less_p (SCM x
, SCM y
)
2978 SCM_WTA_DISPATCH_2 (g_less_p
, x
, y
, SCM_ARG1
, s_less_p
);
2983 return SCM_BOOL(SCM_BIGSIGN (x
));
2984 SCM_ASRTGO (SCM_NIMP (y
), bady
);
2986 return SCM_BOOL(1 == scm_bigcomp (x
, y
));
2987 SCM_ASRTGO (SCM_SLOPPY_REALP (y
), bady
);
2988 return ((scm_big2dbl (x
) < SCM_REALPART (y
))
2992 SCM_ASRTGO (SCM_SLOPPY_REALP (x
), badx
);
2994 SCM_GASSERT2 (SCM_SLOPPY_REALP (x
),
2995 g_less_p
, x
, y
, SCM_ARG1
, s_less_p
);
2998 return ((SCM_REALPART (x
) < ((double) SCM_INUM (y
)))
3002 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3004 return SCM_BOOL(SCM_REALPART (x
) < scm_big2dbl (y
));
3005 SCM_ASRTGO (SCM_SLOPPY_REALP (y
), bady
);
3007 SCM_ASRTGO (SCM_SLOPPY_REALP (y
), bady
);
3009 return SCM_BOOL(SCM_REALPART (x
) < SCM_REALPART (y
));
3014 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3016 return SCM_NEGATE_BOOL(SCM_BIGSIGN (y
));
3017 if (!SCM_SLOPPY_REALP (y
))
3020 SCM_WTA_DISPATCH_2 (g_less_p
, x
, y
, SCM_ARGn
, s_less_p
);
3023 if (!SCM_SLOPPY_REALP (y
))
3026 SCM_WTA_DISPATCH_2 (g_less_p
, x
, y
, SCM_ARGn
, s_less_p
);
3029 return ((((double) SCM_INUM (x
)) < SCM_REALPART (y
))
3033 return SCM_BOOL((long) x
< (long) y
);
3037 SCM_DEFINE1 (scm_gr_p
, ">", scm_tc7_rpsubr
,
3040 #define FUNC_NAME s_scm_gr_p
3042 return scm_less_p (y
, x
);
3048 SCM_DEFINE1 (scm_leq_p
, "<=", scm_tc7_rpsubr
,
3051 #define FUNC_NAME s_scm_leq_p
3053 return SCM_BOOL_NOT (scm_less_p (y
, x
));
3059 SCM_DEFINE1 (scm_geq_p
, ">=", scm_tc7_rpsubr
,
3062 #define FUNC_NAME s_scm_geq_p
3064 return SCM_BOOL_NOT (scm_less_p (x
, y
));
3070 SCM_GPROC (s_zero_p
, "zero?", 1, 0, 0, scm_zero_p
, g_zero_p
);
3078 SCM_ASRTGO (SCM_NIMP (z
), badz
);
3081 if (!SCM_SLOPPY_INEXACTP (z
))
3084 SCM_WTA_DISPATCH_1 (g_zero_p
, z
, SCM_ARG1
, s_zero_p
);
3087 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z
),
3088 g_zero_p
, z
, SCM_ARG1
, s_zero_p
);
3090 if (SCM_SLOPPY_REALP (z
))
3091 return SCM_BOOL (SCM_REAL_VALUE (z
) == 0.0);
3093 return SCM_BOOL (SCM_COMPLEX_REAL (z
) == 0.0
3094 && SCM_COMPLEX_IMAG (z
) == 0.0);
3096 return SCM_BOOL(z
== SCM_INUM0
);
3101 SCM_GPROC (s_positive_p
, "positive?", 1, 0, 0, scm_positive_p
, g_positive_p
);
3104 scm_positive_p (SCM x
)
3109 SCM_ASRTGO (SCM_NIMP (x
), badx
);
3111 return SCM_BOOL (!SCM_BIGSIGN (x
));
3112 if (!SCM_SLOPPY_REALP (x
))
3115 SCM_WTA_DISPATCH_1 (g_positive_p
, x
, SCM_ARG1
, s_positive_p
);
3118 SCM_GASSERT1 (SCM_SLOPPY_REALP (x
),
3119 g_positive_p
, x
, SCM_ARG1
, s_positive_p
);
3121 return SCM_BOOL(SCM_REALPART (x
) > 0.0);
3123 return SCM_BOOL(SCM_INUM(x
) > 0);
3128 SCM_GPROC (s_negative_p
, "negative?", 1, 0, 0, scm_negative_p
, g_negative_p
);
3131 scm_negative_p (SCM x
)
3136 SCM_ASRTGO (SCM_NIMP (x
), badx
);
3138 return SCM_BOOL (SCM_BIGSIGN (x
));
3139 if (!(SCM_SLOPPY_REALP (x
)))
3142 SCM_WTA_DISPATCH_1 (g_negative_p
, x
, SCM_ARG1
, s_negative_p
);
3145 SCM_GASSERT1 (SCM_SLOPPY_REALP (x
),
3146 g_negative_p
, x
, SCM_ARG1
, s_negative_p
);
3148 return SCM_BOOL(SCM_REALPART (x
) < 0.0);
3150 return SCM_BOOL(SCM_INUM(x
) < 0);
3154 SCM_GPROC1 (s_max
, "max", scm_tc7_asubr
, scm_max
, g_max
);
3157 scm_max (SCM x
, SCM y
)
3162 SCM_GASSERT0 (!SCM_UNBNDP (x
),
3163 g_max
, scm_makfrom0str (s_max
), SCM_WNA
, 0);
3164 SCM_GASSERT1 (SCM_NUMBERP (x
), g_max
, x
, SCM_ARG1
, s_max
);
3173 SCM_WTA_DISPATCH_2 (g_max
, x
, y
, SCM_ARG1
, s_max
);
3178 return SCM_BIGSIGN (x
) ? y
: x
;
3179 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3181 return (1 == scm_bigcomp (x
, y
)) ? y
: x
;
3182 SCM_ASRTGO (SCM_SLOPPY_REALP (y
), bady
);
3183 z
= scm_big2dbl (x
);
3184 return (z
< SCM_REALPART (y
)) ? y
: scm_makdbl (z
, 0.0);
3186 SCM_ASRTGO (SCM_SLOPPY_REALP (x
), badx2
);
3188 SCM_GASSERT2 (SCM_SLOPPY_REALP (x
),
3189 g_max
, x
, y
, SCM_ARG1
, s_max
);
3192 return ((SCM_REALPART (x
) < (z
= SCM_INUM (y
)))
3193 ? scm_makdbl (z
, 0.0)
3196 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3198 return ((SCM_REALPART (x
) < (z
= scm_big2dbl (y
)))
3199 ? scm_makdbl (z
, 0.0)
3201 SCM_ASRTGO (SCM_SLOPPY_REALP (y
), bady
);
3203 SCM_ASRTGO (SCM_SLOPPY_REALP (y
), bady
);
3205 return (SCM_REALPART (x
) < SCM_REALPART (y
)) ? y
: x
;
3210 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3212 return SCM_BIGSIGN (y
) ? x
: y
;
3213 if (!(SCM_SLOPPY_REALP (y
)))
3216 SCM_WTA_DISPATCH_2 (g_max
, x
, y
, SCM_ARGn
, s_max
);
3219 if (!SCM_SLOPPY_REALP (y
))
3222 SCM_WTA_DISPATCH_2 (g_max
, x
, y
, SCM_ARGn
, s_max
);
3225 return (((z
= SCM_INUM (x
)) < SCM_REALPART (y
))
3227 : scm_makdbl (z
, 0.0));
3229 return ((long) x
< (long) y
) ? y
: x
;
3233 #define SCM_SWAP(x,y) do { SCM t = x; x = y; y = t; } while (0)
3237 SCM_GPROC1 (s_min
, "min", scm_tc7_asubr
, scm_min
, g_min
);
3240 scm_min (SCM x
, SCM y
)
3245 SCM_GASSERT0 (!SCM_UNBNDP (x
),
3246 g_min
, scm_makfrom0str (s_min
), SCM_WNA
, 0);
3247 SCM_GASSERT1 (SCM_NUMBERP (x
), g_min
, x
, SCM_ARG1
, s_min
);
3256 SCM_WTA_DISPATCH_2 (g_min
, x
, y
, SCM_ARG1
, s_min
);
3261 return SCM_BIGSIGN (x
) ? x
: y
;
3262 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3264 return (-1 == scm_bigcomp (x
, y
)) ? y
: x
;
3265 SCM_ASRTGO (SCM_SLOPPY_REALP (y
), bady
);
3266 z
= scm_big2dbl (x
);
3267 return (z
> SCM_REALPART (y
)) ? y
: scm_makdbl (z
, 0.0);
3269 SCM_ASRTGO (SCM_SLOPPY_REALP (x
), badx2
);
3271 SCM_GASSERT2 (SCM_SLOPPY_REALP (x
),
3272 g_min
, x
, y
, SCM_ARG1
, s_min
);
3275 return ((SCM_REALPART (x
) > (z
= SCM_INUM (y
)))
3276 ? scm_makdbl (z
, 0.0)
3279 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3281 return ((SCM_REALPART (x
) > (z
= scm_big2dbl (y
)))
3282 ? scm_makdbl (z
, 0.0)
3284 SCM_ASRTGO (SCM_SLOPPY_REALP (y
), bady
);
3286 SCM_ASRTGO (SCM_SLOPPY_REALP (y
), bady
);
3288 return (SCM_REALPART (x
) > SCM_REALPART (y
)) ? y
: x
;
3293 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3295 return SCM_BIGSIGN (y
) ? y
: x
;
3296 if (!(SCM_SLOPPY_REALP (y
)))
3299 SCM_WTA_DISPATCH_2 (g_min
, x
, y
, SCM_ARGn
, s_min
);
3302 if (!SCM_SLOPPY_REALP (y
))
3305 SCM_WTA_DISPATCH_2 (g_min
, x
, y
, SCM_ARGn
, s_min
);
3308 return (((z
= SCM_INUM (x
)) > SCM_REALPART (y
))
3310 : scm_makdbl (z
, 0.0));
3312 return ((long) x
> (long) y
) ? y
: x
;
3318 SCM_GPROC1 (s_sum
, "+", scm_tc7_asubr
, scm_sum
, g_sum
);
3321 This is sick, sick, sick code.
3325 scm_sum (SCM x
, SCM y
)
3331 SCM_GASSERT1 (SCM_NUMBERP (x
), g_sum
, x
, SCM_ARG1
, s_sum
);
3340 SCM_WTA_DISPATCH_2 (g_sum
, x
, y
, SCM_ARG1
, s_sum
);
3349 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3352 if (SCM_NUMDIGS (x
) > SCM_NUMDIGS (y
))
3356 return scm_addbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
3360 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3362 if (SCM_SLOPPY_REALP (y
))
3363 return scm_make_real (scm_big2dbl (x
) + SCM_REAL_VALUE (y
));
3365 return scm_make_complex (scm_big2dbl (x
) + SCM_COMPLEX_REAL (y
),
3366 SCM_COMPLEX_IMAG (y
));
3368 # endif /* SCM_BIGDIG */
3369 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x
), badx2
);
3377 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3383 else if (!SCM_SLOPPY_INEXACTP (y
))
3386 SCM_WTA_DISPATCH_2 (g_sum
, x
, y
, SCM_ARGn
, s_sum
);
3388 # else /* SCM_BIGDIG */
3389 if (!SCM_SLOPPY_INEXACTP (y
))
3392 SCM_WTA_DISPATCH_2 (g_sum
, x
, y
, SCM_ARGn
, s_sum
);
3394 # endif /* SCM_BIGDIG */
3397 if (SCM_SLOPPY_COMPLEXP (x
))
3398 i
= SCM_COMPLEX_IMAG (x
);
3399 if (SCM_SLOPPY_COMPLEXP (y
))
3400 i
+= SCM_COMPLEX_IMAG (y
);
3401 return scm_makdbl (SCM_REALPART (x
) + SCM_REALPART (y
), i
);
3407 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3412 # ifndef SCM_DIGSTOOBIG
3413 long z
= scm_pseudolong (SCM_INUM (x
));
3414 return scm_addbig ((SCM_BIGDIG
*) & z
,
3416 (x
< 0) ? SCM_BIGSIGNFLAG
: 0,
3418 # else /* SCM_DIGSTOOBIG */
3419 SCM_BIGDIG zdigs
[SCM_DIGSPERLONG
];
3420 scm_longdigs (SCM_INUM (x
), zdigs
);
3421 return scm_addbig (zdigs
, SCM_DIGSPERLONG
, (x
< 0) ? SCM_BIGSIGNFLAG
: 0,
3423 # endif /* SCM_DIGSTOOBIG */
3426 # endif /* SCM_BIGDIG */
3427 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3430 return scm_make_real (SCM_INUM (x
) + SCM_REAL_VALUE (y
));
3432 return scm_make_complex (SCM_INUM (x
) + SCM_COMPLEX_REAL (y
),
3433 SCM_COMPLEX_IMAG (y
));
3436 long int i
= SCM_INUM (x
) + SCM_INUM (y
);
3437 if (SCM_FIXABLE (i
))
3438 return SCM_MAKINUM (i
);
3440 return scm_long2big (i
);
3441 #else /* SCM_BIGDIG */
3442 return scm_makdbl ((double) i
, 0.0);
3443 #endif /* SCM_BIGDIG */
3450 SCM_GPROC1 (s_difference
, "-", scm_tc7_asubr
, scm_difference
, g_difference
);
3453 HWN:FIXME:: This is sick,sick, sick code. Rewrite me.
3456 scm_difference (SCM x
, SCM y
)
3465 SCM_GASSERT0 (!SCM_UNBNDP (x
), g_difference
,
3466 scm_makfrom0str (s_difference
), SCM_WNA
, 0);
3468 SCM_WTA_DISPATCH_1 (g_difference
, x
, SCM_ARG1
, s_difference
);
3473 SCM_WTA_DISPATCH_2 (g_difference
, x
, y
, SCM_ARG1
, s_difference
);
3481 x
= scm_copybig (x
, !SCM_BIGSIGN (x
));
3482 return (SCM_NUMDIGS (x
) * SCM_BITSPERDIG
/ SCM_CHAR_BIT
3484 ? scm_big2inum (x
, SCM_NUMDIGS (x
))
3488 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x
), badx
);
3489 if (SCM_SLOPPY_REALP (x
))
3490 return scm_make_real (- SCM_REAL_VALUE (x
));
3492 return scm_make_complex (- SCM_COMPLEX_REAL (x
),
3493 - SCM_COMPLEX_IMAG (x
));
3496 return scm_sum (x
, SCM_MAKINUM (- SCM_INUM (y
)));
3498 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3502 return ((SCM_NUMDIGS (x
) < SCM_NUMDIGS (y
))
3503 ? scm_addbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
3506 : scm_addbig (SCM_BDIGITS (y
), SCM_NUMDIGS (y
),
3507 SCM_BIGSIGN (y
) ^ SCM_BIGSIGNFLAG
,
3509 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3511 return scm_make_real (scm_big2dbl (x
) - SCM_REAL_VALUE (y
));
3513 return scm_make_complex (scm_big2dbl (x
) - SCM_COMPLEX_REAL (y
),
3514 - SCM_COMPLEX_IMAG (y
));
3516 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x
), badx2
);
3520 return scm_make_real (SCM_REAL_VALUE (x
) - scm_big2dbl (y
));
3522 return scm_make_complex (SCM_COMPLEX_REAL (x
) - scm_big2dbl (y
),
3523 SCM_COMPLEX_IMAG (x
));
3525 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3527 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x
), badx2
);
3528 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3532 if (SCM_SLOPPY_COMPLEXP (x
))
3534 if (SCM_SLOPPY_COMPLEXP (y
))
3536 SCM_COMPLEX_REAL (x
) - SCM_COMPLEX_REAL (y
),
3537 SCM_COMPLEX_IMAG (x
) - SCM_COMPLEX_IMAG (y
));
3540 SCM_COMPLEX_REAL (x
) - SCM_REAL_VALUE (y
),
3541 SCM_COMPLEX_IMAG (x
));
3545 if (SCM_SLOPPY_COMPLEXP (y
))
3547 SCM_REAL_VALUE (x
) - SCM_COMPLEX_REAL (y
),
3548 - SCM_COMPLEX_IMAG (y
));
3550 SCM_NEWREAL (z
, SCM_REAL_VALUE (x
) - SCM_REAL_VALUE (y
));
3563 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3566 #ifndef SCM_DIGSTOOBIG
3567 long z
= scm_pseudolong (SCM_INUM (x
));
3568 return scm_addbig ((SCM_BIGDIG
*) & z
, SCM_DIGSPERLONG
,
3569 (x
< 0) ? SCM_BIGSIGNFLAG
: 0,
3570 y
, SCM_BIGSIGNFLAG
);
3572 SCM_BIGDIG zdigs
[SCM_DIGSPERLONG
];
3573 scm_longdigs (SCM_INUM (x
), zdigs
);
3574 return scm_addbig (zdigs
, SCM_DIGSPERLONG
, (x
< 0) ? SCM_BIGSIGNFLAG
: 0,
3575 y
, SCM_BIGSIGNFLAG
);
3578 if (!SCM_SLOPPY_INEXACTP (y
))
3581 SCM_WTA_DISPATCH_2 (g_difference
, x
, y
, SCM_ARGn
, s_difference
);
3584 if (!SCM_SLOPPY_INEXACTP (y
))
3587 SCM_WTA_DISPATCH_2 (g_difference
, x
, y
, SCM_ARGn
, s_difference
);
3590 return scm_makdbl (SCM_INUM (x
) - SCM_REALPART (y
),
3591 SCM_SLOPPY_COMPLEXP (y
) ? -SCM_IMAG (y
) : 0.0);
3593 cx
= SCM_INUM (x
) - SCM_INUM (y
);
3595 if (SCM_FIXABLE (cx
))
3596 return SCM_MAKINUM (cx
);
3598 return scm_long2big (cx
);
3600 return scm_makdbl ((double) cx
, 0.0);
3607 SCM_GPROC1 (s_product
, "*", scm_tc7_asubr
, scm_product
, g_product
);
3610 scm_product (SCM x
, SCM y
)
3615 return SCM_MAKINUM (1L);
3616 SCM_GASSERT1 (SCM_NUMBERP (x
), g_product
, x
, SCM_ARG1
, s_product
);
3626 SCM_WTA_DISPATCH_2 (g_product
, x
, y
, SCM_ARG1
, s_product
);
3637 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3639 return scm_mulbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
3640 SCM_BDIGITS (y
), SCM_NUMDIGS (y
),
3641 SCM_BIGSIGN (x
) ^ SCM_BIGSIGN (y
));
3642 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3645 double bg
= scm_big2dbl (x
);
3646 return scm_makdbl (bg
* SCM_REALPART (y
),
3647 SCM_SLOPPY_COMPLEXP (y
) ? bg
* SCM_IMAG (y
) : 0.0);
3650 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x
), badx2
);
3652 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x
), badx2
);
3662 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3670 else if (!(SCM_SLOPPY_INEXACTP (y
)))
3673 SCM_WTA_DISPATCH_2 (g_product
, x
, y
, SCM_ARGn
, s_product
);
3676 if (!SCM_SLOPPY_INEXACTP (y
))
3679 SCM_WTA_DISPATCH_2 (g_product
, x
, y
, SCM_ARGn
, s_product
);
3682 if (SCM_SLOPPY_COMPLEXP (x
))
3684 if (SCM_SLOPPY_COMPLEXP (y
))
3685 return scm_makdbl (SCM_REAL (x
) * SCM_REAL (y
)
3686 - SCM_IMAG (x
) * SCM_IMAG (y
),
3687 SCM_REAL (x
) * SCM_IMAG (y
)
3688 + SCM_IMAG (x
) * SCM_REAL (y
));
3690 return scm_makdbl (SCM_REAL (x
) * SCM_REALPART (y
),
3691 SCM_IMAG (x
) * SCM_REALPART (y
));
3693 return scm_makdbl (SCM_REALPART (x
) * SCM_REALPART (y
),
3694 SCM_SLOPPY_COMPLEXP (y
)
3695 ? SCM_REALPART (x
) * SCM_IMAG (y
)
3701 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3707 if (SCM_MAKINUM (1L) == x
)
3710 #ifndef SCM_DIGSTOOBIG
3711 long z
= scm_pseudolong (SCM_INUM (x
));
3712 return scm_mulbig ((SCM_BIGDIG
*) & z
, SCM_DIGSPERLONG
,
3713 SCM_BDIGITS (y
), SCM_NUMDIGS (y
),
3714 SCM_BIGSIGN (y
) ? (x
> 0) : (x
< 0));
3716 SCM_BIGDIG zdigs
[SCM_DIGSPERLONG
];
3717 scm_longdigs (SCM_INUM (x
), zdigs
);
3718 return scm_mulbig (zdigs
, SCM_DIGSPERLONG
,
3719 SCM_BDIGITS (y
), SCM_NUMDIGS (y
),
3720 SCM_BIGSIGN (y
) ? (x
> 0) : (x
< 0));
3724 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3726 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3729 return scm_makdbl (SCM_INUM (x
) * SCM_REALPART (y
),
3730 SCM_SLOPPY_COMPLEXP (y
) ? SCM_INUM (x
) * SCM_IMAG (y
) : 0.0);
3739 y
= SCM_MAKINUM (k
);
3740 if (k
!= SCM_INUM (y
) || k
/ i
!= j
)
3743 int sgn
= (i
< 0) ^ (j
< 0);
3744 #ifndef SCM_DIGSTOOBIG
3745 i
= scm_pseudolong (i
);
3746 j
= scm_pseudolong (j
);
3747 return scm_mulbig ((SCM_BIGDIG
*) & i
, SCM_DIGSPERLONG
,
3748 (SCM_BIGDIG
*) & j
, SCM_DIGSPERLONG
, sgn
);
3749 #else /* SCM_DIGSTOOBIG */
3750 SCM_BIGDIG idigs
[SCM_DIGSPERLONG
];
3751 SCM_BIGDIG jdigs
[SCM_DIGSPERLONG
];
3752 scm_longdigs (i
, idigs
);
3753 scm_longdigs (j
, jdigs
);
3754 return scm_mulbig (idigs
, SCM_DIGSPERLONG
,
3755 jdigs
, SCM_DIGSPERLONG
,
3760 return scm_makdbl (((double) i
) * ((double) j
), 0.0);
3769 scm_num2dbl (SCM a
, const char *why
)
3772 return (double) SCM_INUM (a
);
3773 SCM_ASSERT (SCM_NIMP (a
), a
, "wrong type argument", why
);
3774 if (SCM_SLOPPY_REALP (a
))
3775 return (SCM_REALPART (a
));
3777 return scm_big2dbl (a
);
3779 SCM_ASSERT (0, a
, "wrong type argument", why
);
3781 unreachable, hopefully.
3783 return (double) 0.0; /* ugh. */
3784 /* return SCM_UNSPECIFIED; */
3788 SCM_GPROC1 (s_divide
, "/", scm_tc7_asubr
, scm_divide
, g_divide
);
3791 scm_divide (SCM x
, SCM y
)
3796 if (!(SCM_NIMP (x
)))
3800 SCM_GASSERT0 (!SCM_UNBNDP (x
),
3801 g_divide
, scm_makfrom0str (s_divide
), SCM_WNA
, 0);
3803 SCM_WTA_DISPATCH_1 (g_divide
, x
, SCM_ARG1
, s_divide
);
3808 SCM_WTA_DISPATCH_2 (g_divide
, x
, y
, SCM_ARG1
, s_divide
);
3815 return scm_makdbl (1.0 / scm_big2dbl (x
), 0.0);
3817 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x
), badx
);
3818 if (SCM_SLOPPY_REALP (x
))
3819 return scm_makdbl (1.0 / SCM_REALPART (x
), 0.0);
3823 return scm_makdbl (r
/ d
, -i
/ d
);
3830 long int z
= SCM_INUM (y
);
3831 #ifndef SCM_RECKLESS
3833 scm_num_overflow (s_divide
);
3841 SCM w
= scm_copybig (x
, SCM_BIGSIGN (x
) ? (y
> 0) : (y
< 0));
3842 return (scm_divbigdig (SCM_BDIGITS (w
), SCM_NUMDIGS (w
),
3844 ? scm_makdbl (scm_big2dbl (x
) / SCM_INUM (y
), 0.0)
3847 #ifndef SCM_DIGSTOOBIG
3848 /*ugh! Does anyone know what this is supposed to do?*/
3849 z
= scm_pseudolong (z
);
3850 z
= SCM_INUM(scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
3851 (SCM_BIGDIG
*) & z
, SCM_DIGSPERLONG
,
3852 SCM_BIGSIGN (x
) ? (y
> 0) : (y
< 0), 3));
3855 SCM_BIGDIG zdigs
[SCM_DIGSPERLONG
];
3856 scm_longdigs (z
, zdigs
);
3857 z
= scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
3858 zdigs
, SCM_DIGSPERLONG
,
3859 SCM_BIGSIGN (x
) ? (y
> 0) : (y
< 0), 3);
3862 return z
? SCM_PACK (z
) : scm_makdbl (scm_big2dbl (x
) / SCM_INUM (y
), 0.0);
3864 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3867 SCM z
= scm_divbigbig (SCM_BDIGITS (x
), SCM_NUMDIGS (x
),
3868 SCM_BDIGITS (y
), SCM_NUMDIGS (y
),
3869 SCM_BIGSIGN (x
) ^ SCM_BIGSIGN (y
), 3);
3870 return z
? z
: scm_makdbl (scm_big2dbl (x
) / scm_big2dbl (y
),
3873 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3874 if (SCM_SLOPPY_REALP (y
))
3875 return scm_makdbl (scm_big2dbl (x
) / SCM_REALPART (y
), 0.0);
3876 a
= scm_big2dbl (x
);
3880 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (x
), badx2
);
3887 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3890 d
= scm_big2dbl (y
);
3893 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3895 SCM_ASRTGO (SCM_SLOPPY_INEXACTP (y
), bady
);
3897 if (SCM_SLOPPY_REALP (y
))
3899 d
= SCM_REALPART (y
);
3901 return scm_makdbl (SCM_REALPART (x
) / d
,
3902 SCM_SLOPPY_COMPLEXP (x
) ? SCM_IMAG (x
) / d
: 0.0);
3904 a
= SCM_REALPART (x
);
3905 if (SCM_SLOPPY_REALP (x
))
3910 return scm_makdbl ((a
* r
+ SCM_IMAG (x
) * i
) / d
,
3911 (SCM_IMAG (x
) * r
- a
* i
) / d
);
3915 if ((SCM_MAKINUM (1L) == x
) || (SCM_MAKINUM (-1L) == x
))
3917 return scm_makdbl (1.0 / ((double) SCM_INUM (x
)), 0.0);
3922 SCM_ASRTGO (SCM_NIMP (y
), bady
);
3924 return scm_makdbl (SCM_INUM (x
) / scm_big2dbl (y
), 0.0);
3925 if (!(SCM_SLOPPY_INEXACTP (y
)))
3928 SCM_WTA_DISPATCH_2 (g_divide
, x
, y
, SCM_ARGn
, s_divide
);
3931 if (!SCM_SLOPPY_INEXACTP (y
))
3934 SCM_WTA_DISPATCH_2 (g_divide
, x
, y
, SCM_ARGn
, s_divide
);
3937 if (SCM_SLOPPY_REALP (y
))
3938 return scm_makdbl (SCM_INUM (x
) / SCM_REALPART (y
), 0.0);
3944 return scm_makdbl ((a
* r
) / d
, (-a
* i
) / d
);
3947 long z
= SCM_INUM (y
);
3948 if ((0 == z
) || SCM_INUM (x
) % z
)
3950 z
= SCM_INUM (x
) / z
;
3951 if (SCM_FIXABLE (z
))
3952 return SCM_MAKINUM (z
);
3954 return scm_long2big (z
);
3957 return scm_makdbl (((double) SCM_INUM (x
)) / ((double) SCM_INUM (y
)), 0.0);
3964 SCM_GPROC1 (s_asinh
, "$asinh", scm_tc7_cxr
, (SCM (*)()) scm_asinh
, g_asinh
);
3967 scm_asinh (double x
)
3969 return log (x
+ sqrt (x
* x
+ 1));
3975 SCM_GPROC1 (s_acosh
, "$acosh", scm_tc7_cxr
, (SCM (*)()) scm_acosh
, g_acosh
);
3978 scm_acosh (double x
)
3980 return log (x
+ sqrt (x
* x
- 1));
3986 SCM_GPROC1 (s_atanh
, "$atanh", scm_tc7_cxr
, (SCM (*)()) scm_atanh
, g_atanh
);
3989 scm_atanh (double x
)
3991 return 0.5 * log ((1 + x
) / (1 - x
));
3997 SCM_GPROC1 (s_truncate
, "truncate", scm_tc7_cxr
, (SCM (*)()) scm_truncate
, g_truncate
);
4000 scm_truncate (double x
)
4009 SCM_GPROC1 (s_round
, "round", scm_tc7_cxr
, (SCM (*)()) scm_round
, g_round
);
4012 scm_round (double x
)
4014 double plus_half
= x
+ 0.5;
4015 double result
= floor (plus_half
);
4016 /* Adjust so that the scm_round is towards even. */
4017 return (plus_half
== result
&& plus_half
/ 2 != floor (plus_half
/ 2))
4018 ? result
- 1 : result
;
4023 SCM_GPROC1 (s_exact_to_inexact
, "exact->inexact", scm_tc7_cxr
, (SCM (*)()) scm_exact_to_inexact
, g_exact_to_inexact
);
4026 scm_exact_to_inexact (double z
)
4032 SCM_GPROC1 (s_i_floor
, "floor", scm_tc7_cxr
, (SCM (*)()) floor
, g_i_floor
);
4033 SCM_GPROC1 (s_i_ceil
, "ceiling", scm_tc7_cxr
, (SCM (*)()) ceil
, g_i_ceil
);
4034 SCM_GPROC1 (s_i_sqrt
, "$sqrt", scm_tc7_cxr
, (SCM (*)()) sqrt
, g_i_sqrt
);
4035 SCM_GPROC1 (s_i_abs
, "$abs", scm_tc7_cxr
, (SCM (*)()) fabs
, g_i_abs
);
4036 SCM_GPROC1 (s_i_exp
, "$exp", scm_tc7_cxr
, (SCM (*)()) exp
, g_i_exp
);
4037 SCM_GPROC1 (s_i_log
, "$log", scm_tc7_cxr
, (SCM (*)()) log
, g_i_log
);
4038 SCM_GPROC1 (s_i_sin
, "$sin", scm_tc7_cxr
, (SCM (*)()) sin
, g_i_sin
);
4039 SCM_GPROC1 (s_i_cos
, "$cos", scm_tc7_cxr
, (SCM (*)()) cos
, g_i_cos
);
4040 SCM_GPROC1 (s_i_tan
, "$tan", scm_tc7_cxr
, (SCM (*)()) tan
, g_i_tan
);
4041 SCM_GPROC1 (s_i_asin
, "$asin", scm_tc7_cxr
, (SCM (*)()) asin
, g_i_asin
);
4042 SCM_GPROC1 (s_i_acos
, "$acos", scm_tc7_cxr
, (SCM (*)()) acos
, g_i_acos
);
4043 SCM_GPROC1 (s_i_atan
, "$atan", scm_tc7_cxr
, (SCM (*)()) atan
, g_i_atan
);
4044 SCM_GPROC1 (s_i_sinh
, "$sinh", scm_tc7_cxr
, (SCM (*)()) sinh
, g_i_sinh
);
4045 SCM_GPROC1 (s_i_cosh
, "$cosh", scm_tc7_cxr
, (SCM (*)()) cosh
, g_i_cosh
);
4046 SCM_GPROC1 (s_i_tanh
, "$tanh", scm_tc7_cxr
, (SCM (*)()) tanh
, g_i_tanh
);
4053 static void scm_two_doubles (SCM z1
,
4055 const char *sstring
,
4059 scm_two_doubles (SCM z1
, SCM z2
, const char *sstring
, struct dpair
*xy
)
4062 xy
->x
= SCM_INUM (z1
);
4066 SCM_ASRTGO (SCM_NIMP (z1
), badz1
);
4068 xy
->x
= scm_big2dbl (z1
);
4071 #ifndef SCM_RECKLESS
4072 if (!SCM_SLOPPY_REALP (z1
))
4073 badz1
:scm_wta (z1
, (char *) SCM_ARG1
, sstring
);
4075 xy
->x
= SCM_REALPART (z1
);
4079 SCM_ASSERT (SCM_SLOPPY_REALP (z1
), z1
, SCM_ARG1
, sstring
);
4080 xy
->x
= SCM_REALPART (z1
);
4085 xy
->y
= SCM_INUM (z2
);
4089 SCM_ASRTGO (SCM_NIMP (z2
), badz2
);
4091 xy
->y
= scm_big2dbl (z2
);
4094 #ifndef SCM_RECKLESS
4095 if (!(SCM_SLOPPY_REALP (z2
)))
4096 badz2
:scm_wta (z2
, (char *) SCM_ARG2
, sstring
);
4098 xy
->y
= SCM_REALPART (z2
);
4102 SCM_ASSERT (SCM_SLOPPY_REALP (z2
), z2
, SCM_ARG2
, sstring
);
4103 xy
->y
= SCM_REALPART (z2
);
4112 SCM_DEFINE (scm_sys_expt
, "$expt", 2, 0, 0,
4115 #define FUNC_NAME s_scm_sys_expt
4118 scm_two_doubles (z1
, z2
, FUNC_NAME
, &xy
);
4119 return scm_makdbl (pow (xy
.x
, xy
.y
), 0.0);
4125 SCM_DEFINE (scm_sys_atan2
, "$atan2", 2, 0, 0,
4128 #define FUNC_NAME s_scm_sys_atan2
4131 scm_two_doubles (z1
, z2
, FUNC_NAME
, &xy
);
4132 return scm_makdbl (atan2 (xy
.x
, xy
.y
), 0.0);
4138 SCM_DEFINE (scm_make_rectangular
, "make-rectangular", 2, 0, 0,
4141 #define FUNC_NAME s_scm_make_rectangular
4144 scm_two_doubles (z1
, z2
, FUNC_NAME
, &xy
);
4145 return scm_makdbl (xy
.x
, xy
.y
);
4151 SCM_DEFINE (scm_make_polar
, "make-polar", 2, 0, 0,
4154 #define FUNC_NAME s_scm_make_polar
4157 scm_two_doubles (z1
, z2
, FUNC_NAME
, &xy
);
4158 return scm_makdbl (xy
.x
* cos (xy
.y
), xy
.x
* sin (xy
.y
));
4165 SCM_GPROC (s_real_part
, "real-part", 1, 0, 0, scm_real_part
, g_real_part
);
4168 scm_real_part (SCM z
)
4173 SCM_ASRTGO (SCM_NIMP (z
), badz
);
4176 if (!(SCM_SLOPPY_INEXACTP (z
)))
4179 SCM_WTA_DISPATCH_1 (g_real_part
, z
, SCM_ARG1
, s_real_part
);
4182 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z
),
4183 g_real_part
, z
, SCM_ARG1
, s_real_part
);
4185 if (SCM_SLOPPY_COMPLEXP (z
))
4186 return scm_makdbl (SCM_REAL (z
), 0.0);
4193 SCM_GPROC (s_imag_part
, "imag-part", 1, 0, 0, scm_imag_part
, g_imag_part
);
4196 scm_imag_part (SCM z
)
4201 SCM_ASRTGO (SCM_NIMP (z
), badz
);
4204 if (!(SCM_SLOPPY_INEXACTP (z
)))
4207 SCM_WTA_DISPATCH_1 (g_imag_part
, z
, SCM_ARG1
, s_imag_part
);
4210 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z
),
4211 g_imag_part
, z
, SCM_ARG1
, s_imag_part
);
4213 if (SCM_SLOPPY_COMPLEXP (z
))
4214 return scm_makdbl (SCM_IMAG (z
), 0.0);
4220 SCM_GPROC (s_magnitude
, "magnitude", 1, 0, 0, scm_magnitude
, g_magnitude
);
4223 scm_magnitude (SCM z
)
4228 SCM_ASRTGO (SCM_NIMP (z
), badz
);
4231 if (!(SCM_SLOPPY_INEXACTP (z
)))
4234 SCM_WTA_DISPATCH_1 (g_magnitude
, z
, SCM_ARG1
, s_magnitude
);
4237 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z
),
4238 g_magnitude
, z
, SCM_ARG1
, s_magnitude
);
4240 if (SCM_SLOPPY_COMPLEXP (z
))
4242 double i
= SCM_IMAG (z
), r
= SCM_REAL (z
);
4243 return scm_makdbl (sqrt (i
* i
+ r
* r
), 0.0);
4245 return scm_makdbl (fabs (SCM_REALPART (z
)), 0.0);
4251 SCM_GPROC (s_angle
, "angle", 1, 0, 0, scm_angle
, g_angle
);
4259 x
= (z
>= SCM_INUM0
) ? 1.0 : -1.0;
4263 SCM_ASRTGO (SCM_NIMP (z
), badz
);
4266 x
= (SCM_BIGSIGN (z
)) ? -1.0 : 1.0;
4269 if (!(SCM_SLOPPY_INEXACTP (z
)))
4272 SCM_WTA_DISPATCH_1 (g_angle
, z
, SCM_ARG1
, s_angle
);
4275 SCM_GASSERT1 (SCM_SLOPPY_INEXACTP (z
), g_angle
, z
, SCM_ARG1
, s_angle
);
4277 if (SCM_SLOPPY_REALP (z
))
4279 x
= SCM_REALPART (z
);
4285 return scm_makdbl (atan2 (y
, x
), 0.0);
4289 SCM_DEFINE (scm_inexact_to_exact
, "inexact->exact", 1, 0, 0,
4292 #define FUNC_NAME s_scm_inexact_to_exact
4297 SCM_ASRTGO (SCM_NIMP (z
), badz
);
4300 #ifndef SCM_RECKLESS
4301 if (!(SCM_SLOPPY_REALP (z
)))
4308 SCM_VALIDATE_REAL (1,z
);
4312 double u
= floor (SCM_REALPART (z
) + 0.5);
4313 if ((u
<= SCM_MOST_POSITIVE_FIXNUM
) && (-u
<= -SCM_MOST_NEGATIVE_FIXNUM
))
4315 /* Negation is a workaround for HP700 cc bug */
4316 SCM ans
= SCM_MAKINUM ((long) u
);
4317 if (SCM_INUM (ans
) == (long) u
)
4320 SCM_ASRTGO (isfinite (u
), badz
); /* problem? */
4321 return scm_dbl2big (u
);
4324 return SCM_MAKINUM ((long) floor (SCM_REALPART (z
) + 0.5));
4332 /* d must be integer */
4335 scm_dbl2big (double d
)
4341 double u
= (d
< 0) ? -d
: d
;
4342 while (0 != floor (u
))
4347 ans
= scm_mkbig (i
, d
< 0);
4348 digits
= SCM_BDIGITS (ans
);
4356 #ifndef SCM_RECKLESS
4358 scm_num_overflow ("dbl2big");
4369 scm_sizet i
= SCM_NUMDIGS (b
);
4370 SCM_BIGDIG
*digits
= SCM_BDIGITS (b
);
4372 ans
= digits
[i
] + SCM_BIGRAD
* ans
;
4373 if (SCM_BIGSIGN (b
))
4381 scm_long2num (long sl
)
4383 if (!SCM_FIXABLE (sl
))
4386 return scm_long2big (sl
);
4388 return scm_makdbl ((double) sl
, 0.0);
4391 return SCM_MAKINUM (sl
);
4395 #ifdef HAVE_LONG_LONGS
4398 scm_long_long2num (long_long sl
)
4400 if (!SCM_FIXABLE (sl
))
4403 return scm_long_long2big (sl
);
4405 return scm_makdbl ((double) sl
, 0.0);
4408 return SCM_MAKINUM (sl
);
4415 scm_ulong2num (unsigned long sl
)
4417 if (!SCM_POSFIXABLE (sl
))
4420 return scm_ulong2big (sl
);
4422 return scm_makdbl ((double) sl
, 0.0);
4425 return SCM_MAKINUM (sl
);
4430 scm_num2long (SCM num
, char *pos
, const char *s_caller
)
4434 if (SCM_INUMP (num
))
4436 res
= SCM_INUM (num
);
4439 SCM_ASRTGO (SCM_NIMP (num
), wrong_type_arg
);
4440 if (SCM_SLOPPY_REALP (num
))
4442 volatile double u
= SCM_REALPART (num
);
4452 unsigned long oldres
= 0;
4454 /* can't use res directly in case num is -2^31. */
4455 unsigned long pos_res
= 0;
4457 for (l
= SCM_NUMDIGS (num
); l
--;)
4459 pos_res
= SCM_BIGUP (pos_res
) + SCM_BDIGITS (num
)[l
];
4460 /* check for overflow. */
4461 if (pos_res
< oldres
)
4465 if (SCM_BIGSIGN (num
))
4481 scm_wrong_type_arg (s_caller
, (int) pos
, num
);
4483 scm_out_of_range (s_caller
, num
);
4488 #ifdef HAVE_LONG_LONGS
4491 scm_num2long_long (SCM num
, char *pos
, const char *s_caller
)
4495 if (SCM_INUMP (num
))
4497 res
= SCM_INUM (num
);
4500 SCM_ASRTGO (SCM_NIMP (num
), wrong_type_arg
);
4501 if (SCM_SLOPPY_REALP (num
))
4503 double u
= SCM_REALPART (num
);
4506 if ((res
< 0 && u
> 0) || (res
> 0 && u
< 0)) /* check for overflow. */
4514 unsigned long long oldres
= 0;
4516 /* can't use res directly in case num is -2^63. */
4517 unsigned long long pos_res
= 0;
4519 for (l
= SCM_NUMDIGS (num
); l
--;)
4521 pos_res
= SCM_LONGLONGBIGUP (pos_res
) + SCM_BDIGITS (num
)[l
];
4522 /* check for overflow. */
4523 if (pos_res
< oldres
)
4527 if (SCM_BIGSIGN (num
))
4543 scm_wrong_type_arg (s_caller
, (int) pos
, num
);
4545 scm_out_of_range (s_caller
, num
);
4552 scm_num2ulong (SCM num
, char *pos
, const char *s_caller
)
4556 if (SCM_INUMP (num
))
4558 if (SCM_INUM (num
) < 0)
4560 res
= SCM_INUM (num
);
4563 SCM_ASRTGO (SCM_NIMP (num
), wrong_type_arg
);
4564 if (SCM_SLOPPY_REALP (num
))
4566 double u
= SCM_REALPART (num
);
4576 unsigned long oldres
= 0;
4580 for (l
= SCM_NUMDIGS (num
); l
--;)
4582 res
= SCM_BIGUP (res
) + SCM_BDIGITS (num
)[l
];
4591 scm_wrong_type_arg (s_caller
, (int) pos
, num
);
4593 scm_out_of_range (s_caller
, num
);
4599 add1 (double f
, double *fsum
)
4610 scm_add_feature ("complex");
4611 scm_add_feature ("inexact");
4612 SCM_NEWREAL (scm_flo0
, 0.0);
4614 scm_dblprec
= (DBL_DIG
> 20) ? 20 : DBL_DIG
;
4616 { /* determine floating point precision */
4618 double fsum
= 1.0 + f
;
4622 if (++scm_dblprec
> 20)
4626 scm_dblprec
= scm_dblprec
- 1;
4628 #endif /* DBL_DIG */
4629 #include "numbers.x"