1 /* arith04.c Copyright (C) 1991-2008 Codemist Ltd */
2
3 /*
4 * Arithmetic functions.
5 * <, rationalize
6 *
7 */
8
9 /**************************************************************************
10 * Copyright (C) 2008, Codemist Ltd. A C Norman *
11 * *
12 * Redistribution and use in source and binary forms, with or without *
13 * modification, are permitted provided that the following conditions are *
14 * met: *
15 * *
16 * * Redistributions of source code must retain the relevant *
17 * copyright notice, this list of conditions and the following *
18 * disclaimer. *
19 * * Redistributions in binary form must reproduce the above *
20 * copyright notice, this list of conditions and the following *
21 * disclaimer in the documentation and/or other materials provided *
22 * with the distribution. *
23 * *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
28 * COPYRIGHT OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
31 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
32 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
33 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
34 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
35 * DAMAGE. *
36 *************************************************************************/
37
38
39
40 /* Signature: 3f8433df 22-Aug-2010 */
41
42 #include "headers.h"
43
44
45 #ifndef COMMON
46 /*
47 * In CSL mode I fudge make_ratio to be just cons, since it is ONLY
48 * needed for (rational ...)
49 */
50
51 #define make_ratio(a, b) cons(a, b)
52
53 #endif
54
make_n_word_bignum(int32_t a1,uint32_t a2,uint32_t a3,int32_t n)55 Lisp_Object make_n_word_bignum(int32_t a1, uint32_t a2, uint32_t a3, int32_t n)
56 /*
57 * This make a bignum with n words of data and digits a1, a2, a3 and
58 * then n zeros. Will only be called with n>=0 and a1, a2, a3 already
59 * correctly structured to make a valid bignum. NOTE that the number n
60 * as passed is the number of zero words to be inserted before the 3
61 * words at the end!
62 */
63 {
64 int32_t i;
65 Lisp_Object w = getvector(TAG_NUMBERS, TYPE_BIGNUM, CELL+4*n+12), nil;
66 errexit();
67 for (i=0; i<n; i++) bignum_digits(w)[i] = 0;
68 bignum_digits(w)[n] = a3;
69 bignum_digits(w)[n+1] = a2;
70 bignum_digits(w)[n+2] = a1;
71 if ((n & 1) != (SIXTY_FOUR_BIT ? 1 : 0)) bignum_digits(w)[n+3] = 0;
72 return w;
73 }
74
make_power_of_two(int32_t x)75 static Lisp_Object make_power_of_two(int32_t x)
76 /*
77 * Create the number 2^x where x is positive. Used to make the
78 * denominator of a rational representation of a float. Endless fun
79 * to cope with various small cases before I get to the general call
80 * to make_n_word_bignum.
81 */
82 {
83 if (x < 27) return fixnum_of_int(((int32_t)1) << x);
84 else if (x < 30) return make_one_word_bignum(((int32_t)1) << x);
85 else if (x == 30) return make_two_word_bignum(0, 0x40000000);
86 else if (x < 61) return make_two_word_bignum(((int32_t)1) << (x-31), 0);
87 else if ((x % 31) == 30)
88 return make_n_word_bignum(0, 0x40000000, 0, (x/31)-2);
89 else return make_n_word_bignum(((int32_t)1) << (x % 31), 0, 0, (x/31)-2);
90 }
91
make_fix_or_big2(int32_t a1,uint32_t a2)92 static Lisp_Object make_fix_or_big2(int32_t a1, uint32_t a2)
93 {
94 if ((a1==0 && (a2 & fix_mask)==0) ||
95 (a1==-1 && (a2 & 0x78000000)==0x78000000))
96 return fixnum_of_int(a2);
97 else if (a1==0 && (a2 & 0x40000000)==0)
98 return make_one_word_bignum(a2);
99 else if (a1==-1 && (a2 & 0x40000000)!=0)
100 return make_one_word_bignum(a2|~0x7fffffff);
101 else return make_two_word_bignum(a1, a2);
102 }
103
rationalf(double d)104 Lisp_Object rationalf(double d)
105 {
106 int x;
107 CSLbool negative = NO;
108 int32_t a0, a1;
109 uint32_t a2;
110 Lisp_Object nil;
111 if (d == 0.0) return fixnum_of_int(0);
112 if (d < 0.0) d = -d, negative = YES;
113 d = frexp(d, &x); /* 0.5 <= abs(d) < 1.0, x = the (binary) exponent */
114 /*
115 * The next line is not logically needed, provided frexp() is implemented to
116 * the relevant standard. However Zortech C release 3.0 used to get the output
117 * range for frexp() marginally out and the following line works around the
118 * resulting problem. I leave the code in (always) since its cost
119 * implications are minor and other libraries may suffer the same way, and it
120 * will be easier not to have to track the bug down from cold again!
121 */
122 if (d == 1.0) d = 0.5, x++;
123 d *= TWO_31;
124 a1 = (int32_t)d;
125 if (d < 0.0) a1--;
126 d -= (double)a1;
127 a2 = (uint32_t)(d * TWO_31);
128 /* Now I have the mantissa of the floating value packed into a1 and a2 */
129 x -= 62;
130 if (x < 0)
131 { Lisp_Object w;
132 /*
133 * Here the value may have a denominator, or it may be that it will turn
134 * out to be representable as an integer.
135 */
136 while ((a2 & 1) == 0 && x < 0)
137 { a2 = (a2 >> 1) | ((a1 & 1) << 30);
138 a1 = a1 >> 1;
139 #ifdef SIGNED_SHIFTS_ARE_LOGICAL
140 if (a1 & 0x40000000) a1 |= ~0x7fffffff;
141 #endif
142 x++;
143 if (x == 0)
144 { if (negative)
145 { if (a2 == 0) a1 = -a1;
146 else
147 { a2 = clear_top_bit(-(int32_t)a2);
148 a1 = ~a1;
149 }
150 }
151 return make_fix_or_big2(a1, a2);
152 }
153 }
154 if (negative)
155 { if (a2 == 0) a1 = -a1;
156 else
157 { a2 = clear_top_bit(-(int32_t)a2);
158 a1 = ~a1;
159 }
160 }
161 w = make_fix_or_big2(a1, a2);
162 errexit();
163 x = -x;
164 /*
165 * Remember: in CSL mode make_ratio is just cons
166 */
167 if (x < 27) return make_ratio(w, fixnum_of_int(((int32_t)1) << x));
168 else
169 { Lisp_Object d, nil;
170 push(w);
171 d = make_power_of_two(x);
172 pop(w);
173 errexit();
174 return make_ratio(w, d);
175 }
176 }
177 else
178 {
179 /*
180 * here the floating point value is quite large, and I need to create
181 * a multi-word bignum for it.
182 */
183 int x1;
184 if (negative)
185 { if (a2 == 0) a1 = -a1;
186 else
187 { a2 = clear_top_bit(-(int32_t)a2);
188 a1 = ~a1;
189 }
190 }
191 if (a1 < 0)
192 { a0 = -1;
193 a1 = clear_top_bit(a1);
194 }
195 else a0 = 0;
196 x1 = x / 31;
197 x = x % 31;
198 a0 = (a0 << x) | (a1 >> (31-x));
199 a1 = clear_top_bit(a1 << x) | (a2 >> (31-x));
200 a2 = clear_top_bit(a2 << x);
201 return make_n_word_bignum(a0, a1, a2, x1);
202 }
203 }
204
205 #ifdef COMMON
206
rationalizef(double d)207 static Lisp_Object rationalizef(double d)
208 /*
209 * This is expected to give a 'nice' rational approximation to the
210 * floating point value d.
211 */
212 {
213 double dd;
214 Lisp_Object p, q, nil;
215 if (d == 0.0) return fixnum_of_int(0);
216 else if (d < 0.0) dd = -d; else dd = d;
217 p = rationalf(dd);
218 errexit();
219 q = denominator(p);
220 p = numerator(p);
221 /* /* No cleaning up done, yet. Need to start to produce continued
222 * fraction for p/q and truncate it at some suitable point to get
223 * a sensible approximation. Since this is only needed in Common Lisp
224 * mode, and seems a bit specialist even then I am not going to rush into
225 * cobbling up the code (which I have done before and is basically OK,
226 * save that the stopping criteria are pretty delicate).
227 */
228 if (d < 0.0)
229 { p = negate(p);
230 errexit();
231 }
232 return make_ratio(p, q);
233 }
234
235 #endif
236
rational(Lisp_Object a)237 Lisp_Object rational(Lisp_Object a)
238 {
239 switch ((int)a & TAG_BITS)
240 {
241 case TAG_FIXNUM:
242 return a;
243 #ifdef COMMON
244 case TAG_SFLOAT:
245 { Float_union aa;
246 aa.i = a - TAG_SFLOAT;
247 return rationalf((double)aa.f);
248 }
249 #endif
250 case TAG_NUMBERS:
251 { int32_t ha = type_of_header(numhdr(a));
252 switch (ha)
253 {
254 case TYPE_BIGNUM:
255 #ifdef COMMON
256 case TYPE_RATNUM:
257 #endif
258 return a;
259 default:
260 return aerror1("bad arg for rational", a);
261 }
262 }
263 case TAG_BOXFLOAT:
264 return rationalf(float_of_number(a));
265 default:
266 return aerror1("bad arg for rational", a);
267 }
268 }
269
270 #ifdef COMMON
rationalize(Lisp_Object a)271 Lisp_Object rationalize(Lisp_Object a)
272 {
273 switch (a & TAG_BITS)
274 {
275 case TAG_FIXNUM:
276 return a;
277 #ifdef COMMON
278 case TAG_SFLOAT:
279 { Float_union aa;
280 aa.i = a - TAG_SFLOAT;
281 return rationalizef((double)aa.f);
282 }
283 #endif
284 case TAG_NUMBERS:
285 { int32_t ha = type_of_header(numhdr(a));
286 switch (ha)
287 {
288 case TYPE_BIGNUM:
289 #ifdef COMMON
290 case TYPE_RATNUM:
291 #endif
292 return a;
293 default:
294 return aerror1("bad arg for rationalize", a);
295 }
296 }
297 case TAG_BOXFLOAT:
298 return rationalizef(float_of_number(a));
299 default:
300 return aerror1("bad arg for rationalize", a);
301 }
302 }
303 #endif
304
305 /*
306 * Arithmetic comparison: lessp
307 */
308
309 #ifdef COMMON
lesspis(Lisp_Object a,Lisp_Object b)310 static CSLbool lesspis(Lisp_Object a, Lisp_Object b)
311 {
312 Float_union bb;
313 bb.i = b - TAG_SFLOAT;
314 /*
315 * Any fixnum can be converted to a float without introducing any
316 * error at all...
317 */
318 return (double)int_of_fixnum(a) < (double)bb.f;
319 }
320 #endif
321
lesspib(Lisp_Object a,Lisp_Object b)322 CSLbool lesspib(Lisp_Object a, Lisp_Object b)
323 /*
324 * a fixnum and a bignum can never be equal, and the magnitude of
325 * the bignum must be at least as great as that of the fixnum, hence
326 * to do a comparison I just need to look at sign of the bignum.
327 */
328 {
329 int32_t len = bignum_length(b);
330 int32_t msd = bignum_digits(b)[(len-CELL-4)/4];
331 CSL_IGNORE(a);
332 return (msd >= 0);
333 }
334
335 #ifdef COMMON
lesspir(Lisp_Object a,Lisp_Object b)336 static CSLbool lesspir(Lisp_Object a, Lisp_Object b)
337 {
338 /*
339 * compute a < p/q as a*q < p
340 */
341 push(numerator(b));
342 a = times2(a, denominator(b));
343 pop(b);
344 return lessp2(a, b);
345 }
346 #endif
347
348 #define lesspif(a, b) ((double)int_of_fixnum(a) < float_of_number(b))
349
lesspdb(double a,Lisp_Object b)350 CSLbool lesspdb(double a, Lisp_Object b)
351 /*
352 * a is a floating point number and b a bignum. Compare them.
353 */
354 {
355 int32_t n = (bignum_length(b)-CELL-4)/4;
356 int32_t bn = (int32_t)bignum_digits(b)[n];
357 /*
358 * The value represented by b can not be in the range that fixnums
359 * cover, so if a is in that range I need only inspect the sign of b.
360 */
361 if ((double)(-0x08000000) <= a &&
362 a <= (double)(0x7fffffff))
363 return (bn >= 0);
364 /*
365 * If b is a one-word bignum I can convert it to floating point
366 * with no loss of accuracy at all.
367 */
368 if (n == 0) return a < (double)bn;
369 /*
370 * For two-digit bignums I first check if the float is so big that I can
371 * tell that it dominames the bignum, and if not I subtract the top digit
372 * of the bignum from both sides... in the critical case where the two
373 * values are almost the same that subtraction will not lead to loss of
374 * accuracy (at least provided that my floating point was implemented
375 * with a guard bit..)
376 */
377 if (n == 1)
378 { if (1.0e19 < a) return NO;
379 else if (a < -1.0e19) return YES;
380 a -= TWO_31*(int32_t)bn;
381 return a < (double)bignum_digits(b)[0];
382 }
383 /*
384 * If the two operands differ in their signs then all is easy.
385 */
386 if (bn >= 0 && a < 0.0) return YES;
387 if (bn < 0 && a >= 0.0) return NO;
388 /*
389 * Now I have a 3 or more digit bignum, so here I will (in effect)
390 * convert the float to a bignum and then perform the comparison.. that
391 * does the best I can to avoid error. I do not actually have to create
392 * a datastructure for the bignum provided I can collect up the data that
393 * would have to be stored in it. See lisp_fix (arith8.c) for related code.
394 */
395 { int32_t a0, a1, a2;
396 int x, x1;
397 a = frexp(a, &x); /* 0.5 <= abs(a) < 1.0, x = (binary) exponent */
398 if (a == 1.0) a = 0.5, x++; /* For Zortech */
399 a *= TWO_31;
400 a1 = (int32_t)a; /* 2^31 > |a| >= 2^30 */
401 if (a < 0.0) a1--; /* now maybe a1 is -2^31 */
402 a -= (double)a1;
403 a2 = (uint32_t)(a * TWO_31); /* This conversion should be exact */
404 x -= 62;
405 /*
406 * If the float is smaller in absolute value than the bignum life is easy
407 */
408 if (x < 0) return (bn >= 0);
409 x1 = x/31 + 2;
410 if (n != x1)
411 { if (n < x1) return a < 0.0;
412 else return (bn >= 0);
413 }
414 /*
415 * Now the most jolly bit - the two numbers have the same sign and involve
416 * the same number of digits.
417 */
418 if (a1 < 0)
419 { a0 = -1;
420 a1 = clear_top_bit(a1);
421 }
422 else a0 = 0;
423 x = x % 31;
424 a0 = (a0 << x) | (a1 >> (31-x));
425 a1 = clear_top_bit(a1 << x) | (a2 >> (31-x));
426 a2 = clear_top_bit(a2 << x);
427 if (a0 != bn) return a0 < bn;
428 bn = bignum_digits(b)[n-1];
429 if (a1 != bn) return a1 < bn;
430 return a2 < (int32_t)bignum_digits(b)[n-2];
431 }
432 }
433
lesspbd(Lisp_Object b,double a)434 CSLbool lesspbd(Lisp_Object b, double a)
435 /*
436 * Code as for lesspdb, but use '>' test instead of '<'
437 */
438 {
439 int32_t n = (bignum_length(b)-CELL-4)/4;
440 int32_t bn = (int32_t)bignum_digits(b)[n];
441 /*
442 * The value represented by b can not be in the range that fixnums
443 * cover, so if a is in that range I need only inspect the sign of b.
444 */
445 if ((double)(-0x08000000) <= a &&
446 a <= (double)(0x7fffffff))
447 return (bn < 0);
448 /*
449 * If b is a one-word bignum I can convert it to floating point
450 * with no loss of accuracy at all.
451 */
452 if (n == 0) return (double)bn < a;
453 /*
454 * For two-digit bignums I first check if the float is so big that I can
455 * tell that it dominates the bignum, and if not I subtract the top digit
456 * of the bignum from both sides... in the critical case where the two
457 * values are almost the same that subtraction will not lead to loss of
458 * accuracy (at least provided that my floating point was implemented
459 * with a guard bit..)
460 */
461 if (n == 1)
462 { if (1.0e19 < a) return YES;
463 else if (a < -1.0e19) return NO;
464 a -= TWO_31 * (double)bn;
465 return (double)bignum_digits(b)[0] < a;
466 }
467 /*
468 * If the two operands differ in their signs then all is easy.
469 */
470 if (bn >= 0 && a < 0.0) return NO;
471 if (bn < 0 && a >= 0.0) return YES;
472 /*
473 * Now I have a 3 or more digit bignum, so here I will (in effect)
474 * convert the float to a bignum and then perform the comparison.. that
475 * does the best I can to avoid error. I do not actually have to create
476 * a datastructure for the bignum provided I can collect up the data that
477 * would have to be stored in it. See lisp_fix (arith8.c) for related code.
478 */
479 { int32_t a0, a1, a2;
480 int x, x1;
481 a = frexp(a, &x); /* 0.5 <= abs(a) < 1.0, x = (binary) exponent */
482 if (a == 1.0) a = 0.5, x++;
483 a *= TWO_31;
484 a1 = (int32_t)a; /* 2^31 > |a| >= 2^30 */
485 if (a < 0.0) a1--; /* now maybe a1 is -2^31 */
486 a -= (double)a1;
487 a2 = (uint32_t)(a * TWO_31); /* This conversion should be exact */
488 x -= 62;
489 /*
490 * If the float is smaller in absolute value than the bignum life is easy
491 */
492 if (x < 0) return (bn < 0);
493 x1 = x/31 + 2;
494 if (n != x1)
495 { if (n < x1) return a >= 0.0;
496 else return (bn < 0);
497 }
498 /*
499 * Now the most jolly bit - the two numbers have the same sign and involve
500 * the same number of digits.
501 */
502 if (a1 < 0)
503 { a0 = -1;
504 a1 = clear_top_bit(a1);
505 }
506 else a0 = 0;
507 x = x % 31;
508 a0 = (a0 << x) | (a1 >> (31-x));
509 a1 = clear_top_bit(a1 << x) | (a2 >> (31-x));
510 a2 = clear_top_bit(a2 << x);
511 if (a0 != bn) return a0 > bn;
512 bn = bignum_digits(b)[n-1];
513 if (a1 != bn) return a1 > bn;
514 return a2 > (int32_t)bignum_digits(b)[n-2];
515 }
516 }
517
518 #ifdef COMMON
519
lessprr(Lisp_Object a,Lisp_Object b)520 static CSLbool lessprr(Lisp_Object a, Lisp_Object b)
521 {
522 Lisp_Object c;
523 push2(a, b);
524 c = times2(numerator(a), denominator(b));
525 pop2(b, a);
526 push(c);
527 b = times2(numerator(b), denominator(a));
528 pop(c);
529 return lessp2(c, b);
530 }
531
lesspdr(double a,Lisp_Object b)532 CSLbool lesspdr(double a, Lisp_Object b)
533 /*
534 * Compare float with ratio... painfully expensive.
535 */
536 {
537 Lisp_Object a1 = rationalf(a), nil;
538 errexit();
539 return lessprr(a1, b);
540 }
541
lessprd(Lisp_Object a,double b)542 CSLbool lessprd(Lisp_Object a, double b)
543 /*
544 * Compare float with ratio.
545 */
546 {
547 Lisp_Object b1 = rationalf(b), nil;
548 errexit();
549 return lessprr(a, b1);
550 }
551
lesspsi(Lisp_Object a,Lisp_Object b)552 static CSLbool lesspsi(Lisp_Object a, Lisp_Object b)
553 {
554 Float_union aa;
555 aa.i = a - TAG_SFLOAT;
556 return (double)aa.f < (double)int_of_fixnum(b);
557 }
558
lesspsb(Lisp_Object a,Lisp_Object b)559 static CSLbool lesspsb(Lisp_Object a, Lisp_Object b)
560 {
561 Float_union aa;
562 aa.i = a - TAG_SFLOAT;
563 return lesspdb((double)aa.f, b);
564 }
565
lesspsr(Lisp_Object a,Lisp_Object b)566 static CSLbool lesspsr(Lisp_Object a, Lisp_Object b)
567 {
568 Float_union aa;
569 aa.i = a - TAG_SFLOAT;
570 return lesspdr((double)aa.f, b);
571 }
572
lesspsf(Lisp_Object a,Lisp_Object b)573 static CSLbool lesspsf(Lisp_Object a, Lisp_Object b)
574 {
575 Float_union aa;
576 aa.i = a - TAG_SFLOAT;
577 return (double)aa.f < float_of_number(b);
578 }
579 #endif
580
lesspbi(Lisp_Object a,Lisp_Object b)581 CSLbool lesspbi(Lisp_Object a, Lisp_Object b)
582 {
583 int32_t len = bignum_length(a);
584 int32_t msd = bignum_digits(a)[(len-CELL-4)/4];
585 CSL_IGNORE(b);
586 return (msd < 0);
587 }
588
589 #ifdef COMMON
lesspbs(Lisp_Object a,Lisp_Object b)590 static CSLbool lesspbs(Lisp_Object a, Lisp_Object b)
591 {
592 Float_union bb;
593 bb.i = b - TAG_SFLOAT;
594 return lesspbd(a, (double)bb.f);
595 }
596 #endif
597
lesspbb(Lisp_Object a,Lisp_Object b)598 static CSLbool lesspbb(Lisp_Object a, Lisp_Object b)
599 {
600 int32_t lena = bignum_length(a),
601 lenb = bignum_length(b);
602 if (lena > lenb)
603 { int32_t msd = bignum_digits(a)[(lena-CELL-4)/4];
604 return (msd < 0);
605 }
606 else if (lenb > lena)
607 { int32_t msd = bignum_digits(b)[(lenb-CELL-4)/4];
608 return (msd >= 0);
609 }
610 lena = (lena-CELL-4)/4;
611 /* lenb == lena here */
612 { int32_t msa = bignum_digits(a)[lena],
613 msb = bignum_digits(b)[lena];
614 if (msa < msb) return YES;
615 else if (msa > msb) return NO;
616 /*
617 * Now the leading digits of the numbers agree, so in particular the numbers
618 * have the same sign.
619 */
620 while (--lena >= 0)
621 { uint32_t da = bignum_digits(a)[lena],
622 db = bignum_digits(b)[lena];
623 if (da == db) continue;
624 return (da < db);
625 }
626 return NO; /* numbers are the same */
627 }
628 }
629
630 #define lesspbr(a, b) lesspir(a, b)
631
632 #define lesspbf(a, b) lesspbd(a, float_of_number(b))
633
634 #ifdef COMMON
635
lesspri(Lisp_Object a,Lisp_Object b)636 static CSLbool lesspri(Lisp_Object a, Lisp_Object b)
637 {
638 push(numerator(a));
639 b = times2(b, denominator(a));
640 pop(a);
641 return lessp2(a, b);
642 }
643
lessprs(Lisp_Object a,Lisp_Object b)644 static CSLbool lessprs(Lisp_Object a, Lisp_Object b)
645 {
646 Float_union bb;
647 bb.i = b - TAG_SFLOAT;
648 return lessprd(a, (double)bb.f);
649 }
650
651 #define lessprb(a, b) lesspri(a, b)
652
653 #define lessprf(a, b) lessprd(a, float_of_number(b))
654
655 #endif
656
657 #define lesspfi(a, b) (float_of_number(a) < (double)int_of_fixnum(b))
658
659 #ifdef COMMON
lesspfs(Lisp_Object a,Lisp_Object b)660 static CSLbool lesspfs(Lisp_Object a, Lisp_Object b)
661 {
662 Float_union bb;
663 bb.i = b - TAG_SFLOAT;
664 return float_of_number(a) < (double)bb.f;
665 }
666 #endif
667
668 #define lesspfb(a, b) lesspdb(float_of_number(a), b)
669
670 #define lesspfr(a, b) lesspfb(a, b)
671
672 #define lesspff(a, b) (float_of_number(a) < float_of_number(b))
673
674
greaterp2(Lisp_Object a,Lisp_Object b)675 CSLbool greaterp2(Lisp_Object a, Lisp_Object b)
676 {
677 return lessp2(b, a);
678 }
679
lessp2(Lisp_Object a,Lisp_Object b)680 CSLbool lessp2(Lisp_Object a, Lisp_Object b)
681 /*
682 * Note that this type-dispatch does not permit complex numbers to
683 * be compared - their presence will lead to an exception being raised.
684 * This shortens the code (marginally).
685 */
686 {
687 Lisp_Object nil = C_nil;
688 if (exception_pending()) return NO;
689 switch ((int)a & TAG_BITS)
690 {
691 case TAG_FIXNUM:
692 switch ((int)b & TAG_BITS)
693 {
694 case TAG_FIXNUM:
695 /* For fixnums the comparison happens directly */
696 return ((int32_t)a < (int32_t)b);
697 #ifdef COMMON
698 case TAG_SFLOAT:
699 return lesspis(a, b);
700 #endif
701 case TAG_NUMBERS:
702 { int32_t hb = type_of_header(numhdr(b));
703 switch (hb)
704 {
705 case TYPE_BIGNUM:
706 return lesspib(a, b);
707 #ifdef COMMON
708 case TYPE_RATNUM:
709 return lesspir(a, b);
710 #endif
711 default:
712 return (CSLbool)aerror2("bad arg for lessp", a, b);
713 }
714 }
715 case TAG_BOXFLOAT:
716 return lesspif(a, b);
717 default:
718 return (CSLbool)aerror2("bad arg for lessp", a, b);
719 }
720 #ifdef COMMON
721 case TAG_SFLOAT:
722 switch (b & TAG_BITS)
723 {
724 case TAG_FIXNUM:
725 return lesspsi(a, b);
726 case TAG_SFLOAT:
727 { Float_union aa, bb;
728 aa.i = a - TAG_SFLOAT;
729 bb.i = b - TAG_SFLOAT;
730 return (aa.f < bb.f);
731 }
732 case TAG_NUMBERS:
733 { int32_t hb = type_of_header(numhdr(b));
734 switch (hb)
735 {
736 case TYPE_BIGNUM:
737 return lesspsb(a, b);
738 case TYPE_RATNUM:
739 return lesspsr(a, b);
740 default:
741 return (CSLbool)aerror2("bad arg for lessp", a, b);
742 }
743 }
744 case TAG_BOXFLOAT:
745 return lesspsf(a, b);
746 default:
747 return (CSLbool)aerror2("bad arg for lessp", a, b);
748 }
749 #endif
750 case TAG_NUMBERS:
751 { int32_t ha = type_of_header(numhdr(a));
752 switch (ha)
753 {
754 case TYPE_BIGNUM:
755 switch ((int)b & TAG_BITS)
756 {
757 case TAG_FIXNUM:
758 return lesspbi(a, b);
759 #ifdef COMMON
760 case TAG_SFLOAT:
761 return lesspbs(a, b);
762 #endif
763 case TAG_NUMBERS:
764 { int32_t hb = type_of_header(numhdr(b));
765 switch (hb)
766 {
767 case TYPE_BIGNUM:
768 return lesspbb(a, b);
769 #ifdef COMMON
770 case TYPE_RATNUM:
771 return lesspbr(a, b);
772 #endif
773 default:
774 return (CSLbool)aerror2("bad arg for lessp", a, b);
775 }
776 }
777 case TAG_BOXFLOAT:
778 return lesspbf(a, b);
779 default:
780 return (CSLbool)aerror2("bad arg for lessp", a, b);
781 }
782 #ifdef COMMON
783 case TYPE_RATNUM:
784 switch (b & TAG_BITS)
785 {
786 case TAG_FIXNUM:
787 return lesspri(a, b);
788 case TAG_SFLOAT:
789 return lessprs(a, b);
790 case TAG_NUMBERS:
791 { int32_t hb = type_of_header(numhdr(b));
792 switch (hb)
793 {
794 case TYPE_BIGNUM:
795 return lessprb(a, b);
796 case TYPE_RATNUM:
797 return lessprr(a, b);
798 default:
799 return (CSLbool)aerror2("bad arg for lessp", a, b);
800 }
801 }
802 case TAG_BOXFLOAT:
803 return lessprf(a, b);
804 default:
805 return (CSLbool)aerror2("bad arg for lessp", a, b);
806 }
807 #endif
808 default: return (CSLbool)aerror2("bad arg for lessp", a, b);
809 }
810 }
811 case TAG_BOXFLOAT:
812 switch ((int)b & TAG_BITS)
813 {
814 case TAG_FIXNUM:
815 return lesspfi(a, b);
816 #ifdef COMMON
817 case TAG_SFLOAT:
818 return lesspfs(a, b);
819 #endif
820 case TAG_NUMBERS:
821 { int32_t hb = type_of_header(numhdr(b));
822 switch (hb)
823 {
824 case TYPE_BIGNUM:
825 return lesspfb(a, b);
826 #ifdef COMMON
827 case TYPE_RATNUM:
828 return lesspfr(a, b);
829 #endif
830 default:
831 return (CSLbool)aerror2("bad arg for lessp", a, b);
832 }
833 }
834 case TAG_BOXFLOAT:
835 return lesspff(a, b);
836 default:
837 return (CSLbool)aerror2("bad arg for lessp", a, b);
838 }
839 default:
840 return (CSLbool)aerror2("bad arg for lessp", a, b);
841 }
842 }
843
844 /* end of arith04.c */
845