bignum.c 56 KB

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