bignum.c 56 KB

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