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