arith04.c 23 KB

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