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