arith05.c 25 KB

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