bignum.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052
  1. /* -*-C-*-
  2. $Id: bignum.c,v 9.41 1994/02/09 00:53:27 cph Exp $
  3. Copyright 1986,1987,1988,1989,1990,1991 Massachusetts Institute of Technology
  4. Copyright 1992,1993,1994,2004 Massachusetts Institute of Technology
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions are
  7. met:
  8. 1. Redistributions of source code must retain the above copyright
  9. notice, this list of conditions and the following disclaimer.
  10. 2. Redistributions in binary form must reproduce the above
  11. copyright notice, this list of conditions and the following
  12. disclaimer in the documentation and/or other materials provided
  13. with the distribution.
  14. 3. The name of the author may not be used to endorse or promote
  15. products derived from this software without specific prior
  16. written permission.
  17. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  21. INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23. SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  25. STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  26. IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. /* License changed to modified BSD by cph on 2004-11-08. */
  30. /*
  31. * Modifications for Scheme 48 by Martin Gasbichler, Mike Sperber,
  32. * Marcus Crestani, Harald Glab-Phlak
  33. */
  34. /* Changes for Scheme 48:
  35. * - Converted to ANSI.
  36. * - Added bitwise operations.
  37. * - Added s48_ to the beginning of all externally visible names.
  38. * - Cached the bignum representations of -1, 0, and 1.
  39. */
  40. #include "bignum.h"
  41. #include "bignumint.h"
  42. #include <limits.h>
  43. #include <stdio.h>
  44. #include <stdlib.h> /* abort */
  45. #include <math.h>
  46. /* Forward references */
  47. static int bignum_equal_p_unsigned(bignum_type, bignum_type);
  48. static enum bignum_comparison bignum_compare_unsigned(bignum_type, bignum_type);
  49. static bignum_type bignum_add_unsigned(bignum_type, bignum_type, int);
  50. static bignum_type bignum_subtract_unsigned(bignum_type, bignum_type);
  51. static bignum_type bignum_multiply_unsigned(bignum_type, bignum_type, int);
  52. static bignum_type bignum_multiply_unsigned_small_factor
  53. (bignum_type, bignum_digit_type, int);
  54. static void bignum_destructive_scale_up(bignum_type, bignum_digit_type);
  55. static void bignum_destructive_add(bignum_type, bignum_digit_type);
  56. static void bignum_divide_unsigned_large_denominator
  57. (bignum_type, bignum_type, bignum_type *, bignum_type *, int, int);
  58. static void bignum_destructive_normalization(bignum_type, bignum_type, int);
  59. static void bignum_destructive_unnormalization(bignum_type, int);
  60. static void bignum_divide_unsigned_normalized(bignum_type, bignum_type, bignum_type);
  61. static bignum_digit_type bignum_divide_subtract
  62. (bignum_digit_type *, bignum_digit_type *, bignum_digit_type,
  63. bignum_digit_type *);
  64. static void bignum_divide_unsigned_medium_denominator
  65. (bignum_type, bignum_digit_type, bignum_type *, bignum_type *, int, int);
  66. static bignum_digit_type bignum_digit_divide
  67. (bignum_digit_type, bignum_digit_type, bignum_digit_type, bignum_digit_type *);
  68. static bignum_digit_type bignum_digit_divide_subtract
  69. (bignum_digit_type, bignum_digit_type, bignum_digit_type, bignum_digit_type *);
  70. static void bignum_divide_unsigned_small_denominator
  71. (bignum_type, bignum_digit_type, bignum_type *, bignum_type *, int, int);
  72. static bignum_digit_type bignum_destructive_scale_down
  73. (bignum_type, bignum_digit_type);
  74. static bignum_type bignum_remainder_unsigned_small_denominator
  75. (bignum_type, bignum_digit_type, int);
  76. static bignum_type bignum_digit_to_bignum(bignum_digit_type, int);
  77. static bignum_type bignum_allocate(bignum_length_type, int);
  78. static bignum_type bignum_allocate_zeroed(bignum_length_type, int);
  79. static bignum_type bignum_shorten_length(bignum_type, bignum_length_type);
  80. static bignum_type bignum_trim(bignum_type);
  81. static bignum_type bignum_copy(bignum_type);
  82. static bignum_type bignum_new_sign(bignum_type, int);
  83. static bignum_type bignum_maybe_new_sign(bignum_type, int);
  84. static void bignum_destructive_copy(bignum_type, bignum_type);
  85. /* Unused
  86. static void bignum_destructive_zero(bignum_type);
  87. */
  88. /* Added for bitwise operations. */
  89. static bignum_type bignum_magnitude_ash(bignum_type arg1, long n);
  90. static bignum_type bignum_pospos_bitwise_op(int op, bignum_type, bignum_type);
  91. static bignum_type bignum_posneg_bitwise_op(int op, bignum_type, bignum_type);
  92. static bignum_type bignum_negneg_bitwise_op(int op, bignum_type, bignum_type);
  93. static void bignum_negate_magnitude(bignum_type);
  94. static long bignum_unsigned_logcount(bignum_type arg);
  95. static int bignum_unsigned_logbitp(int shift, bignum_type bignum);
  96. static s48_ref_t s48_bignum_zero = NULL;
  97. static s48_ref_t s48_bignum_pos_one = NULL;
  98. static s48_ref_t s48_bignum_neg_one = NULL;
  99. /* Exports */
  100. /*
  101. * We have to allocate the cached constants slightly differently because
  102. * they have to be registered with the GC, which requires that we have
  103. * tagged pointers to them.
  104. */
  105. void
  106. s48_bignum_make_cached_constants(void)
  107. {
  108. if (s48_bignum_zero == NULL) {
  109. bignum_type temp;
  110. s48_bignum_zero = s48_make_global_ref((s48_value) BIGNUM_ALLOCATE_TAGGED(0));
  111. temp = S48_ADDRESS_AFTER_HEADER(s48_deref(s48_bignum_zero), long);
  112. BIGNUM_SET_HEADER (temp, 0, 0);
  113. s48_bignum_pos_one = s48_make_global_ref((s48_value) BIGNUM_ALLOCATE_TAGGED(1));
  114. temp = S48_ADDRESS_AFTER_HEADER(s48_deref(s48_bignum_pos_one), long);
  115. BIGNUM_SET_HEADER (temp, 1, 0);
  116. (BIGNUM_REF (temp, 0)) = 1;
  117. s48_bignum_neg_one = s48_make_global_ref ((s48_value) BIGNUM_ALLOCATE_TAGGED(1));
  118. temp = S48_ADDRESS_AFTER_HEADER(s48_deref(s48_bignum_neg_one), long);
  119. BIGNUM_SET_HEADER (temp, 1, 1);
  120. (BIGNUM_REF (temp, 0)) = 1;
  121. }
  122. }
  123. int
  124. s48_bignum_equal_p(bignum_type x, bignum_type y)
  125. {
  126. return
  127. ((BIGNUM_ZERO_P (x))
  128. ? (BIGNUM_ZERO_P (y))
  129. : ((! (BIGNUM_ZERO_P (y)))
  130. && ((BIGNUM_NEGATIVE_P (x))
  131. ? (BIGNUM_NEGATIVE_P (y))
  132. : (! (BIGNUM_NEGATIVE_P (y))))
  133. && (bignum_equal_p_unsigned (x, y))));
  134. }
  135. enum bignum_comparison
  136. s48_bignum_test(bignum_type bignum)
  137. {
  138. return
  139. ((BIGNUM_ZERO_P (bignum))
  140. ? bignum_comparison_equal
  141. : (BIGNUM_NEGATIVE_P (bignum))
  142. ? bignum_comparison_less
  143. : bignum_comparison_greater);
  144. }
  145. enum bignum_comparison
  146. s48_bignum_compare(bignum_type x, bignum_type y)
  147. {
  148. return
  149. ((BIGNUM_ZERO_P (x))
  150. ? ((BIGNUM_ZERO_P (y))
  151. ? bignum_comparison_equal
  152. : (BIGNUM_NEGATIVE_P (y))
  153. ? bignum_comparison_greater
  154. : bignum_comparison_less)
  155. : (BIGNUM_ZERO_P (y))
  156. ? ((BIGNUM_NEGATIVE_P (x))
  157. ? bignum_comparison_less
  158. : bignum_comparison_greater)
  159. : (BIGNUM_NEGATIVE_P (x))
  160. ? ((BIGNUM_NEGATIVE_P (y))
  161. ? (bignum_compare_unsigned (y, x))
  162. : (bignum_comparison_less))
  163. : ((BIGNUM_NEGATIVE_P (y))
  164. ? (bignum_comparison_greater)
  165. : (bignum_compare_unsigned (x, y))));
  166. }
  167. bignum_type
  168. s48_bignum_add(bignum_type x, bignum_type y)
  169. {
  170. return
  171. ((BIGNUM_ZERO_P (x))
  172. ? (BIGNUM_MAYBE_COPY (y))
  173. : (BIGNUM_ZERO_P (y))
  174. ? (BIGNUM_MAYBE_COPY (x))
  175. : ((BIGNUM_NEGATIVE_P (x))
  176. ? ((BIGNUM_NEGATIVE_P (y))
  177. ? (bignum_add_unsigned (x, y, 1))
  178. : (bignum_subtract_unsigned (y, x)))
  179. : ((BIGNUM_NEGATIVE_P (y))
  180. ? (bignum_subtract_unsigned (x, y))
  181. : (bignum_add_unsigned (x, y, 0)))));
  182. }
  183. bignum_type
  184. s48_bignum_subtract(bignum_type x, bignum_type y)
  185. {
  186. return
  187. ((BIGNUM_ZERO_P (x))
  188. ? ((BIGNUM_ZERO_P (y))
  189. ? (BIGNUM_MAYBE_COPY (y))
  190. : (bignum_new_sign (y, (! (BIGNUM_NEGATIVE_P (y))))))
  191. : ((BIGNUM_ZERO_P (y))
  192. ? (BIGNUM_MAYBE_COPY (x))
  193. : ((BIGNUM_NEGATIVE_P (x))
  194. ? ((BIGNUM_NEGATIVE_P (y))
  195. ? (bignum_subtract_unsigned (y, x))
  196. : (bignum_add_unsigned (x, y, 1)))
  197. : ((BIGNUM_NEGATIVE_P (y))
  198. ? (bignum_add_unsigned (x, y, 0))
  199. : (bignum_subtract_unsigned (x, y))))));
  200. }
  201. bignum_type
  202. s48_bignum_negate(bignum_type x)
  203. {
  204. return
  205. ((BIGNUM_ZERO_P (x))
  206. ? (BIGNUM_MAYBE_COPY (x))
  207. : (bignum_new_sign (x, (! (BIGNUM_NEGATIVE_P (x))))));
  208. }
  209. bignum_type
  210. s48_bignum_multiply(bignum_type x, bignum_type y)
  211. {
  212. bignum_length_type x_length = (BIGNUM_LENGTH (x));
  213. bignum_length_type y_length = (BIGNUM_LENGTH (y));
  214. int negative_p =
  215. ((BIGNUM_NEGATIVE_P (x))
  216. ? (! (BIGNUM_NEGATIVE_P (y)))
  217. : (BIGNUM_NEGATIVE_P (y)));
  218. if (BIGNUM_ZERO_P (x))
  219. return (BIGNUM_MAYBE_COPY (x));
  220. if (BIGNUM_ZERO_P (y))
  221. return (BIGNUM_MAYBE_COPY (y));
  222. if (x_length == 1)
  223. {
  224. bignum_digit_type digit = (BIGNUM_REF (x, 0));
  225. if (digit == 1)
  226. return (bignum_maybe_new_sign (y, negative_p));
  227. if (digit < BIGNUM_RADIX_ROOT)
  228. return (bignum_multiply_unsigned_small_factor (y, digit, negative_p));
  229. }
  230. if (y_length == 1)
  231. {
  232. bignum_digit_type digit = (BIGNUM_REF (y, 0));
  233. if (digit == 1)
  234. return (bignum_maybe_new_sign (x, negative_p));
  235. if (digit < BIGNUM_RADIX_ROOT)
  236. return (bignum_multiply_unsigned_small_factor (x, digit, negative_p));
  237. }
  238. return (bignum_multiply_unsigned (x, y, negative_p));
  239. }
  240. static int
  241. bignum_divide(bignum_type numerator, bignum_type denominator,
  242. bignum_type * quotient, bignum_type * remainder)
  243. {
  244. if (BIGNUM_ZERO_P (denominator))
  245. return (1);
  246. if (BIGNUM_ZERO_P (numerator))
  247. {
  248. (*quotient) = (BIGNUM_MAYBE_COPY (numerator));
  249. (*remainder) = (BIGNUM_MAYBE_COPY (numerator));
  250. }
  251. else
  252. {
  253. int r_negative_p = (BIGNUM_NEGATIVE_P (numerator));
  254. int q_negative_p =
  255. ((BIGNUM_NEGATIVE_P (denominator)) ? (! r_negative_p) : r_negative_p);
  256. switch (bignum_compare_unsigned (numerator, denominator))
  257. {
  258. case bignum_comparison_equal:
  259. {
  260. (*quotient) = (BIGNUM_ONE (q_negative_p));
  261. (*remainder) = (BIGNUM_ZERO ());
  262. break;
  263. }
  264. case bignum_comparison_less:
  265. {
  266. (*quotient) = (BIGNUM_ZERO ());
  267. (*remainder) = (BIGNUM_MAYBE_COPY (numerator));
  268. break;
  269. }
  270. case bignum_comparison_greater:
  271. {
  272. if ((BIGNUM_LENGTH (denominator)) == 1)
  273. {
  274. bignum_digit_type digit = (BIGNUM_REF (denominator, 0));
  275. if (digit == 1)
  276. {
  277. (*quotient) =
  278. (bignum_maybe_new_sign (numerator, q_negative_p));
  279. (*remainder) = (BIGNUM_ZERO ());
  280. break;
  281. }
  282. else if (digit < BIGNUM_RADIX_ROOT)
  283. {
  284. bignum_divide_unsigned_small_denominator
  285. (numerator, digit,
  286. quotient, remainder,
  287. q_negative_p, r_negative_p);
  288. break;
  289. }
  290. else
  291. {
  292. bignum_divide_unsigned_medium_denominator
  293. (numerator, digit,
  294. quotient, remainder,
  295. q_negative_p, r_negative_p);
  296. break;
  297. }
  298. }
  299. bignum_divide_unsigned_large_denominator
  300. (numerator, denominator,
  301. quotient, remainder,
  302. q_negative_p, r_negative_p);
  303. break;
  304. }
  305. }
  306. }
  307. return (0);
  308. }
  309. int
  310. s48_bignum_divide(bignum_type numerator, bignum_type denominator,
  311. void* quotient, void * remainder)
  312. {
  313. return bignum_divide(numerator, denominator,
  314. (bignum_type *)quotient, (bignum_type *)remainder);
  315. }
  316. bignum_type
  317. s48_bignum_quotient(bignum_type numerator, bignum_type denominator)
  318. {
  319. if (BIGNUM_ZERO_P (denominator))
  320. return (BIGNUM_OUT_OF_BAND);
  321. if (BIGNUM_ZERO_P (numerator))
  322. return (BIGNUM_MAYBE_COPY (numerator));
  323. {
  324. int q_negative_p =
  325. ((BIGNUM_NEGATIVE_P (denominator))
  326. ? (! (BIGNUM_NEGATIVE_P (numerator)))
  327. : (BIGNUM_NEGATIVE_P (numerator)));
  328. switch (bignum_compare_unsigned (numerator, denominator))
  329. {
  330. case bignum_comparison_equal:
  331. return (BIGNUM_ONE (q_negative_p));
  332. case bignum_comparison_less:
  333. return (BIGNUM_ZERO ());
  334. case bignum_comparison_greater:
  335. default: /* to appease gcc -Wall */
  336. {
  337. bignum_type quotient;
  338. if ((BIGNUM_LENGTH (denominator)) == 1)
  339. {
  340. bignum_digit_type digit = (BIGNUM_REF (denominator, 0));
  341. if (digit == 1)
  342. return (bignum_maybe_new_sign (numerator, q_negative_p));
  343. if (digit < BIGNUM_RADIX_ROOT)
  344. bignum_divide_unsigned_small_denominator
  345. (numerator, digit,
  346. (&quotient), ((bignum_type *) 0),
  347. q_negative_p, 0);
  348. else
  349. bignum_divide_unsigned_medium_denominator
  350. (numerator, digit,
  351. (&quotient), ((bignum_type *) 0),
  352. q_negative_p, 0);
  353. }
  354. else
  355. bignum_divide_unsigned_large_denominator
  356. (numerator, denominator,
  357. (&quotient), ((bignum_type *) 0),
  358. q_negative_p, 0);
  359. return (quotient);
  360. }
  361. }
  362. }
  363. }
  364. bignum_type
  365. s48_bignum_remainder(bignum_type numerator, bignum_type denominator)
  366. {
  367. if (BIGNUM_ZERO_P (denominator))
  368. return (BIGNUM_OUT_OF_BAND);
  369. if (BIGNUM_ZERO_P (numerator))
  370. return (BIGNUM_MAYBE_COPY (numerator));
  371. switch (bignum_compare_unsigned (numerator, denominator))
  372. {
  373. case bignum_comparison_equal:
  374. return (BIGNUM_ZERO ());
  375. case bignum_comparison_less:
  376. return (BIGNUM_MAYBE_COPY (numerator));
  377. case bignum_comparison_greater:
  378. default: /* to appease gcc -Wall */
  379. {
  380. bignum_type remainder;
  381. if ((BIGNUM_LENGTH (denominator)) == 1)
  382. {
  383. bignum_digit_type digit = (BIGNUM_REF (denominator, 0));
  384. if (digit == 1)
  385. return (BIGNUM_ZERO ());
  386. if (digit < BIGNUM_RADIX_ROOT)
  387. return
  388. (bignum_remainder_unsigned_small_denominator
  389. (numerator, digit, (BIGNUM_NEGATIVE_P (numerator))));
  390. bignum_divide_unsigned_medium_denominator
  391. (numerator, digit,
  392. ((bignum_type *) 0), (&remainder),
  393. 0, (BIGNUM_NEGATIVE_P (numerator)));
  394. }
  395. else
  396. bignum_divide_unsigned_large_denominator
  397. (numerator, denominator,
  398. ((bignum_type *) 0), (&remainder),
  399. 0, (BIGNUM_NEGATIVE_P (numerator)));
  400. return (remainder);
  401. }
  402. }
  403. }
  404. /* These procedures depend on the non-portable type `unsigned long'.
  405. If your compiler doesn't support this type, either define the
  406. switch `BIGNUM_NO_ULONG' to disable them (in "bignum.h"), or write
  407. new versions that don't use this type. */
  408. #ifndef BIGNUM_NO_ULONG
  409. bignum_type
  410. s48_long_to_bignum(long n)
  411. {
  412. int negative_p;
  413. bignum_digit_type result_digits [BIGNUM_DIGITS_FOR_LONG];
  414. bignum_digit_type * end_digits = result_digits;
  415. /* Special cases win when these small constants are cached. */
  416. if (n == 0) return (BIGNUM_ZERO ());
  417. if (n == 1) return (BIGNUM_ONE (0));
  418. if (n == -1) return (BIGNUM_ONE (1));
  419. {
  420. unsigned long accumulator = ((negative_p = (n < 0)) ? (-n) : n);
  421. do
  422. {
  423. (*end_digits++) = (accumulator & BIGNUM_DIGIT_MASK);
  424. accumulator >>= BIGNUM_DIGIT_LENGTH;
  425. }
  426. while (accumulator != 0);
  427. }
  428. {
  429. bignum_type result =
  430. (bignum_allocate ((end_digits - result_digits), negative_p));
  431. bignum_digit_type * scan_digits = result_digits;
  432. bignum_digit_type * scan_result = (BIGNUM_START_PTR (result));
  433. while (scan_digits < end_digits)
  434. (*scan_result++) = (*scan_digits++);
  435. return (result);
  436. }
  437. }
  438. long
  439. s48_bignum_to_long(bignum_type bignum)
  440. {
  441. if (BIGNUM_ZERO_P (bignum))
  442. return (0);
  443. {
  444. unsigned long accumulator = 0;
  445. bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
  446. bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum)));
  447. while (start < scan)
  448. accumulator = ((accumulator << BIGNUM_DIGIT_LENGTH) + (*--scan));
  449. return ((BIGNUM_NEGATIVE_P (bignum)) ? (-((long)accumulator)) : (long)accumulator);
  450. }
  451. }
  452. bignum_type
  453. s48_ulong_to_bignum(unsigned long n)
  454. {
  455. bignum_digit_type result_digits [BIGNUM_DIGITS_FOR_LONG];
  456. bignum_digit_type * end_digits = result_digits;
  457. /* Special cases win when these small constants are cached. */
  458. if (n == 0) return (BIGNUM_ZERO ());
  459. if (n == 1) return (BIGNUM_ONE (0));
  460. {
  461. unsigned long accumulator = n;
  462. do
  463. {
  464. (*end_digits++) = (accumulator & BIGNUM_DIGIT_MASK);
  465. accumulator >>= BIGNUM_DIGIT_LENGTH;
  466. }
  467. while (accumulator != 0);
  468. }
  469. {
  470. bignum_type result =
  471. (bignum_allocate ((end_digits - result_digits), 0));
  472. bignum_digit_type * scan_digits = result_digits;
  473. bignum_digit_type * scan_result = (BIGNUM_START_PTR (result));
  474. while (scan_digits < end_digits)
  475. (*scan_result++) = (*scan_digits++);
  476. return (result);
  477. }
  478. }
  479. unsigned long
  480. s48_bignum_to_ulong(bignum_type bignum)
  481. {
  482. if (BIGNUM_ZERO_P (bignum))
  483. return (0);
  484. {
  485. unsigned long accumulator = 0;
  486. bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
  487. bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum)));
  488. while (start < scan)
  489. accumulator = ((accumulator << BIGNUM_DIGIT_LENGTH) + (*--scan));
  490. return (accumulator);
  491. }
  492. }
  493. #endif /* not BIGNUM_NO_ULONG */
  494. #define DTB_WRITE_DIGIT(factor) \
  495. { \
  496. significand *= (factor); \
  497. digit = ((bignum_digit_type) significand); \
  498. (*--scan) = digit; \
  499. significand -= ((double) digit); \
  500. }
  501. bignum_type
  502. s48_double_to_bignum(double x)
  503. {
  504. int exponent;
  505. double significand = (frexp (x, (&exponent)));
  506. if (exponent <= 0) return (BIGNUM_ZERO ());
  507. if (exponent == 1) return (BIGNUM_ONE (x < 0));
  508. if (significand < 0) significand = (-significand);
  509. {
  510. bignum_length_type length = (BIGNUM_BITS_TO_DIGITS (exponent));
  511. bignum_type result = (bignum_allocate (length, (x < 0)));
  512. bignum_digit_type * start = (BIGNUM_START_PTR (result));
  513. bignum_digit_type * scan = (start + length);
  514. bignum_digit_type digit;
  515. int odd_bits = (exponent % BIGNUM_DIGIT_LENGTH);
  516. if (odd_bits > 0)
  517. DTB_WRITE_DIGIT (1L << odd_bits);
  518. while (start < scan)
  519. {
  520. if (significand == 0)
  521. {
  522. while (start < scan)
  523. (*--scan) = 0;
  524. break;
  525. }
  526. DTB_WRITE_DIGIT (BIGNUM_RADIX);
  527. }
  528. return (result);
  529. }
  530. }
  531. #undef DTB_WRITE_DIGIT
  532. double
  533. s48_bignum_to_double(bignum_type bignum)
  534. {
  535. if (BIGNUM_ZERO_P (bignum))
  536. return (0);
  537. {
  538. double accumulator = 0;
  539. bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
  540. bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum)));
  541. while (start < scan)
  542. accumulator = ((accumulator * BIGNUM_RADIX) + (*--scan));
  543. return ((BIGNUM_NEGATIVE_P (bignum)) ? (-accumulator) : accumulator);
  544. }
  545. }
  546. int
  547. s48_bignum_fits_in_word_p(bignum_type bignum, long word_length,
  548. int twos_complement_p)
  549. {
  550. unsigned int n_bits = (twos_complement_p ? (word_length - 1) : word_length);
  551. BIGNUM_ASSERT (n_bits > 0);
  552. {
  553. bignum_length_type length = (BIGNUM_LENGTH (bignum));
  554. bignum_length_type max_digits = (BIGNUM_BITS_TO_DIGITS (n_bits));
  555. bignum_digit_type msd, max;
  556. return
  557. ((length < max_digits) ||
  558. ((length == max_digits) &&
  559. ((((msd = (BIGNUM_REF (bignum, (length - 1)))) <
  560. (max = (1L << (n_bits - ((length - 1) * BIGNUM_DIGIT_LENGTH))))) ||
  561. (twos_complement_p &&
  562. (msd == max) &&
  563. (BIGNUM_NEGATIVE_P (bignum)))))));
  564. }
  565. }
  566. bignum_type
  567. s48_bignum_length_in_bits(bignum_type bignum)
  568. {
  569. if (BIGNUM_ZERO_P (bignum))
  570. return (BIGNUM_ZERO ());
  571. {
  572. bignum_length_type index = ((BIGNUM_LENGTH (bignum)) - 1);
  573. bignum_digit_type digit = (BIGNUM_REF (bignum, index));
  574. bignum_type result = (bignum_allocate (2, 0));
  575. (BIGNUM_REF (result, 0)) = index;
  576. (BIGNUM_REF (result, 1)) = 0;
  577. bignum_destructive_scale_up (result, BIGNUM_DIGIT_LENGTH);
  578. while (digit > 0)
  579. {
  580. bignum_destructive_add (result, ((bignum_digit_type) 1));
  581. digit >>= 1;
  582. }
  583. return (bignum_trim (result));
  584. }
  585. }
  586. bignum_type
  587. s48_bignum_length_upper_limit(void)
  588. {
  589. bignum_type result = (bignum_allocate (2, 0));
  590. (BIGNUM_REF (result, 0)) = 0;
  591. (BIGNUM_REF (result, 1)) = BIGNUM_DIGIT_LENGTH;
  592. return (result);
  593. }
  594. bignum_type
  595. s48_digit_stream_to_bignum(unsigned int n_digits,
  596. unsigned int (*producer)(bignum_procedure_context),
  597. bignum_procedure_context context,
  598. unsigned int radix,
  599. int negative_p)
  600. {
  601. BIGNUM_ASSERT ((radix > 1) && (radix <= BIGNUM_RADIX_ROOT));
  602. if (n_digits == 0)
  603. return (BIGNUM_ZERO ());
  604. if (n_digits == 1)
  605. {
  606. long digit = ((long) ((*producer) (context)));
  607. return (s48_long_to_bignum (negative_p ? (- digit) : digit));
  608. }
  609. {
  610. bignum_length_type length;
  611. {
  612. unsigned int radix_copy = radix;
  613. unsigned int log_radix = 0;
  614. while (radix_copy > 0)
  615. {
  616. radix_copy >>= 1;
  617. log_radix += 1;
  618. }
  619. /* This length will be at least as large as needed. */
  620. length = (BIGNUM_BITS_TO_DIGITS (n_digits * log_radix));
  621. }
  622. {
  623. bignum_type result = (bignum_allocate_zeroed (length, negative_p));
  624. while ((n_digits--) > 0)
  625. {
  626. bignum_destructive_scale_up (result, ((bignum_digit_type) radix));
  627. bignum_destructive_add
  628. (result, ((bignum_digit_type) ((*producer) (context))));
  629. }
  630. return (bignum_trim (result));
  631. }
  632. }
  633. }
  634. void
  635. s48_bignum_to_digit_stream(bignum_type bignum,
  636. unsigned int radix,
  637. void (*consumer)(bignum_procedure_context,
  638. bignum_digit_type),
  639. bignum_procedure_context context)
  640. {
  641. BIGNUM_ASSERT ((radix > 1) && (radix <= BIGNUM_RADIX_ROOT));
  642. if (! (BIGNUM_ZERO_P (bignum)))
  643. {
  644. bignum_type working_copy = (bignum_copy (bignum));
  645. bignum_digit_type * start = (BIGNUM_START_PTR (working_copy));
  646. bignum_digit_type * scan = (start + (BIGNUM_LENGTH (working_copy)));
  647. while (start < scan)
  648. {
  649. if ((scan[-1]) == 0)
  650. scan -= 1;
  651. else
  652. (*consumer)
  653. (context, (bignum_destructive_scale_down (working_copy, radix)));
  654. }
  655. BIGNUM_DEALLOCATE (working_copy);
  656. }
  657. return;
  658. }
  659. long
  660. s48_bignum_max_digit_stream_radix(void)
  661. {
  662. return (BIGNUM_RADIX_ROOT);
  663. }
  664. /* Comparisons */
  665. static int
  666. bignum_equal_p_unsigned(bignum_type x, bignum_type y)
  667. {
  668. bignum_length_type length = (BIGNUM_LENGTH (x));
  669. if (length != (BIGNUM_LENGTH (y)))
  670. return (0);
  671. else
  672. {
  673. bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
  674. bignum_digit_type * scan_y = (BIGNUM_START_PTR (y));
  675. bignum_digit_type * end_x = (scan_x + length);
  676. while (scan_x < end_x)
  677. if ((*scan_x++) != (*scan_y++))
  678. return (0);
  679. return (1);
  680. }
  681. }
  682. static enum bignum_comparison
  683. bignum_compare_unsigned(bignum_type x, bignum_type y)
  684. {
  685. bignum_length_type x_length = (BIGNUM_LENGTH (x));
  686. bignum_length_type y_length = (BIGNUM_LENGTH (y));
  687. if (x_length < y_length)
  688. return (bignum_comparison_less);
  689. if (x_length > y_length)
  690. return (bignum_comparison_greater);
  691. {
  692. bignum_digit_type * start_x = (BIGNUM_START_PTR (x));
  693. bignum_digit_type * scan_x = (start_x + x_length);
  694. bignum_digit_type * scan_y = ((BIGNUM_START_PTR (y)) + y_length);
  695. while (start_x < scan_x)
  696. {
  697. bignum_digit_type digit_x = (*--scan_x);
  698. bignum_digit_type digit_y = (*--scan_y);
  699. if (digit_x < digit_y)
  700. return (bignum_comparison_less);
  701. if (digit_x > digit_y)
  702. return (bignum_comparison_greater);
  703. }
  704. }
  705. return (bignum_comparison_equal);
  706. }
  707. /* Addition */
  708. static bignum_type
  709. bignum_add_unsigned(bignum_type x, bignum_type y, int negative_p)
  710. {
  711. if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
  712. {
  713. bignum_type z = x;
  714. x = y;
  715. y = z;
  716. }
  717. {
  718. bignum_length_type x_length = (BIGNUM_LENGTH (x));
  719. bignum_type r = (bignum_allocate ((x_length + 1), negative_p));
  720. bignum_digit_type sum;
  721. bignum_digit_type carry = 0;
  722. bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
  723. bignum_digit_type * scan_r = (BIGNUM_START_PTR (r));
  724. {
  725. bignum_digit_type * scan_y = (BIGNUM_START_PTR (y));
  726. bignum_digit_type * end_y = (scan_y + (BIGNUM_LENGTH (y)));
  727. while (scan_y < end_y)
  728. {
  729. sum = ((*scan_x++) + (*scan_y++) + carry);
  730. if (sum < BIGNUM_RADIX)
  731. {
  732. (*scan_r++) = sum;
  733. carry = 0;
  734. }
  735. else
  736. {
  737. (*scan_r++) = (sum - BIGNUM_RADIX);
  738. carry = 1;
  739. }
  740. }
  741. }
  742. {
  743. bignum_digit_type * end_x = ((BIGNUM_START_PTR (x)) + x_length);
  744. if (carry != 0)
  745. while (scan_x < end_x)
  746. {
  747. sum = ((*scan_x++) + 1);
  748. if (sum < BIGNUM_RADIX)
  749. {
  750. (*scan_r++) = sum;
  751. carry = 0;
  752. break;
  753. }
  754. else
  755. (*scan_r++) = (sum - BIGNUM_RADIX);
  756. }
  757. while (scan_x < end_x)
  758. (*scan_r++) = (*scan_x++);
  759. }
  760. if (carry != 0)
  761. {
  762. (*scan_r) = 1;
  763. return (r);
  764. }
  765. return (bignum_shorten_length (r, x_length));
  766. }
  767. }
  768. /* Subtraction */
  769. static bignum_type
  770. bignum_subtract_unsigned(bignum_type x, bignum_type y)
  771. {
  772. int negative_p;
  773. switch (bignum_compare_unsigned (x, y))
  774. {
  775. case bignum_comparison_equal:
  776. return (BIGNUM_ZERO ());
  777. case bignum_comparison_less:
  778. {
  779. bignum_type z = x;
  780. x = y;
  781. y = z;
  782. }
  783. negative_p = 1;
  784. break;
  785. case bignum_comparison_greater:
  786. negative_p = 0;
  787. break;
  788. }
  789. {
  790. bignum_length_type x_length = (BIGNUM_LENGTH (x));
  791. bignum_type r = (bignum_allocate (x_length, negative_p));
  792. bignum_digit_type difference;
  793. bignum_digit_type borrow = 0;
  794. bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
  795. bignum_digit_type * scan_r = (BIGNUM_START_PTR (r));
  796. {
  797. bignum_digit_type * scan_y = (BIGNUM_START_PTR (y));
  798. bignum_digit_type * end_y = (scan_y + (BIGNUM_LENGTH (y)));
  799. while (scan_y < end_y)
  800. {
  801. difference = (((*scan_x++) - (*scan_y++)) - borrow);
  802. if (difference < 0)
  803. {
  804. (*scan_r++) = (difference + BIGNUM_RADIX);
  805. borrow = 1;
  806. }
  807. else
  808. {
  809. (*scan_r++) = difference;
  810. borrow = 0;
  811. }
  812. }
  813. }
  814. {
  815. bignum_digit_type * end_x = ((BIGNUM_START_PTR (x)) + x_length);
  816. if (borrow != 0)
  817. while (scan_x < end_x)
  818. {
  819. difference = ((*scan_x++) - borrow);
  820. if (difference < 0)
  821. (*scan_r++) = (difference + BIGNUM_RADIX);
  822. else
  823. {
  824. (*scan_r++) = difference;
  825. borrow = 0;
  826. break;
  827. }
  828. }
  829. BIGNUM_ASSERT (borrow == 0);
  830. while (scan_x < end_x)
  831. (*scan_r++) = (*scan_x++);
  832. }
  833. return (bignum_trim (r));
  834. }
  835. }
  836. /* Multiplication
  837. Maximum value for product_low or product_high:
  838. ((R * R) + (R * (R - 2)) + (R - 1))
  839. Maximum value for carry: ((R * (R - 1)) + (R - 1))
  840. where R == BIGNUM_RADIX_ROOT */
  841. static bignum_type
  842. bignum_multiply_unsigned(bignum_type x, bignum_type y, int negative_p)
  843. {
  844. if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
  845. {
  846. bignum_type z = x;
  847. x = y;
  848. y = z;
  849. }
  850. {
  851. bignum_digit_type carry;
  852. bignum_digit_type y_digit_low;
  853. bignum_digit_type y_digit_high;
  854. bignum_digit_type x_digit_low;
  855. bignum_digit_type x_digit_high;
  856. bignum_digit_type product_low;
  857. bignum_digit_type * scan_r;
  858. bignum_digit_type * scan_y;
  859. bignum_length_type x_length = (BIGNUM_LENGTH (x));
  860. bignum_length_type y_length = (BIGNUM_LENGTH (y));
  861. bignum_type r =
  862. (bignum_allocate_zeroed ((x_length + y_length), negative_p));
  863. bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
  864. bignum_digit_type * end_x = (scan_x + x_length);
  865. bignum_digit_type * start_y = (BIGNUM_START_PTR (y));
  866. bignum_digit_type * end_y = (start_y + y_length);
  867. bignum_digit_type * start_r = (BIGNUM_START_PTR (r));
  868. #define x_digit x_digit_high
  869. #define y_digit y_digit_high
  870. #define product_high carry
  871. while (scan_x < end_x)
  872. {
  873. x_digit = (*scan_x++);
  874. x_digit_low = (HD_LOW (x_digit));
  875. x_digit_high = (HD_HIGH (x_digit));
  876. carry = 0;
  877. scan_y = start_y;
  878. scan_r = (start_r++);
  879. while (scan_y < end_y)
  880. {
  881. y_digit = (*scan_y++);
  882. y_digit_low = (HD_LOW (y_digit));
  883. y_digit_high = (HD_HIGH (y_digit));
  884. product_low =
  885. ((*scan_r) +
  886. (x_digit_low * y_digit_low) +
  887. (HD_LOW (carry)));
  888. product_high =
  889. ((x_digit_high * y_digit_low) +
  890. (x_digit_low * y_digit_high) +
  891. (HD_HIGH (product_low)) +
  892. (HD_HIGH (carry)));
  893. (*scan_r++) =
  894. (HD_CONS ((HD_LOW (product_high)), (HD_LOW (product_low))));
  895. carry =
  896. ((x_digit_high * y_digit_high) +
  897. (HD_HIGH (product_high)));
  898. }
  899. (*scan_r) += carry;
  900. }
  901. return (bignum_trim (r));
  902. #undef x_digit
  903. #undef y_digit
  904. #undef product_high
  905. }
  906. }
  907. static bignum_type
  908. bignum_multiply_unsigned_small_factor(bignum_type x, bignum_digit_type y,
  909. int negative_p)
  910. {
  911. bignum_length_type length_x = (BIGNUM_LENGTH (x));
  912. bignum_type p = (bignum_allocate ((length_x + 1), negative_p));
  913. bignum_destructive_copy (x, p);
  914. (BIGNUM_REF (p, length_x)) = 0;
  915. bignum_destructive_scale_up (p, y);
  916. return (bignum_trim (p));
  917. }
  918. static void
  919. bignum_destructive_scale_up(bignum_type bignum, bignum_digit_type factor)
  920. {
  921. bignum_digit_type carry = 0;
  922. bignum_digit_type * scan = (BIGNUM_START_PTR (bignum));
  923. bignum_digit_type two_digits;
  924. bignum_digit_type product_low;
  925. #define product_high carry
  926. bignum_digit_type * end = (scan + (BIGNUM_LENGTH (bignum)));
  927. BIGNUM_ASSERT ((factor > 1) && (factor < BIGNUM_RADIX_ROOT));
  928. while (scan < end)
  929. {
  930. two_digits = (*scan);
  931. product_low = ((factor * (HD_LOW (two_digits))) + (HD_LOW (carry)));
  932. product_high =
  933. ((factor * (HD_HIGH (two_digits))) +
  934. (HD_HIGH (product_low)) +
  935. (HD_HIGH (carry)));
  936. (*scan++) = (HD_CONS ((HD_LOW (product_high)), (HD_LOW (product_low))));
  937. carry = (HD_HIGH (product_high));
  938. }
  939. /* A carry here would be an overflow, i.e. it would not fit.
  940. Hopefully the callers allocate enough space that this will
  941. never happen.
  942. */
  943. BIGNUM_ASSERT (carry == 0);
  944. return;
  945. #undef product_high
  946. }
  947. static void
  948. bignum_destructive_add(bignum_type bignum, bignum_digit_type n)
  949. {
  950. bignum_digit_type * scan = (BIGNUM_START_PTR (bignum));
  951. bignum_digit_type digit;
  952. digit = ((*scan) + n);
  953. if (digit < BIGNUM_RADIX)
  954. {
  955. (*scan) = digit;
  956. return;
  957. }
  958. (*scan++) = (digit - BIGNUM_RADIX);
  959. while (1)
  960. {
  961. digit = ((*scan) + 1);
  962. if (digit < BIGNUM_RADIX)
  963. {
  964. (*scan) = digit;
  965. return;
  966. }
  967. (*scan++) = (digit - BIGNUM_RADIX);
  968. }
  969. }
  970. /* Division */
  971. /* For help understanding this algorithm, see:
  972. Knuth, Donald E., "The Art of Computer Programming",
  973. volume 2, "Seminumerical Algorithms"
  974. section 4.3.1, "Multiple-Precision Arithmetic". */
  975. static void
  976. bignum_divide_unsigned_large_denominator(bignum_type numerator,
  977. bignum_type denominator,
  978. bignum_type * quotient,
  979. bignum_type * remainder,
  980. int q_negative_p,
  981. int r_negative_p)
  982. {
  983. bignum_length_type length_n = ((BIGNUM_LENGTH (numerator)) + 1);
  984. bignum_length_type length_d = (BIGNUM_LENGTH (denominator));
  985. bignum_type q =
  986. ((quotient != ((bignum_type *) 0))
  987. ? (bignum_allocate ((length_n - length_d), q_negative_p))
  988. : BIGNUM_OUT_OF_BAND);
  989. bignum_type u = (bignum_allocate (length_n, r_negative_p));
  990. int shift = 0;
  991. BIGNUM_ASSERT (length_d > 1);
  992. {
  993. bignum_digit_type v1 = (BIGNUM_REF ((denominator), (length_d - 1)));
  994. while (v1 < (BIGNUM_RADIX / 2))
  995. {
  996. v1 <<= 1;
  997. shift += 1;
  998. }
  999. }
  1000. if (shift == 0)
  1001. {
  1002. bignum_destructive_copy (numerator, u);
  1003. (BIGNUM_REF (u, (length_n - 1))) = 0;
  1004. bignum_divide_unsigned_normalized (u, denominator, q);
  1005. }
  1006. else
  1007. {
  1008. bignum_type v = (bignum_allocate (length_d, 0));
  1009. bignum_destructive_normalization (numerator, u, shift);
  1010. bignum_destructive_normalization (denominator, v, shift);
  1011. bignum_divide_unsigned_normalized (u, v, q);
  1012. BIGNUM_DEALLOCATE (v);
  1013. if (remainder != ((bignum_type *) 0))
  1014. bignum_destructive_unnormalization (u, shift);
  1015. }
  1016. if (quotient != ((bignum_type *) 0))
  1017. (*quotient) = (bignum_trim (q));
  1018. if (remainder != ((bignum_type *) 0))
  1019. (*remainder) = (bignum_trim (u));
  1020. else
  1021. BIGNUM_DEALLOCATE (u);
  1022. return;
  1023. }
  1024. static void
  1025. bignum_divide_unsigned_normalized(bignum_type u, bignum_type v, bignum_type q)
  1026. {
  1027. bignum_length_type u_length = (BIGNUM_LENGTH (u));
  1028. bignum_length_type v_length = (BIGNUM_LENGTH (v));
  1029. bignum_digit_type * u_start = (BIGNUM_START_PTR (u));
  1030. bignum_digit_type * u_scan = (u_start + u_length);
  1031. bignum_digit_type * u_scan_limit = (u_start + v_length);
  1032. bignum_digit_type * u_scan_start = (u_scan - v_length);
  1033. bignum_digit_type * v_start = (BIGNUM_START_PTR (v));
  1034. bignum_digit_type * v_end = (v_start + v_length);
  1035. bignum_digit_type * q_scan;
  1036. bignum_digit_type v1 = (v_end[-1]);
  1037. bignum_digit_type v2 = (v_end[-2]);
  1038. bignum_digit_type ph; /* high half of double-digit product */
  1039. bignum_digit_type pl; /* low half of double-digit product */
  1040. bignum_digit_type guess;
  1041. bignum_digit_type gh; /* high half-digit of guess */
  1042. bignum_digit_type ch; /* high half of double-digit comparand */
  1043. bignum_digit_type v2l = (HD_LOW (v2));
  1044. bignum_digit_type v2h = (HD_HIGH (v2));
  1045. bignum_digit_type cl; /* low half of double-digit comparand */
  1046. #define gl ph /* low half-digit of guess */
  1047. #define uj pl
  1048. #define qj ph
  1049. bignum_digit_type gm; /* memory loc for reference parameter */
  1050. if (q != BIGNUM_OUT_OF_BAND)
  1051. q_scan = ((BIGNUM_START_PTR (q)) + (BIGNUM_LENGTH (q)));
  1052. while (u_scan_limit < u_scan)
  1053. {
  1054. uj = (*--u_scan);
  1055. if (uj != v1)
  1056. {
  1057. /* comparand =
  1058. (((((uj * BIGNUM_RADIX) + uj1) % v1) * BIGNUM_RADIX) + uj2);
  1059. guess = (((uj * BIGNUM_RADIX) + uj1) / v1); */
  1060. cl = (u_scan[-2]);
  1061. ch = (bignum_digit_divide (uj, (u_scan[-1]), v1, (&gm)));
  1062. guess = gm;
  1063. }
  1064. else
  1065. {
  1066. cl = (u_scan[-2]);
  1067. ch = ((u_scan[-1]) + v1);
  1068. guess = (BIGNUM_RADIX - 1);
  1069. }
  1070. while (1)
  1071. {
  1072. /* product = (guess * v2); */
  1073. gl = (HD_LOW (guess));
  1074. gh = (HD_HIGH (guess));
  1075. pl = (v2l * gl);
  1076. ph = ((v2l * gh) + (v2h * gl) + (HD_HIGH (pl)));
  1077. pl = (HD_CONS ((HD_LOW (ph)), (HD_LOW (pl))));
  1078. ph = ((v2h * gh) + (HD_HIGH (ph)));
  1079. /* if (comparand >= product) */
  1080. if ((ch > ph) || ((ch == ph) && (cl >= pl)))
  1081. break;
  1082. guess -= 1;
  1083. /* comparand += (v1 << BIGNUM_DIGIT_LENGTH) */
  1084. ch += v1;
  1085. /* if (comparand >= (BIGNUM_RADIX * BIGNUM_RADIX)) */
  1086. if (ch >= BIGNUM_RADIX)
  1087. break;
  1088. }
  1089. qj = (bignum_divide_subtract (v_start, v_end, guess, (--u_scan_start)));
  1090. if (q != BIGNUM_OUT_OF_BAND)
  1091. (*--q_scan) = qj;
  1092. }
  1093. return;
  1094. #undef gl
  1095. #undef uj
  1096. #undef qj
  1097. }
  1098. static bignum_digit_type
  1099. bignum_divide_subtract(bignum_digit_type * v_start,
  1100. bignum_digit_type * v_end,
  1101. bignum_digit_type guess,
  1102. bignum_digit_type * u_start)
  1103. {
  1104. bignum_digit_type * v_scan = v_start;
  1105. bignum_digit_type * u_scan = u_start;
  1106. bignum_digit_type carry = 0;
  1107. if (guess == 0) return (0);
  1108. {
  1109. bignum_digit_type gl = (HD_LOW (guess));
  1110. bignum_digit_type gh = (HD_HIGH (guess));
  1111. bignum_digit_type v;
  1112. bignum_digit_type pl;
  1113. bignum_digit_type vl;
  1114. #define vh v
  1115. #define ph carry
  1116. #define diff pl
  1117. while (v_scan < v_end)
  1118. {
  1119. v = (*v_scan++);
  1120. vl = (HD_LOW (v));
  1121. vh = (HD_HIGH (v));
  1122. pl = ((vl * gl) + (HD_LOW (carry)));
  1123. ph = ((vl * gh) + (vh * gl) + (HD_HIGH (pl)) + (HD_HIGH (carry)));
  1124. diff = ((*u_scan) - (HD_CONS ((HD_LOW (ph)), (HD_LOW (pl)))));
  1125. if (diff < 0)
  1126. {
  1127. (*u_scan++) = (diff + BIGNUM_RADIX);
  1128. carry = ((vh * gh) + (HD_HIGH (ph)) + 1);
  1129. }
  1130. else
  1131. {
  1132. (*u_scan++) = diff;
  1133. carry = ((vh * gh) + (HD_HIGH (ph)));
  1134. }
  1135. }
  1136. if (carry == 0)
  1137. return (guess);
  1138. diff = ((*u_scan) - carry);
  1139. if (diff < 0)
  1140. (*u_scan) = (diff + BIGNUM_RADIX);
  1141. else
  1142. {
  1143. (*u_scan) = diff;
  1144. return (guess);
  1145. }
  1146. #undef vh
  1147. #undef ph
  1148. #undef diff
  1149. }
  1150. /* Subtraction generated carry, implying guess is one too large.
  1151. Add v back in to bring it back down. */
  1152. v_scan = v_start;
  1153. u_scan = u_start;
  1154. carry = 0;
  1155. while (v_scan < v_end)
  1156. {
  1157. bignum_digit_type sum = ((*v_scan++) + (*u_scan) + carry);
  1158. if (sum < BIGNUM_RADIX)
  1159. {
  1160. (*u_scan++) = sum;
  1161. carry = 0;
  1162. }
  1163. else
  1164. {
  1165. (*u_scan++) = (sum - BIGNUM_RADIX);
  1166. carry = 1;
  1167. }
  1168. }
  1169. if (carry == 1)
  1170. {
  1171. bignum_digit_type sum = ((*u_scan) + carry);
  1172. (*u_scan) = ((sum < BIGNUM_RADIX) ? sum : (sum - BIGNUM_RADIX));
  1173. }
  1174. return (guess - 1);
  1175. }
  1176. static void
  1177. bignum_divide_unsigned_medium_denominator(bignum_type numerator,
  1178. bignum_digit_type denominator,
  1179. bignum_type * quotient,
  1180. bignum_type * remainder,
  1181. int q_negative_p,
  1182. int r_negative_p)
  1183. {
  1184. bignum_length_type length_n = (BIGNUM_LENGTH (numerator));
  1185. bignum_length_type length_q;
  1186. bignum_type q;
  1187. int shift = 0;
  1188. /* Because `bignum_digit_divide' requires a normalized denominator. */
  1189. while (denominator < (BIGNUM_RADIX / 2))
  1190. {
  1191. denominator <<= 1;
  1192. shift += 1;
  1193. }
  1194. if (shift == 0)
  1195. {
  1196. length_q = length_n;
  1197. q = (bignum_allocate (length_q, q_negative_p));
  1198. bignum_destructive_copy (numerator, q);
  1199. }
  1200. else
  1201. {
  1202. length_q = (length_n + 1);
  1203. q = (bignum_allocate (length_q, q_negative_p));
  1204. bignum_destructive_normalization (numerator, q, shift);
  1205. }
  1206. {
  1207. bignum_digit_type r = 0;
  1208. bignum_digit_type * start = (BIGNUM_START_PTR (q));
  1209. bignum_digit_type * scan = (start + length_q);
  1210. bignum_digit_type qj;
  1211. if (quotient != ((bignum_type *) 0))
  1212. {
  1213. while (start < scan)
  1214. {
  1215. r = (bignum_digit_divide (r, (*--scan), denominator, (&qj)));
  1216. (*scan) = qj;
  1217. }
  1218. (*quotient) = (bignum_trim (q));
  1219. }
  1220. else
  1221. {
  1222. while (start < scan)
  1223. r = (bignum_digit_divide (r, (*--scan), denominator, (&qj)));
  1224. BIGNUM_DEALLOCATE (q);
  1225. }
  1226. if (remainder != ((bignum_type *) 0))
  1227. {
  1228. if (shift != 0)
  1229. r >>= shift;
  1230. (*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
  1231. }
  1232. }
  1233. return;
  1234. }
  1235. static void
  1236. bignum_destructive_normalization(bignum_type source, bignum_type target,
  1237. int shift_left)
  1238. {
  1239. bignum_digit_type digit;
  1240. bignum_digit_type * scan_source = (BIGNUM_START_PTR (source));
  1241. bignum_digit_type carry = 0;
  1242. bignum_digit_type * scan_target = (BIGNUM_START_PTR (target));
  1243. bignum_digit_type * end_source = (scan_source + (BIGNUM_LENGTH (source)));
  1244. bignum_digit_type * end_target = (scan_target + (BIGNUM_LENGTH (target)));
  1245. int shift_right = (BIGNUM_DIGIT_LENGTH - shift_left);
  1246. bignum_digit_type mask = ((1L << shift_right) - 1);
  1247. while (scan_source < end_source)
  1248. {
  1249. digit = (*scan_source++);
  1250. (*scan_target++) = (((digit & mask) << shift_left) | carry);
  1251. carry = (digit >> shift_right);
  1252. }
  1253. if (scan_target < end_target)
  1254. (*scan_target) = carry;
  1255. else
  1256. BIGNUM_ASSERT (carry == 0);
  1257. return;
  1258. }
  1259. static void
  1260. bignum_destructive_unnormalization(bignum_type bignum, int shift_right)
  1261. {
  1262. bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
  1263. bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum)));
  1264. bignum_digit_type digit;
  1265. bignum_digit_type carry = 0;
  1266. int shift_left = (BIGNUM_DIGIT_LENGTH - shift_right);
  1267. bignum_digit_type mask = ((1L << shift_right) - 1);
  1268. while (start < scan)
  1269. {
  1270. digit = (*--scan);
  1271. (*scan) = ((digit >> shift_right) | carry);
  1272. carry = ((digit & mask) << shift_left);
  1273. }
  1274. BIGNUM_ASSERT (carry == 0);
  1275. return;
  1276. }
  1277. /* This is a reduced version of the division algorithm, applied to the
  1278. case of dividing two bignum digits by one bignum digit. It is
  1279. assumed that the numerator, denominator are normalized. */
  1280. #define BDD_STEP(qn, j) \
  1281. { \
  1282. uj = (u[j]); \
  1283. if (uj != v1) \
  1284. { \
  1285. uj_uj1 = (HD_CONS (uj, (u[j + 1]))); \
  1286. guess = (uj_uj1 / v1); \
  1287. comparand = (HD_CONS ((uj_uj1 % v1), (u[j + 2]))); \
  1288. } \
  1289. else \
  1290. { \
  1291. guess = (BIGNUM_RADIX_ROOT - 1); \
  1292. comparand = (HD_CONS (((u[j + 1]) + v1), (u[j + 2]))); \
  1293. } \
  1294. while ((guess * v2) > comparand) \
  1295. { \
  1296. guess -= 1; \
  1297. comparand += (v1 << BIGNUM_HALF_DIGIT_LENGTH); \
  1298. if (comparand >= BIGNUM_RADIX) \
  1299. break; \
  1300. } \
  1301. qn = (bignum_digit_divide_subtract (v1, v2, guess, (&u[j]))); \
  1302. }
  1303. static bignum_digit_type
  1304. bignum_digit_divide(bignum_digit_type uh, bignum_digit_type ul,
  1305. bignum_digit_type v,
  1306. bignum_digit_type * q) /* return value */
  1307. {
  1308. bignum_digit_type guess;
  1309. bignum_digit_type comparand;
  1310. bignum_digit_type v1 = (HD_HIGH (v));
  1311. bignum_digit_type v2 = (HD_LOW (v));
  1312. bignum_digit_type uj;
  1313. bignum_digit_type uj_uj1;
  1314. bignum_digit_type q1;
  1315. bignum_digit_type q2;
  1316. bignum_digit_type u [4];
  1317. if (uh == 0)
  1318. {
  1319. if (ul < v)
  1320. {
  1321. (*q) = 0;
  1322. return (ul);
  1323. }
  1324. else if (ul == v)
  1325. {
  1326. (*q) = 1;
  1327. return (0);
  1328. }
  1329. }
  1330. (u[0]) = (HD_HIGH (uh));
  1331. (u[1]) = (HD_LOW (uh));
  1332. (u[2]) = (HD_HIGH (ul));
  1333. (u[3]) = (HD_LOW (ul));
  1334. v1 = (HD_HIGH (v));
  1335. v2 = (HD_LOW (v));
  1336. BDD_STEP (q1, 0);
  1337. BDD_STEP (q2, 1);
  1338. (*q) = (HD_CONS (q1, q2));
  1339. return (HD_CONS ((u[2]), (u[3])));
  1340. }
  1341. #undef BDD_STEP
  1342. #define BDDS_MULSUB(vn, un, carry_in) \
  1343. { \
  1344. product = ((vn * guess) + carry_in); \
  1345. diff = (un - (HD_LOW (product))); \
  1346. if (diff < 0) \
  1347. { \
  1348. un = (diff + BIGNUM_RADIX_ROOT); \
  1349. carry = ((HD_HIGH (product)) + 1); \
  1350. } \
  1351. else \
  1352. { \
  1353. un = diff; \
  1354. carry = (HD_HIGH (product)); \
  1355. } \
  1356. }
  1357. #define BDDS_ADD(vn, un, carry_in) \
  1358. { \
  1359. sum = (vn + un + carry_in); \
  1360. if (sum < BIGNUM_RADIX_ROOT) \
  1361. { \
  1362. un = sum; \
  1363. carry = 0; \
  1364. } \
  1365. else \
  1366. { \
  1367. un = (sum - BIGNUM_RADIX_ROOT); \
  1368. carry = 1; \
  1369. } \
  1370. }
  1371. static bignum_digit_type
  1372. bignum_digit_divide_subtract(bignum_digit_type v1, bignum_digit_type v2,
  1373. bignum_digit_type guess, bignum_digit_type * u)
  1374. {
  1375. {
  1376. bignum_digit_type product;
  1377. bignum_digit_type diff;
  1378. bignum_digit_type carry;
  1379. BDDS_MULSUB (v2, (u[2]), 0);
  1380. BDDS_MULSUB (v1, (u[1]), carry);
  1381. if (carry == 0)
  1382. return (guess);
  1383. diff = ((u[0]) - carry);
  1384. if (diff < 0)
  1385. (u[0]) = (diff + BIGNUM_RADIX);
  1386. else
  1387. {
  1388. (u[0]) = diff;
  1389. return (guess);
  1390. }
  1391. }
  1392. {
  1393. bignum_digit_type sum;
  1394. bignum_digit_type carry;
  1395. BDDS_ADD(v2, (u[2]), 0);
  1396. BDDS_ADD(v1, (u[1]), carry);
  1397. if (carry == 1)
  1398. (u[0]) += 1;
  1399. }
  1400. return (guess - 1);
  1401. }
  1402. #undef BDDS_MULSUB
  1403. #undef BDDS_ADD
  1404. static void
  1405. bignum_divide_unsigned_small_denominator(bignum_type numerator,
  1406. bignum_digit_type denominator,
  1407. bignum_type * quotient,
  1408. bignum_type * remainder,
  1409. int q_negative_p,
  1410. int r_negative_p)
  1411. {
  1412. bignum_type q = (bignum_new_sign (numerator, q_negative_p));
  1413. bignum_digit_type r = (bignum_destructive_scale_down (q, denominator));
  1414. (*quotient) = (bignum_trim (q));
  1415. if (remainder != ((bignum_type *) 0))
  1416. (*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
  1417. return;
  1418. }
  1419. /* Given (denominator > 1), it is fairly easy to show that
  1420. (quotient_high < BIGNUM_RADIX_ROOT), after which it is easy to see
  1421. that all digits are < BIGNUM_RADIX. */
  1422. static bignum_digit_type
  1423. bignum_destructive_scale_down(bignum_type bignum, bignum_digit_type denominator)
  1424. {
  1425. bignum_digit_type numerator;
  1426. bignum_digit_type remainder = 0;
  1427. bignum_digit_type two_digits;
  1428. #define quotient_high remainder
  1429. bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
  1430. bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum)));
  1431. BIGNUM_ASSERT ((denominator > 1) && (denominator < BIGNUM_RADIX_ROOT));
  1432. while (start < scan)
  1433. {
  1434. two_digits = (*--scan);
  1435. numerator = (HD_CONS (remainder, (HD_HIGH (two_digits))));
  1436. quotient_high = (numerator / denominator);
  1437. numerator = (HD_CONS ((numerator % denominator), (HD_LOW (two_digits))));
  1438. (*scan) = (HD_CONS (quotient_high, (numerator / denominator)));
  1439. remainder = (numerator % denominator);
  1440. }
  1441. return (remainder);
  1442. #undef quotient_high
  1443. }
  1444. static bignum_type
  1445. bignum_remainder_unsigned_small_denominator(
  1446. bignum_type n, bignum_digit_type d, int negative_p)
  1447. {
  1448. bignum_digit_type two_digits;
  1449. bignum_digit_type * start = (BIGNUM_START_PTR (n));
  1450. bignum_digit_type * scan = (start + (BIGNUM_LENGTH (n)));
  1451. bignum_digit_type r = 0;
  1452. BIGNUM_ASSERT ((d > 1) && (d < BIGNUM_RADIX_ROOT));
  1453. while (start < scan)
  1454. {
  1455. two_digits = (*--scan);
  1456. r =
  1457. ((HD_CONS (((HD_CONS (r, (HD_HIGH (two_digits)))) % d),
  1458. (HD_LOW (two_digits))))
  1459. % d);
  1460. }
  1461. return (bignum_digit_to_bignum (r, negative_p));
  1462. }
  1463. static bignum_type
  1464. bignum_digit_to_bignum(bignum_digit_type digit, int negative_p)
  1465. {
  1466. if (digit == 0)
  1467. return (BIGNUM_ZERO ());
  1468. else
  1469. {
  1470. bignum_type result = (bignum_allocate (1, negative_p));
  1471. (BIGNUM_REF (result, 0)) = digit;
  1472. return (result);
  1473. }
  1474. }
  1475. /* Allocation */
  1476. static bignum_type
  1477. bignum_allocate(bignum_length_type length, int negative_p)
  1478. {
  1479. BIGNUM_ASSERT ((length >= 0) || (length < BIGNUM_RADIX));
  1480. {
  1481. bignum_type result = (BIGNUM_ALLOCATE (length));
  1482. BIGNUM_SET_HEADER (result, length, negative_p);
  1483. return (result);
  1484. }
  1485. }
  1486. static bignum_type
  1487. bignum_allocate_zeroed(bignum_length_type length, int negative_p)
  1488. {
  1489. BIGNUM_ASSERT ((length >= 0) || (length < BIGNUM_RADIX));
  1490. {
  1491. bignum_type result = (BIGNUM_ALLOCATE (length));
  1492. bignum_digit_type * scan = (BIGNUM_START_PTR (result));
  1493. bignum_digit_type * end = (scan + length);
  1494. BIGNUM_SET_HEADER (result, length, negative_p);
  1495. while (scan < end)
  1496. (*scan++) = 0;
  1497. return (result);
  1498. }
  1499. }
  1500. static bignum_type
  1501. bignum_shorten_length(bignum_type bignum, bignum_length_type length)
  1502. {
  1503. bignum_length_type current_length = (BIGNUM_LENGTH (bignum));
  1504. BIGNUM_ASSERT ((length >= 0) || (length <= current_length));
  1505. if (length < current_length)
  1506. {
  1507. BIGNUM_SET_HEADER
  1508. (bignum, length, ((length != 0) && (BIGNUM_NEGATIVE_P (bignum))));
  1509. BIGNUM_REDUCE_LENGTH (bignum, bignum, length);
  1510. }
  1511. return (bignum);
  1512. }
  1513. static bignum_type
  1514. bignum_trim(bignum_type bignum)
  1515. {
  1516. bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
  1517. bignum_digit_type * end = (start + (BIGNUM_LENGTH (bignum)));
  1518. bignum_digit_type * scan = end;
  1519. while ((start <= scan) && ((*--scan) == 0))
  1520. ;
  1521. scan += 1;
  1522. if (scan < end)
  1523. {
  1524. bignum_length_type length = (scan - start);
  1525. BIGNUM_SET_HEADER
  1526. (bignum, length, ((length != 0) && (BIGNUM_NEGATIVE_P (bignum))));
  1527. BIGNUM_REDUCE_LENGTH (bignum, bignum, length);
  1528. }
  1529. return (bignum);
  1530. }
  1531. /* Copying */
  1532. static bignum_type
  1533. bignum_copy(bignum_type source)
  1534. {
  1535. bignum_type target =
  1536. (bignum_allocate ((BIGNUM_LENGTH (source)), (BIGNUM_NEGATIVE_P (source))));
  1537. bignum_destructive_copy (source, target);
  1538. return (target);
  1539. }
  1540. static bignum_type
  1541. bignum_new_sign(bignum_type bignum, int negative_p)
  1542. {
  1543. bignum_type result =
  1544. (bignum_allocate ((BIGNUM_LENGTH (bignum)), negative_p));
  1545. bignum_destructive_copy (bignum, result);
  1546. return (result);
  1547. }
  1548. static bignum_type
  1549. bignum_maybe_new_sign(bignum_type bignum, int negative_p)
  1550. {
  1551. #ifndef BIGNUM_FORCE_NEW_RESULTS
  1552. if ((BIGNUM_NEGATIVE_P (bignum)) ? negative_p : (! negative_p))
  1553. return (bignum);
  1554. else
  1555. #endif /* not BIGNUM_FORCE_NEW_RESULTS */
  1556. {
  1557. bignum_type result =
  1558. (bignum_allocate ((BIGNUM_LENGTH (bignum)), negative_p));
  1559. bignum_destructive_copy (bignum, result);
  1560. return (result);
  1561. }
  1562. }
  1563. static void
  1564. bignum_destructive_copy(bignum_type source, bignum_type target)
  1565. {
  1566. bignum_digit_type * scan_source = (BIGNUM_START_PTR (source));
  1567. bignum_digit_type * end_source =
  1568. (scan_source + (BIGNUM_LENGTH (source)));
  1569. bignum_digit_type * scan_target = (BIGNUM_START_PTR (target));
  1570. while (scan_source < end_source)
  1571. (*scan_target++) = (*scan_source++);
  1572. return;
  1573. }
  1574. /* Unused
  1575. static void
  1576. bignum_destructive_zero(bignum_type bignum)
  1577. {
  1578. bignum_digit_type * scan = (BIGNUM_START_PTR (bignum));
  1579. bignum_digit_type * end = (scan + (BIGNUM_LENGTH (bignum)));
  1580. while (scan < end)
  1581. (*scan++) = 0;
  1582. return;
  1583. }
  1584. */
  1585. /*
  1586. * Added bitwise operations (and oddp).
  1587. */
  1588. int
  1589. s48_bignum_oddp (bignum_type bignum)
  1590. {
  1591. return (BIGNUM_LENGTH (bignum) > 0) && (BIGNUM_REF (bignum, 0) & 1);
  1592. }
  1593. bignum_type
  1594. s48_bignum_bitwise_not(bignum_type x)
  1595. {
  1596. return s48_bignum_subtract(BIGNUM_ONE(1), x);
  1597. }
  1598. bignum_type
  1599. s48_bignum_arithmetic_shift(bignum_type arg1, long n)
  1600. {
  1601. if (BIGNUM_NEGATIVE_P(arg1) && n < 0)
  1602. return
  1603. s48_bignum_bitwise_not(bignum_magnitude_ash(s48_bignum_bitwise_not(arg1),
  1604. n));
  1605. else
  1606. return bignum_magnitude_ash(arg1, n);
  1607. }
  1608. /*
  1609. * This uses a `long'-returning bignum_length_in_bits() which we don't have.
  1610. long
  1611. s48_bignum_integer_length(bignum_type arg1)
  1612. {
  1613. return((BIGNUM_NEGATIVE_P (arg1))
  1614. ? bignum_length_in_bits (s48_bignum_bitwise_not (arg1))
  1615. : bignum_length_in_bits (arg1));
  1616. }
  1617. */
  1618. long
  1619. s48_bignum_bit_count(bignum_type arg1)
  1620. {
  1621. return((BIGNUM_NEGATIVE_P (arg1))
  1622. ? bignum_unsigned_logcount (s48_bignum_bitwise_not (arg1))
  1623. : bignum_unsigned_logcount (arg1));
  1624. }
  1625. #define AND_OP 0
  1626. #define IOR_OP 1
  1627. #define XOR_OP 2
  1628. bignum_type
  1629. s48_bignum_bitwise_and(bignum_type arg1, bignum_type arg2)
  1630. {
  1631. return(
  1632. (BIGNUM_NEGATIVE_P (arg1))
  1633. ? (BIGNUM_NEGATIVE_P (arg2))
  1634. ? bignum_negneg_bitwise_op(AND_OP, arg1, arg2)
  1635. : bignum_posneg_bitwise_op(AND_OP, arg2, arg1)
  1636. : (BIGNUM_NEGATIVE_P (arg2))
  1637. ? bignum_posneg_bitwise_op(AND_OP, arg1, arg2)
  1638. : bignum_pospos_bitwise_op(AND_OP, arg1, arg2)
  1639. );
  1640. }
  1641. bignum_type
  1642. s48_bignum_bitwise_ior(bignum_type arg1, bignum_type arg2)
  1643. {
  1644. return(
  1645. (BIGNUM_NEGATIVE_P (arg1))
  1646. ? (BIGNUM_NEGATIVE_P (arg2))
  1647. ? bignum_negneg_bitwise_op(IOR_OP, arg1, arg2)
  1648. : bignum_posneg_bitwise_op(IOR_OP, arg2, arg1)
  1649. : (BIGNUM_NEGATIVE_P (arg2))
  1650. ? bignum_posneg_bitwise_op(IOR_OP, arg1, arg2)
  1651. : bignum_pospos_bitwise_op(IOR_OP, arg1, arg2)
  1652. );
  1653. }
  1654. bignum_type
  1655. s48_bignum_bitwise_xor(bignum_type arg1, bignum_type arg2)
  1656. {
  1657. return(
  1658. (BIGNUM_NEGATIVE_P (arg1))
  1659. ? (BIGNUM_NEGATIVE_P (arg2))
  1660. ? bignum_negneg_bitwise_op(XOR_OP, arg1, arg2)
  1661. : bignum_posneg_bitwise_op(XOR_OP, arg2, arg1)
  1662. : (BIGNUM_NEGATIVE_P (arg2))
  1663. ? bignum_posneg_bitwise_op(XOR_OP, arg1, arg2)
  1664. : bignum_pospos_bitwise_op(XOR_OP, arg1, arg2)
  1665. );
  1666. }
  1667. /* ash for the magnitude */
  1668. /* assume arg1 is a big number, n is a long */
  1669. static bignum_type
  1670. bignum_magnitude_ash(bignum_type arg1, long n)
  1671. {
  1672. bignum_type result;
  1673. bignum_digit_type *scan1;
  1674. bignum_digit_type *scanr;
  1675. bignum_digit_type *end;
  1676. long digit_offset,bit_offset;
  1677. if (BIGNUM_ZERO_P (arg1)) return (arg1);
  1678. if (n > 0) {
  1679. digit_offset = n / BIGNUM_DIGIT_LENGTH;
  1680. bit_offset = n % BIGNUM_DIGIT_LENGTH;
  1681. result = bignum_allocate_zeroed (BIGNUM_LENGTH (arg1) + digit_offset + 1,
  1682. BIGNUM_NEGATIVE_P(arg1));
  1683. scanr = BIGNUM_START_PTR (result) + digit_offset;
  1684. scan1 = BIGNUM_START_PTR (arg1);
  1685. end = scan1 + BIGNUM_LENGTH (arg1);
  1686. while (scan1 < end) {
  1687. *scanr = *scanr | (*scan1 & BIGNUM_DIGIT_MASK) << bit_offset;
  1688. *scanr = *scanr & BIGNUM_DIGIT_MASK;
  1689. scanr++;
  1690. *scanr = *scan1++ >> (BIGNUM_DIGIT_LENGTH - bit_offset);
  1691. *scanr = *scanr & BIGNUM_DIGIT_MASK;
  1692. }
  1693. }
  1694. else if (n < 0
  1695. && (-n >= (BIGNUM_LENGTH (arg1) * (bignum_length_type) BIGNUM_DIGIT_LENGTH)))
  1696. result = BIGNUM_ZERO ();
  1697. else if (n < 0) {
  1698. digit_offset = -n / BIGNUM_DIGIT_LENGTH;
  1699. bit_offset = -n % BIGNUM_DIGIT_LENGTH;
  1700. result = bignum_allocate_zeroed (BIGNUM_LENGTH (arg1) - digit_offset,
  1701. BIGNUM_NEGATIVE_P(arg1));
  1702. scanr = BIGNUM_START_PTR (result);
  1703. scan1 = BIGNUM_START_PTR (arg1) + digit_offset;
  1704. end = scanr + BIGNUM_LENGTH (result) - 1;
  1705. while (scanr < end) {
  1706. *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset ;
  1707. *scanr = (*scanr |
  1708. *scan1 << (BIGNUM_DIGIT_LENGTH - bit_offset)) & BIGNUM_DIGIT_MASK;
  1709. scanr++;
  1710. }
  1711. *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset ;
  1712. }
  1713. else if (n == 0) result = arg1;
  1714. return (bignum_trim (result));
  1715. }
  1716. static bignum_type
  1717. bignum_pospos_bitwise_op(int op, bignum_type arg1, bignum_type arg2)
  1718. {
  1719. bignum_type result;
  1720. bignum_length_type max_length;
  1721. bignum_digit_type *scan1, *end1, digit1;
  1722. bignum_digit_type *scan2, *end2, digit2;
  1723. bignum_digit_type *scanr, *endr;
  1724. max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
  1725. ? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2);
  1726. result = bignum_allocate(max_length, 0);
  1727. scanr = BIGNUM_START_PTR(result);
  1728. scan1 = BIGNUM_START_PTR(arg1);
  1729. scan2 = BIGNUM_START_PTR(arg2);
  1730. endr = scanr + max_length;
  1731. end1 = scan1 + BIGNUM_LENGTH(arg1);
  1732. end2 = scan2 + BIGNUM_LENGTH(arg2);
  1733. while (scanr < endr) {
  1734. digit1 = (scan1 < end1) ? *scan1++ : 0;
  1735. digit2 = (scan2 < end2) ? *scan2++ : 0;
  1736. /*
  1737. fprintf(stderr, "[pospos op = %d, i = %ld, d1 = %lx, d2 = %lx]\n",
  1738. op, endr - scanr, digit1, digit2);
  1739. */
  1740. *scanr++ = (op == 0) ? digit1 & digit2 :
  1741. (op == 1) ? digit1 | digit2 :
  1742. digit1 ^ digit2;
  1743. }
  1744. return bignum_trim(result);
  1745. }
  1746. static bignum_type
  1747. bignum_posneg_bitwise_op(int op, bignum_type arg1, bignum_type arg2)
  1748. {
  1749. bignum_type result;
  1750. bignum_length_type max_length;
  1751. bignum_digit_type *scan1, *end1, digit1;
  1752. bignum_digit_type *scan2, *end2, digit2, carry2;
  1753. bignum_digit_type *scanr, *endr;
  1754. char neg_p = op == IOR_OP || op == XOR_OP;
  1755. max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2) + 1)
  1756. ? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2) + 1;
  1757. result = bignum_allocate(max_length, neg_p);
  1758. scanr = BIGNUM_START_PTR(result);
  1759. scan1 = BIGNUM_START_PTR(arg1);
  1760. scan2 = BIGNUM_START_PTR(arg2);
  1761. endr = scanr + max_length;
  1762. end1 = scan1 + BIGNUM_LENGTH(arg1);
  1763. end2 = scan2 + BIGNUM_LENGTH(arg2);
  1764. carry2 = 1;
  1765. while (scanr < endr) {
  1766. digit1 = (scan1 < end1) ? *scan1++ : 0;
  1767. digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK)
  1768. + carry2;
  1769. if (digit2 < BIGNUM_RADIX)
  1770. carry2 = 0;
  1771. else
  1772. {
  1773. digit2 = (digit2 - BIGNUM_RADIX);
  1774. carry2 = 1;
  1775. }
  1776. *scanr++ = (op == AND_OP) ? digit1 & digit2 :
  1777. (op == IOR_OP) ? digit1 | digit2 :
  1778. digit1 ^ digit2;
  1779. }
  1780. if (neg_p)
  1781. bignum_negate_magnitude(result);
  1782. return bignum_trim(result);
  1783. }
  1784. static bignum_type
  1785. bignum_negneg_bitwise_op(int op, bignum_type arg1, bignum_type arg2)
  1786. {
  1787. bignum_type result;
  1788. bignum_length_type max_length;
  1789. bignum_digit_type *scan1, *end1, digit1, carry1;
  1790. bignum_digit_type *scan2, *end2, digit2, carry2;
  1791. bignum_digit_type *scanr, *endr;
  1792. char neg_p = op == AND_OP || op == IOR_OP;
  1793. max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
  1794. ? BIGNUM_LENGTH(arg1) + 1 : BIGNUM_LENGTH(arg2) + 1;
  1795. result = bignum_allocate(max_length, neg_p);
  1796. scanr = BIGNUM_START_PTR(result);
  1797. scan1 = BIGNUM_START_PTR(arg1);
  1798. scan2 = BIGNUM_START_PTR(arg2);
  1799. endr = scanr + max_length;
  1800. end1 = scan1 + BIGNUM_LENGTH(arg1);
  1801. end2 = scan2 + BIGNUM_LENGTH(arg2);
  1802. carry1 = 1;
  1803. carry2 = 1;
  1804. while (scanr < endr) {
  1805. digit1 = (~((scan1 < end1) ? *scan1++ : 0) & BIGNUM_DIGIT_MASK) + carry1;
  1806. digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK) + carry2;
  1807. if (digit1 < BIGNUM_RADIX)
  1808. carry1 = 0;
  1809. else
  1810. {
  1811. digit1 = (digit1 - BIGNUM_RADIX);
  1812. carry1 = 1;
  1813. }
  1814. if (digit2 < BIGNUM_RADIX)
  1815. carry2 = 0;
  1816. else
  1817. {
  1818. digit2 = (digit2 - BIGNUM_RADIX);
  1819. carry2 = 1;
  1820. }
  1821. *scanr++ = (op == 0) ? digit1 & digit2 :
  1822. (op == 1) ? digit1 | digit2 :
  1823. digit1 ^ digit2;
  1824. }
  1825. if (neg_p)
  1826. bignum_negate_magnitude(result);
  1827. return bignum_trim(result);
  1828. }
  1829. static void
  1830. bignum_negate_magnitude(bignum_type arg)
  1831. {
  1832. bignum_digit_type *scan;
  1833. bignum_digit_type *end;
  1834. bignum_digit_type digit;
  1835. bignum_digit_type carry;
  1836. scan = BIGNUM_START_PTR(arg);
  1837. end = scan + BIGNUM_LENGTH(arg);
  1838. carry = 1;
  1839. while (scan < end) {
  1840. digit = (~*scan & BIGNUM_DIGIT_MASK) + carry;
  1841. if (digit < BIGNUM_RADIX)
  1842. carry = 0;
  1843. else
  1844. {
  1845. digit = (digit - BIGNUM_RADIX);
  1846. carry = 1;
  1847. }
  1848. *scan++ = digit;
  1849. }
  1850. }
  1851. static long
  1852. bignum_unsigned_logcount(bignum_type arg)
  1853. {
  1854. bignum_digit_type *scan;
  1855. bignum_digit_type *end;
  1856. bignum_digit_type digit;
  1857. /* sufficient for any reasonable big number */
  1858. long result;
  1859. unsigned long i;
  1860. if (BIGNUM_ZERO_P (arg)) return (0L);
  1861. scan = BIGNUM_START_PTR (arg);
  1862. end = scan + BIGNUM_LENGTH (arg);
  1863. result = 0L;
  1864. while (scan < end) {
  1865. digit = *scan++ & BIGNUM_DIGIT_MASK;
  1866. for (i = 0; i++ < BIGNUM_DIGIT_LENGTH; digit = digit >> 1L)
  1867. result += digit & 1L;
  1868. }
  1869. return (result);
  1870. }
  1871. int
  1872. bignum_logbitp(int shift, bignum_type arg)
  1873. {
  1874. return((BIGNUM_NEGATIVE_P (arg))
  1875. ? !bignum_unsigned_logbitp (shift, s48_bignum_bitwise_not (arg))
  1876. : bignum_unsigned_logbitp (shift,arg));
  1877. }
  1878. static int
  1879. bignum_unsigned_logbitp(int shift, bignum_type bignum)
  1880. {
  1881. bignum_length_type len = (BIGNUM_LENGTH (bignum));
  1882. bignum_digit_type digit;
  1883. int index = shift / BIGNUM_DIGIT_LENGTH;
  1884. int p;
  1885. if (index >= len)
  1886. return 0;
  1887. digit = (BIGNUM_REF (bignum, index));
  1888. p = shift % BIGNUM_DIGIT_LENGTH;
  1889. return digit & (1 << p);
  1890. }