arith05.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /* arith05.c Copyright (C) 1990-2002 Codemist Ltd */
  2. /*
  3. * Arithmetic functions.
  4. * low-level 64/32 bit arithmetic, <=, print_bignum
  5. */
  6. /*
  7. * This code may be used and modified, and redistributed in binary
  8. * or source form, subject to the "CCL Public License", which should
  9. * accompany it. This license is a variant on the BSD license, and thus
  10. * permits use of code derived from this in either open and commercial
  11. * projects: but it does require that updates to this code be made
  12. * available back to the originators of the package.
  13. * Before merging other code in with this or linking this code
  14. * with other packages or libraries please check that the license terms
  15. * of the other material are compatible with those of this.
  16. */
  17. /* Signature: 6d01f96b 10-Oct-2002 */
  18. #include <stdarg.h>
  19. #include <string.h>
  20. #include <ctype.h>
  21. #include <math.h>
  22. #include "machine.h"
  23. #include "tags.h"
  24. #include "cslerror.h"
  25. #include "externs.h"
  26. #include "arith.h"
  27. #include "stream.h"
  28. #ifdef TIMEOUT
  29. #include "timeout.h"
  30. #endif
  31. /*
  32. * I provide symbols IMULTIPLY and IDIVIDE which can be asserted if the
  33. * corresponding routines have been provided elsewhere (e.g. in machine
  34. * code for extra speed)
  35. */
  36. #ifndef IDIVIDE
  37. #ifdef MULDIV64
  38. unsigned32 Idiv10_9(unsigned32 *qp, unsigned32 high, unsigned32 low)
  39. /*
  40. * Same behaviour as Idivide(qp, high, low, 1000000000U).
  41. * Used for printing only - i.e. only in this file
  42. */
  43. {
  44. unsigned64 p = ((unsigned64)high << 31) | (unsigned64)low;
  45. *qp = (unsigned32)(p / (unsigned64)1000000000U);
  46. return (unsigned32)(p % (unsigned64)1000000000U);
  47. }
  48. #else
  49. unsigned32 Idiv10_9(unsigned32 *qp, unsigned32 high, unsigned32 low)
  50. /*
  51. * Same behaviour as Idivide(qp, high, low, 1000000000U).
  52. * If Idivide is coded in assembler then this will probably be
  53. * easy and sensible to implement as an alternative entrypoint.
  54. * The code given here is intended for use on computers where
  55. * division is a slow operation - it works by a sort of long
  56. * division, forming guessed for the partial quotients my
  57. * multiplying by a (binary scaled) reciprocal of 1000000000.
  58. *
  59. * Used for printing only - i.e. only in this file
  60. */
  61. {
  62. #define RECIP_10_9 70368U /* 2^46/10^9 */
  63. #define TEN_9_16H 15258U
  64. /*
  65. * The APOLLO conditionalisation is a work-round for a bug present
  66. * July 1992 in at least some versions of the APOLLO C compiler, whereby
  67. * multiplication by 51712 was treated as multiplication by
  68. * (65536-51712). Putting the constant in a variable is a temporary
  69. * patch and will be removed as soon as we hear reports of a newer
  70. * and mended Apollo C compiler!
  71. */
  72. #ifdef __APOLLO__
  73. static unsigned32 TEN_9_16L = 51712U;
  74. #else
  75. #define TEN_9_16L 51712U /* 10^9 in 2 chunks, base 2^16 */
  76. #endif
  77. #define TEN_9_15H 30517U
  78. #define TEN_9_15L 18944U /* 10^9 in 2 chunks, base 2^15 */
  79. unsigned32 w = ((high >> 14) * RECIP_10_9) >> 16;
  80. /*
  81. * The above line sets w to the first partial quotient. Multiply
  82. * it back up by 10^9 (working base 2^16 while so doing) and subtract
  83. * that off from the original number to get a residue.
  84. */
  85. unsigned32 w1 = w * TEN_9_16L, w2, w3, w4, w5;
  86. w2 = w1 >> 16;
  87. high -= (w * TEN_9_16H + w2);
  88. low -= ((w1 << 15) & 0x7fffffff);
  89. if ((int32)low < 0)
  90. { high--;
  91. low &= 0x7fffffff;
  92. }
  93. /*
  94. * Now do the same sort of operation again to get the next
  95. * part of the quotient.
  96. */
  97. w3 = (high * RECIP_10_9) >> 15;
  98. /*
  99. * when I multiply back up by 10^9 and subtract off I need to use
  100. * all the bits that there are in my 32-bit words, and it seems to
  101. * turn out that working base 2^15 rather than 2^16 here is best.
  102. */
  103. w4 = w3 * TEN_9_15H;
  104. w5 = w4 >> 16;
  105. high -= w5;
  106. w4 -= (w5 << 16);
  107. low -= (w3 * TEN_9_15L);
  108. if ((int32)low < 0)
  109. { high--; /* propage a borrow */
  110. low &= 0x7fffffff;
  111. }
  112. low -= (w4 << 15);
  113. if ((int32)low < 0)
  114. { high--; /* propagate another borrow */
  115. low &= 0x7fffffff;
  116. }
  117. /*
  118. * The quotient that I compute here is almost correct - I will
  119. * adjust it by 1, 2, 3 or 4..
  120. */
  121. w = (w << 15) + w3;
  122. /*
  123. * If high was nonzero I subtract (2*high*10^9) from low, and need not
  124. * consider high again.
  125. */
  126. if (high != 0)
  127. { low -= (2000000000U + 0x80000000U);
  128. w += 2;
  129. if (high != 1)
  130. { low -= (2000000000U + 0x80000000U);
  131. w += 2;
  132. }
  133. }
  134. /*
  135. * final adjustment..
  136. */
  137. if (low >= 1000000000U)
  138. { low -= 1000000000U;
  139. w += 1;
  140. if (low >= 1000000000U)
  141. { low -= 1000000000U;
  142. w += 1;
  143. }
  144. }
  145. *qp = w;
  146. return low;
  147. }
  148. #endif
  149. #endif /* IDIVIDE */
  150. /*
  151. * Arithmetic comparison: lesseq
  152. * Note that for floating point values on a system which supports
  153. * IEEE arithmetic (and in particular Nans) it may not be the case
  154. * that (a < b) = !(b <= a). Note also Common Lisp requires that
  155. * floating point values get widened to ratios in many cases here,
  156. * despite the vast cost thereof.
  157. */
  158. #ifdef COMMON
  159. static CSLbool lesseqis(Lisp_Object a, Lisp_Object b)
  160. {
  161. Float_union bb;
  162. bb.i = b - TAG_SFLOAT;
  163. return (double)int_of_fixnum(a) <= (double)bb.f;
  164. }
  165. #endif
  166. #define lesseqib(a, b) lesspib(a, b)
  167. #ifdef COMMON
  168. static CSLbool lesseqir(Lisp_Object a, Lisp_Object b)
  169. {
  170. /*
  171. * compute a <= p/q as a*q <= p
  172. */
  173. push(numerator(b));
  174. a = times2(a, denominator(b));
  175. pop(b);
  176. return lesseq2(a, b);
  177. }
  178. #endif
  179. #define lesseqif(a, b) ((double)int_of_fixnum(a) <= float_of_number(b))
  180. #ifdef COMMON
  181. static CSLbool lesseqsi(Lisp_Object a, Lisp_Object b)
  182. {
  183. Float_union aa;
  184. aa.i = a - TAG_SFLOAT;
  185. return (double)aa.f <= (double)int_of_fixnum(b);
  186. }
  187. static CSLbool lesseqsb(Lisp_Object a, Lisp_Object b)
  188. {
  189. Float_union aa;
  190. aa.i = a - TAG_SFLOAT;
  191. return !lesspbd(b, (double)aa.f);
  192. }
  193. static CSLbool lesseqsr(Lisp_Object a, Lisp_Object b)
  194. {
  195. Float_union aa;
  196. aa.i = a - TAG_SFLOAT;
  197. return !lessprd(b, (double)aa.f);
  198. }
  199. static CSLbool lesseqsf(Lisp_Object a, Lisp_Object b)
  200. {
  201. Float_union aa;
  202. aa.i = a - TAG_SFLOAT;
  203. return (double)aa.f <= float_of_number(b);
  204. }
  205. #endif
  206. #define lesseqbi(a, b) lesspbi(a, b)
  207. #ifdef COMMON
  208. static CSLbool lesseqbs(Lisp_Object a, Lisp_Object b)
  209. {
  210. Float_union bb;
  211. bb.i = b - TAG_SFLOAT;
  212. return !lesspdb((double)bb.f, a);
  213. }
  214. #endif
  215. static CSLbool lesseqbb(Lisp_Object a, Lisp_Object b)
  216. {
  217. int32 lena = bignum_length(a),
  218. lenb = bignum_length(b);
  219. if (lena > lenb)
  220. { int32 msd = bignum_digits(a)[(lena-CELL-4)/4];
  221. return (msd < 0);
  222. }
  223. else if (lenb > lena)
  224. { int32 msd = bignum_digits(b)[(lenb-CELL-4)/4];
  225. return (msd >= 0);
  226. }
  227. lena = (lena-CELL-4)/4;
  228. /* lenb == lena here */
  229. { int32 msa = bignum_digits(a)[lena],
  230. msb = bignum_digits(b)[lena];
  231. if (msa < msb) return YES;
  232. else if (msa > msb) return NO;
  233. /*
  234. * Now the leading digits of the numbers agree, so in particular the numbers
  235. * have the same sign.
  236. */
  237. while (--lena >= 0)
  238. { unsigned32 da = bignum_digits(a)[lena],
  239. db = bignum_digits(b)[lena];
  240. if (da == db) continue;
  241. return (da < db);
  242. }
  243. return YES; /* numbers are the same */
  244. }
  245. }
  246. #define lesseqbr(a, b) lesseqir(a, b)
  247. #define lesseqbf(a, b) (!lesspdb(float_of_number(b), a))
  248. #ifdef COMMON
  249. static CSLbool lesseqri(Lisp_Object a, Lisp_Object b)
  250. {
  251. push(numerator(a));
  252. b = times2(b, denominator(a));
  253. pop(a);
  254. return lesseq2(a, b);
  255. }
  256. static CSLbool lesseqrs(Lisp_Object a, Lisp_Object b)
  257. {
  258. Float_union bb;
  259. bb.i = b - TAG_SFLOAT;
  260. return !lesspdr((double)bb.f, a);
  261. }
  262. #define lesseqrb(a, b) lesseqri(a, b)
  263. static CSLbool lesseqrr(Lisp_Object a, Lisp_Object b)
  264. {
  265. Lisp_Object c;
  266. push2(a, b);
  267. c = times2(numerator(a), denominator(b));
  268. pop2(b, a);
  269. push(c);
  270. b = times2(numerator(b), denominator(a));
  271. pop(c);
  272. return lesseq2(c, b);
  273. }
  274. #define lesseqrf(a, b) (!lesspdr(float_of_number(b), a))
  275. #endif
  276. #define lesseqfi(a, b) (float_of_number(a) <= (double)int_of_fixnum(b))
  277. #ifdef COMMON
  278. static CSLbool lesseqfs(Lisp_Object a, Lisp_Object b)
  279. {
  280. Float_union bb;
  281. bb.i = b - TAG_SFLOAT;
  282. return float_of_number(a) <= (double)bb.f;
  283. }
  284. #endif
  285. #define lesseqfb(a, b) (!lesspbd(b, float_of_number(a)))
  286. #define lesseqfr(a, b) (!lessprd(b, float_of_number(a)))
  287. #define lesseqff(a, b) (float_of_number(a) <= float_of_number(b))
  288. CSLbool geq2(Lisp_Object a, Lisp_Object b)
  289. {
  290. return lesseq2(b, a);
  291. }
  292. CSLbool lesseq2(Lisp_Object a, Lisp_Object b)
  293. {
  294. Lisp_Object nil = C_nil;
  295. if (exception_pending()) return NO;
  296. switch ((int)a & TAG_BITS)
  297. {
  298. case TAG_FIXNUM:
  299. switch ((int)b & TAG_BITS)
  300. {
  301. case TAG_FIXNUM:
  302. /* For fixnums the comparison can be done directly */
  303. return ((int32)a <= (int32)b);
  304. #ifdef COMMON
  305. case TAG_SFLOAT:
  306. return lesseqis(a, b);
  307. #endif
  308. case TAG_NUMBERS:
  309. { int32 hb = type_of_header(numhdr(b));
  310. switch (hb)
  311. {
  312. case TYPE_BIGNUM:
  313. return lesseqib(a, b);
  314. #ifdef COMMON
  315. case TYPE_RATNUM:
  316. return lesseqir(a, b);
  317. #endif
  318. default:
  319. return (CSLbool)aerror2("bad arg for leq", a, b);
  320. }
  321. }
  322. case TAG_BOXFLOAT:
  323. return lesseqif(a, b);
  324. default:
  325. return (CSLbool)aerror2("bad arg for leq", a, b);
  326. }
  327. #ifdef COMMON
  328. case TAG_SFLOAT:
  329. switch (b & TAG_BITS)
  330. {
  331. case TAG_FIXNUM:
  332. return lesseqsi(a, b);
  333. case TAG_SFLOAT:
  334. { Float_union aa, bb;
  335. aa.i = a - TAG_SFLOAT;
  336. bb.i = b - TAG_SFLOAT;
  337. return (aa.f <= bb.f);
  338. }
  339. case TAG_NUMBERS:
  340. { int32 hb = type_of_header(numhdr(b));
  341. switch (hb)
  342. {
  343. case TYPE_BIGNUM:
  344. return lesseqsb(a, b);
  345. case TYPE_RATNUM:
  346. return lesseqsr(a, b);
  347. default:
  348. return (CSLbool)aerror2("bad arg for leq", a, b);
  349. }
  350. }
  351. case TAG_BOXFLOAT:
  352. return lesseqsf(a, b);
  353. default:
  354. return (CSLbool)aerror2("bad arg for leq", a, b);
  355. }
  356. #endif
  357. case TAG_NUMBERS:
  358. { int32 ha = type_of_header(numhdr(a));
  359. switch (ha)
  360. {
  361. case TYPE_BIGNUM:
  362. switch ((int)b & TAG_BITS)
  363. {
  364. case TAG_FIXNUM:
  365. return lesseqbi(a, b);
  366. #ifdef COMMON
  367. case TAG_SFLOAT:
  368. return lesseqbs(a, b);
  369. #endif
  370. case TAG_NUMBERS:
  371. { int32 hb = type_of_header(numhdr(b));
  372. switch (hb)
  373. {
  374. case TYPE_BIGNUM:
  375. return lesseqbb(a, b);
  376. #ifdef COMMON
  377. case TYPE_RATNUM:
  378. return lesseqbr(a, b);
  379. #endif
  380. default:
  381. return (CSLbool)aerror2("bad arg for leq", a, b);
  382. }
  383. }
  384. case TAG_BOXFLOAT:
  385. return lesseqbf(a, b);
  386. default:
  387. return (CSLbool)aerror2("bad arg for leq", a, b);
  388. }
  389. #ifdef COMMON
  390. case TYPE_RATNUM:
  391. switch (b & TAG_BITS)
  392. {
  393. case TAG_FIXNUM:
  394. return lesseqri(a, b);
  395. case TAG_SFLOAT:
  396. return lesseqrs(a, b);
  397. case TAG_NUMBERS:
  398. { int32 hb = type_of_header(numhdr(b));
  399. switch (hb)
  400. {
  401. case TYPE_BIGNUM:
  402. return lesseqrb(a, b);
  403. case TYPE_RATNUM:
  404. return lesseqrr(a, b);
  405. default:
  406. return (CSLbool)aerror2("bad arg for leq", a, b);
  407. }
  408. }
  409. case TAG_BOXFLOAT:
  410. return lesseqrf(a, b);
  411. default:
  412. return (CSLbool)aerror2("bad arg for leq", a, b);
  413. }
  414. #endif
  415. default: return (CSLbool)aerror2("bad arg for leq", a, b);
  416. }
  417. }
  418. case TAG_BOXFLOAT:
  419. switch ((int)b & TAG_BITS)
  420. {
  421. case TAG_FIXNUM:
  422. return lesseqfi(a, b);
  423. #ifdef COMMON
  424. case TAG_SFLOAT:
  425. return lesseqfs(a, b);
  426. #endif
  427. case TAG_NUMBERS:
  428. { int32 hb = type_of_header(numhdr(b));
  429. switch (hb)
  430. {
  431. case TYPE_BIGNUM:
  432. return lesseqfb(a, b);
  433. #ifdef COMMON
  434. case TYPE_RATNUM:
  435. return lesseqfr(a, b);
  436. #endif
  437. default:
  438. return (CSLbool)aerror2("bad arg for leq", a, b);
  439. }
  440. }
  441. case TAG_BOXFLOAT:
  442. return lesseqff(a, b);
  443. default:
  444. return (CSLbool)aerror2("bad arg for leq", a, b);
  445. }
  446. default:
  447. return (CSLbool)aerror2("bad arg for leq", a, b);
  448. }
  449. }
  450. void print_bignum(Lisp_Object u, CSLbool blankp, int nobreak)
  451. {
  452. int32 len = length_of_header(numhdr(u))-CELL;
  453. int32 i, len1;
  454. Lisp_Object w, nil = C_nil;
  455. char my_buff[24]; /* Big enough for 2-word bignum value */
  456. int line_length = other_write_action(WRITE_GET_INFO+WRITE_GET_LINE_LENGTH,
  457. active_stream);
  458. int column =
  459. other_write_action(WRITE_GET_INFO+WRITE_GET_COLUMN, active_stream);
  460. #ifdef NEED_TO_CHECK_BIGNUM_FORMAT
  461. /* The next few lines are to help me track down bugs... */
  462. { int32 d1 = bignum_digits(u)[(len-4)/4];
  463. if (len == 4)
  464. { int32 m = d1 & fix_mask;
  465. if (m == 0 || m == fix_mask)
  466. myprintf("[%.8lx should be fixnum]", (long)d1);
  467. if (signed_overflow(d1))
  468. myprintf("[%.8lx needs 2 words]", (long)d1);
  469. }
  470. else
  471. { int32 d0 = bignum_digits(u)[(len-8)/4];
  472. if (signed_overflow(d1)) myprintf("[needs more words]");
  473. else if (d1 == 0 && (d0 & 0x40000000) == 0) myprintf("[shrink]");
  474. else if (d1 == -1 &&(d0 & 0x40000000) != 0) myprintf("[shrink]");
  475. }
  476. }
  477. /* end of temp code */
  478. #endif
  479. switch (len)
  480. {
  481. case 4: /* one word bignum - especially easy! */
  482. { int32 dig0 = bignum_digits(u)[0];
  483. unsigned32 dig = dig0;
  484. int i = 0;
  485. if (dig0 < 0) dig = -dig0;
  486. /*
  487. * I do all my conversion from binary to decimal by hand in this code,
  488. * where once I used sprintf - but sprintf is somewhat more powerful
  489. * than I need, and thus I expect it to be somewhat more costly.
  490. */
  491. do
  492. { int32 nxt = dig % 10;
  493. dig = dig / 10;
  494. my_buff[i++] = (char)(nxt + '0');
  495. } while (dig != 0);
  496. if (dig0 < 0) my_buff[i++] = '-';
  497. if (blankp)
  498. { if (nobreak==0 && column+i >= line_length)
  499. { if (column != 0) putc_stream('\n', active_stream);
  500. }
  501. else putc_stream(' ', active_stream);
  502. }
  503. else if (nobreak==0 && column != 0 && column+i > line_length)
  504. putc_stream('\n', active_stream);
  505. while (--i >= 0) putc_stream(my_buff[i], active_stream);
  506. }
  507. return;
  508. case 8: /* two word bignum */
  509. { unsigned32 d0 = bignum_digits(u)[0], d1 = bignum_digits(u)[1];
  510. unsigned32 d0high, d0low, w;
  511. unsigned32 p0, p1, p2;
  512. CSLbool negativep = NO;
  513. int i, j;
  514. if (((int32)d1) < 0)
  515. { negativep = YES;
  516. d0 = clear_top_bit(-(int32)d0);
  517. if (d0 == 0) d1 = -(int32)d1;
  518. else d1 = ~d1;
  519. }
  520. d0high = ((unsigned32)d0)>>16;
  521. d0low = d0 - (d0high << 16);
  522. /* Adjust for the fact that I packed just 31 bits into each word.. */
  523. if ((d1 & 1) != 0) d0high |= 0x8000U;
  524. w = d1 >> 1;
  525. /* d1 is at most 0x40000000 here, so no problem wrt sign */
  526. d1 = w / 10000;
  527. w = d0high + ((w % 10000) << 16);
  528. d0high = w / 10000;
  529. w = d0low + ((w % 10000) << 16);
  530. d0low = w / 10000;
  531. p0 = w % 10000; /* last 4 digits of value */
  532. w = d1;
  533. d1 = w / 10000;
  534. w = d0high + ((w % 10000) << 16);
  535. d0high = w / 10000;
  536. w = d0low + ((w % 10000) << 16);
  537. d0low = w / 10000;
  538. p1 = w % 10000; /* 4 more digits of value */
  539. /* By now d1 is certainly less then 10000 */
  540. w = d0high + (d1 << 16);
  541. d0high = w / 10000;
  542. w = d0low + ((w % 10000) << 16);
  543. d0 = (w / 10000) + (d0high << 16);
  544. p2 = w % 10000;
  545. i = 0;
  546. for (j=0; j<4; j++)
  547. my_buff[i++] = (char)((p0 % 10) + '0'), p0 = p0/10;
  548. for (j=0; j<4; j++)
  549. my_buff[i++] = (char)((p1 % 10) + '0'), p1 = p1/10;
  550. /*
  551. * Because the value used 2 words it must have more than 8 digits in it,
  552. * but it may not have more than 12. Therefore I am not certain whether
  553. * all 4 digits of p2 are needed.
  554. */
  555. if (d0 == 0)
  556. { while (p2 != 0)
  557. my_buff[i++] = (char)((p2 % 10) + '0'), p2 = p2/10;
  558. }
  559. else
  560. { for (j=0; j<4; j++)
  561. my_buff[i++] = (char)((p2 % 10) + '0'), p2 = p2/10;
  562. while (d0 != 0)
  563. my_buff[i++] = (char)((d0 % 10) + '0'), d0 = d0/10;
  564. }
  565. if (negativep) my_buff[i++] = '-';
  566. if (blankp)
  567. { if (nobreak==0 && column+i >= line_length)
  568. { if (column != 0) putc_stream('\n', active_stream);
  569. }
  570. else putc_stream(' ', active_stream);
  571. }
  572. else if (nobreak==0 && column != 0 && column+i > line_length)
  573. putc_stream('\n', active_stream);
  574. while (--i >= 0) putc_stream(my_buff[i], active_stream);
  575. return;
  576. }
  577. default:
  578. break; /* general big case */
  579. }
  580. push(u);
  581. len1 = CELL+4+(11*len)/10;
  582. /*
  583. * To print a general big number I will convert it from radix 2^31 to
  584. * radix 10^9. This can involve increasing the number of digits by a factor
  585. * of about 1.037, so the 10% expansion I allow for in len1 above should
  586. * keep me safe.
  587. */
  588. len1 = (intxx)doubleword_align_up(len1);
  589. w = getvector(TAG_NUMBERS, TYPE_BIGNUM, len1);
  590. pop(u);
  591. nil = C_nil;
  592. if (!exception_pending())
  593. { CSLbool sign = NO;
  594. int32 len2;
  595. len = len/4;
  596. len1 = (len1-CELL)/4;
  597. if (((int32)bignum_digits(u)[len-1]) >= 0)
  598. for (i=0; i<len; i++) bignum_digits(w)[i] = bignum_digits(u)[i];
  599. else
  600. { int32 carry = -1;
  601. sign = YES;
  602. for (i=0; i<len; i++)
  603. /* negate the number so I am working with a +ve value */
  604. { carry = clear_top_bit(~bignum_digits(u)[i]) + top_bit(carry);
  605. bignum_digits(w)[i] = clear_top_bit(carry);
  606. }
  607. }
  608. len2 = len1;
  609. while (len > 1)
  610. { int32 k;
  611. int32 carry = 0;
  612. /*
  613. * This stack-check is so that I can respond to interrupts
  614. */
  615. if (stack >= stacklimit)
  616. { w = reclaim(w, "stack", GC_STACK, 0);
  617. errexitv();
  618. }
  619. /* divide by 10^9 to obtain remainder */
  620. for (k=len-1; k>=0; k--)
  621. Ddiv10_9(carry, bignum_digits(w)[k],
  622. carry, bignum_digits(w)[k]);
  623. if (bignum_digits(w)[len-1] == 0) len--;
  624. bignum_digits(w)[--len2] = carry; /* 9 digits in decimal format */
  625. }
  626. push(w);
  627. { unsigned32 dig;
  628. int i;
  629. int32 len;
  630. if (bignum_digits(w)[0] == 0) dig = bignum_digits(w)[len2++];
  631. else dig = bignum_digits(w)[0];
  632. i = 0;
  633. do
  634. { int32 nxt = dig % 10;
  635. dig = dig / 10;
  636. my_buff[i++] = (char)(nxt + '0');
  637. } while (dig != 0);
  638. if (sign) my_buff[i++] = '-';
  639. len = i + 9*(len1-len2);
  640. if (blankp)
  641. { if (nobreak==0 && column+len >= line_length)
  642. { if (column != 0) putc_stream('\n', active_stream);
  643. }
  644. else putc_stream(' ', active_stream);
  645. }
  646. else if (nobreak==0 && column != 0 && column+len > line_length)
  647. putc_stream('\n', active_stream);
  648. while (--i >= 0) putc_stream(my_buff[i], active_stream);
  649. }
  650. pop(w);
  651. while (len2 < len1)
  652. { unsigned32 dig = bignum_digits(w)[len2++];
  653. int i;
  654. push(w);
  655. for (i=8; i>=0; i--)
  656. { int32 nxt = dig % 10;
  657. dig = dig / 10;
  658. my_buff[i] = (char)(nxt + '0');
  659. }
  660. for (i=0; i<=8; i++) putc_stream(my_buff[i], active_stream);
  661. pop(w);
  662. errexitv();
  663. if (stack >= stacklimit)
  664. { w = reclaim(w, "stack", GC_STACK, 0);
  665. errexitv();
  666. }
  667. }
  668. }
  669. }
  670. void print_bighexoctbin(Lisp_Object u, int radix, int width,
  671. CSLbool blankp, int nobreak)
  672. /*
  673. * This prints a bignum in base 16, 8 or 2. The main misery about this is
  674. * that internally bignums are stored in chunks of 31 bits, so I have
  675. * to collect digits for printing in a way that can span across word
  676. * boundaries. There is also potential fun with regard to the display
  677. * of negative values - here I will print a "~" mark in front but will
  678. * then show them revealing the 2s complement representation used.
  679. * The width specifier is intended to specify a minimum width to be
  680. * used in the sense that printf uses the word "precision", so numbers
  681. * will be padded with leading zeros (of f/7/1 if negative) if necessary.
  682. * Well actually I have not implemented support for width specification
  683. * yet. It will be wanted so that (prinhex 1 8) comes out as 00000001,
  684. * for instance. So at present some C compilers will give me a warning about
  685. * width being ignored - they are RIGHT!
  686. */
  687. {
  688. int32 n = (bignum_length(u)-CELL-4)/4;
  689. unsigned32 a=0, b=0;
  690. int32 len = 31*(n+1);
  691. int flag = 0, bits;
  692. CSLbool sign = NO, started = NO;
  693. nil_as_base
  694. int line_length = other_write_action(WRITE_GET_INFO+WRITE_GET_LINE_LENGTH,
  695. active_stream);
  696. int column =
  697. other_write_action(WRITE_GET_INFO+WRITE_GET_COLUMN, active_stream);
  698. if (radix == 16)
  699. { bits = len % 4;
  700. len = len / 4;
  701. if (bits != 0) len++, bits = 4 - bits;
  702. }
  703. else if (radix == 8)
  704. { bits = len % 3;
  705. len = len / 3;
  706. if (bits != 0) len++, bits = 3 - bits;
  707. }
  708. else
  709. { bits = 0;
  710. }
  711. /*
  712. * As I work down the bignum, b holds the next chunk of digits to be printed,
  713. * and bits tells me how many valid bits are present in it. I start off
  714. * with bits non-zero to (in effect) adjoin a few bits from an implicit
  715. * extra leading digit so as to make up to an integral multiple of 3 or 4
  716. * bits in all when I am printing base 8 or 16. The variable (len) now tells
  717. * me how many digits remain to be printed.
  718. */
  719. push(u);
  720. if ((int32)bignum_digits(u)[n] < 0)
  721. { sign = YES;
  722. len+=2; /* Allow extra length for sign marker and initial f/7/1 */
  723. if (radix == 16) flag = 0xf;
  724. else if (radix == 8) flag = 0x7;
  725. else flag = 0x1;
  726. /*
  727. * Set the buffer b to have a few '1' bits at its top.
  728. */
  729. if (bits != 0) b = ((int32)-1) << (32-bits);
  730. }
  731. /*
  732. * I kill leading zeros - and since this is a real bignum there MUST be
  733. * at least one nonzero digit somewhere, so I do not have to worry about the
  734. * total supression of the value 0. I will do something with leading 'f' or
  735. * '7' digits for negative numbers.
  736. */
  737. while (n >= 0 || bits > 0)
  738. { if (radix == 16)
  739. { a = (b >> 28); /* Grab the next 4 bits of the number */
  740. b = b << 4; /* shift buffer to position the next four */
  741. bits -= 4;
  742. }
  743. else if (radix == 8)
  744. { a = (b >> 29); /* 3 bits */
  745. b = b << 3;
  746. bits -= 3;
  747. }
  748. else
  749. { a = (b >> 31); /* just 1 bit */
  750. b = b << 1;
  751. bits -= 1;
  752. }
  753. if (bits < 0) /* there had not been enough buffered bits */
  754. { u = stack[0];
  755. b = bignum_digits(u)[n] << 1;
  756. n--;
  757. a |= b >> (32+bits);
  758. b = b << (-bits);
  759. bits += 31;
  760. }
  761. if ((int)a != flag) /* leading '0' or 'f' (or '7') supression code */
  762. {
  763. if (!started)
  764. {
  765. if (blankp)
  766. { if (nobreak==0 && column+len >= line_length)
  767. { if (column != 0) putc_stream('\n', active_stream);
  768. }
  769. else putc_stream(' ', active_stream);
  770. }
  771. else if (nobreak==0 && column != 0 && column+len > line_length)
  772. putc_stream('\n', active_stream);
  773. if (sign) putc_stream('~', active_stream);
  774. started = YES;
  775. if (flag > 0) putc_stream(radix == 16 ? 'f' :
  776. radix == 8 ? '7' : '1', active_stream);
  777. flag = -1;
  778. }
  779. }
  780. len--;
  781. if (flag >= 0) continue; /* lose leading zeros (or F digits) */
  782. if (a < 10) a += '0';
  783. else a += ('a' - 10);
  784. putc_stream((int)a, active_stream);
  785. }
  786. popv(1);
  787. }
  788. /* end of arith05.c */