PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/phobos/std/bigint.d

#
D | 2273 lines | 1749 code | 307 blank | 217 comment | 294 complexity | b93b31d1324ca1852bdf9a5d9b808999 MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. // Written in the D programming language.
  2. /**
  3. Provides a BigInt struct for multiprecision integer arithmetic.
  4. The internal representation is binary, not decimal.
  5. All relevant operators are overloaded.
  6. Example:
  7. ----------------------------------------------------
  8. BigInt a = "9588669891916142";
  9. BigInt b = "7452469135154800";
  10. auto c = a * b;
  11. assert(c == "71459266416693160362545788781600");
  12. auto d = b * a;
  13. assert(d == "71459266416693160362545788781600");
  14. assert(d == c);
  15. d = c * "794628672112";
  16. assert(d == "56783581982794522489042432639320434378739200");
  17. auto e = c + d;
  18. assert(e == "56783581982865981755459125799682980167520800");
  19. auto f = d + c;
  20. assert(f == e);
  21. auto g = f - c;
  22. assert(g == d);
  23. g = f - d;
  24. assert(g == c);
  25. e = 12345678;
  26. g = c + e;
  27. auto h = g / b;
  28. auto i = g % b;
  29. assert(h == a);
  30. assert(i == e);
  31. ----------------------------------------------------
  32. Authors: Janice Caron
  33. Date: 2008.05.18
  34. License: Public Domain
  35. Macros:
  36. WIKI=Phobos/StdBigint
  37. */
  38. module bigint;
  39. import std.string : format;
  40. import std.stdio : writef, writefln;
  41. import std.algorithm : min, max, swap, reverse;
  42. import std.traits : isIntegral;
  43. import std.contracts : assumeUnique;
  44. alias uint Digit; /// alias for uint
  45. /******************
  46. * Struct representing a multiprecision integer
  47. */
  48. struct BigInt
  49. {
  50. Digits digits = [ cast(Digit)0 ];
  51. static const BigInt ZERO = { [ cast(Digit)0 ] };
  52. static const BigInt ONE = { [ cast(Digit)1 ] };
  53. ///
  54. void opAssign(const BigInt n)
  55. {
  56. digits = n.digits;
  57. }
  58. ///
  59. void opAssign(int n)
  60. {
  61. digits = cast(Digits)( [ cast(Digit)n ] );
  62. }
  63. ///
  64. void opAssign(uint n)
  65. {
  66. static if(BIG_ENDIAN) { Digits a = [ cast(Digit)0, n ]; }
  67. else { Digits a = [ cast(Digit)n, 0 ]; }
  68. Big b = bigInt(a);
  69. digits = b.digits;
  70. }
  71. ///
  72. void opAssign(long n)
  73. {
  74. static if(BIG_ENDIAN) { Digits a = [ cast(Digit)(n>>32), cast(Digit)n ]; }
  75. else { Digits a = [ cast(Digit)n, cast(Digit)(n>>32) ]; }
  76. Big b = bigInt(a);
  77. digits = b.digits;
  78. }
  79. ///
  80. void opAssign(ulong n)
  81. {
  82. static if(BIG_ENDIAN) { Digits a = [ cast(Digit)0, cast(Digit)(n>>32), cast(Digit)n ]; }
  83. else { Digits a = [ cast(Digit)n, cast(Digit)(n>>32), cast(Digit)0 ]; }
  84. Big b = bigInt(a);
  85. digits = b.digits;
  86. }
  87. ///
  88. void opAssign(string s)
  89. {
  90. Big b = fromString(s);
  91. digits = b.digits;
  92. }
  93. ///
  94. static BigInt opCall(T)(T n)
  95. {
  96. BigInt r;
  97. r.opAssign(n);
  98. return r;
  99. }
  100. // Convert TO other types
  101. ///
  102. void castTo(out BigInt r) const
  103. {
  104. r.digits = digits;
  105. }
  106. ///
  107. void castTo(out int r) const
  108. {
  109. r = cast(int)tail(digits,1u)[0];
  110. }
  111. ///
  112. void castTo(out uint r) const
  113. {
  114. r = cast(uint)tail(digits,1u)[0];
  115. }
  116. ///
  117. void castTo(out long r) const
  118. {
  119. ulong t;
  120. castTo(t);
  121. r = cast(long)t;
  122. }
  123. ///
  124. void castTo(out ulong r) const
  125. {
  126. mixin(setUp("x","this"));
  127. r = peek(xp);
  128. xp = next(xp);
  129. if (xp != xe) r += cast(ulong)(peek(xp)) << 32;
  130. }
  131. ///
  132. void castTo(out string r) const
  133. {
  134. r = decimal(this);
  135. }
  136. // Unary operator overloads
  137. ///
  138. BigInt opPos() const
  139. {
  140. BigInt r;
  141. r.digits = digits;
  142. return r;
  143. }
  144. ///
  145. BigInt opNeg() const
  146. {
  147. return neg(this);
  148. }
  149. ///
  150. BigInt opCom() const
  151. {
  152. return com(this);
  153. }
  154. ///
  155. BigInt opPostInc()
  156. {
  157. BigInt n = this;
  158. opAddAssign(1);
  159. return n;
  160. }
  161. ///
  162. BigInt opPostDec()
  163. {
  164. BigInt n = this;
  165. opSubAssign(1);
  166. return n;
  167. }
  168. // Binary operator overloads
  169. ///
  170. BigInt opAdd(T)(T n) const
  171. {
  172. return opAdd(BigInt(n));
  173. }
  174. ///
  175. BigInt opAdd(T:int)(T n) const
  176. {
  177. return add(this,cast(Digit)n);
  178. }
  179. ///
  180. BigInt opAdd(T:const(BigInt))(T n) const
  181. {
  182. return add(this,n);
  183. }
  184. ///
  185. void opAddAssign(T)(T n)
  186. {
  187. auto r = opAdd(n);
  188. digits = r.digits;
  189. }
  190. ///
  191. BigInt opSub(T)(T n) const
  192. {
  193. return opSub(BigInt(n));
  194. }
  195. ///
  196. BigInt opSub(T:int)(T n) const
  197. {
  198. return sub(this,cast(Digit)n);
  199. }
  200. ///
  201. BigInt opSub(T:const(BigInt))(T n) const
  202. {
  203. return sub(this,n);
  204. }
  205. ///
  206. void opSubAssign(T)(T n)
  207. {
  208. auto r = opSub(n);
  209. digits = r.digits;
  210. }
  211. ///
  212. BigInt opMul(T)(T n) const
  213. {
  214. return opMul(BigInt(n));
  215. }
  216. ///
  217. BigInt opMul(T:int)(T n) const
  218. {
  219. if (cast(int)n == int.min) return opMul(BigInt(n));
  220. int xs = sgn;
  221. if (xs == 0 || n == 0) return BigInt.ZERO;
  222. int ys = n > 0 ? 1 : -1;
  223. auto x = abs;
  224. auto y = n > 0 ? n : -n;
  225. auto r = mul(x,y);
  226. return (xs == ys) ? r : -r;
  227. }
  228. ///
  229. BigInt opMul(T:const(BigInt))(T n) const
  230. {
  231. int xs = sgn;
  232. int ys = n.sgn;
  233. if (xs == 0 || ys == 0) return BigInt.ZERO;
  234. auto x = abs;
  235. auto y = n.abs;
  236. auto r = mul(x,y);
  237. return (xs == ys) ? r : -r;
  238. }
  239. ///
  240. void opMulAssign(T)(T n)
  241. {
  242. auto r = opMul(n);
  243. digits = r.digits;
  244. }
  245. /*
  246. Here's how the signs work
  247. 7 / 3 = 2
  248. 7 % 3 = 1
  249. 7 / -3 = -2
  250. 7 % -3 = 1
  251. -7 / 3 = -2
  252. -7 % 3 = -1
  253. -7 / -3 = 2
  254. -7 % -3 = -1
  255. */
  256. ///
  257. BigInt opDiv(T)(T n) const
  258. {
  259. return opDiv(BigInt(n));
  260. }
  261. ///
  262. BigInt opDiv(T:int)(T n) const
  263. {
  264. if (n == 0) throw new Exception("Divide by zero");
  265. if (cast(int)n == int.min) return opDiv(BigInt(n));
  266. int xs = sgn;
  267. int ys = n > 0 ? 1 : -1;
  268. if (xs == 0) return BigInt.ZERO;
  269. auto x = abs;
  270. auto y = n > 0 ? n : -n;
  271. auto r = div(x,y);
  272. return (xs == ys) ? r.q : -r.q;
  273. }
  274. ///
  275. BigInt opDiv(T:const(BigInt))(T n) const
  276. {
  277. int xs = sgn;
  278. int ys = n.sgn;
  279. if (ys == 0) throw new Exception("Divide by zero");
  280. if (xs == 0) return BigInt.ZERO;
  281. auto x = abs;
  282. auto y = n.abs;
  283. auto r = div(x,y);
  284. return (xs == ys) ? r.q : -r.q;
  285. }
  286. ///
  287. void opDivAssign(T)(T n)
  288. {
  289. auto r = opDiv(n);
  290. digits = r.digits;
  291. }
  292. ///
  293. BigInt opMod(T)(T n) const
  294. {
  295. return opMod(BigInt(n));
  296. }
  297. ///
  298. int opMod(T:int)(T n) const
  299. {
  300. if (n == 0) throw new Exception("Divide by zero");
  301. int xs = sgn;
  302. if (xs == 0) return n;
  303. auto x = abs;
  304. auto y = n > 0 ? n : -n;
  305. auto r = div(x,y);
  306. return (xs == 1) ? r.r : -r.r;
  307. }
  308. ///
  309. BigInt opMod(T:const(BigInt))(T n) const
  310. {
  311. int xs = sgn;
  312. int ys = n.sgn;
  313. if (ys == 0) throw new Exception("Divide by zero");
  314. if (xs == 0) return n;
  315. auto x = abs;
  316. auto y = n.abs;
  317. auto r = div(x,y);
  318. assert(r.r.abs < n.abs);
  319. return (xs == 1) ? r.r : -r.r;
  320. }
  321. ///
  322. void opModAssign(T:int)(T n)
  323. {
  324. auto r = opMod(BigInt(n));
  325. digits = r.digits;
  326. }
  327. ///
  328. void opModAssign(T)(T n)
  329. {
  330. auto r = opMod(n);
  331. digits = r.digits;
  332. }
  333. ///
  334. BigInt opAnd(T)(T n) const
  335. {
  336. return opAnd(BigInt(n));
  337. }
  338. ///
  339. BigInt opAnd(T:int)(T n) const
  340. {
  341. return and(this,cast(Digit)n);
  342. }
  343. ///
  344. uint opAnd(T:uint)(T n) const
  345. {
  346. uint t;
  347. castTo(t);
  348. return t & n;
  349. }
  350. ///
  351. BigInt opAnd(T:const(BigInt))(T n) const
  352. {
  353. return and(this,n);
  354. }
  355. ///
  356. void opAndAssign(T:uint)(T n)
  357. {
  358. auto r = opAnd(BigInt(n));
  359. digits = r.digits;
  360. }
  361. ///
  362. void opAndAssign(T)(T n)
  363. {
  364. auto r = opAnd(n);
  365. digits = r.digits;
  366. }
  367. ///
  368. BigInt opOr(T)(T n) const
  369. {
  370. return opOr(BigInt(n));
  371. }
  372. ///
  373. BigInt opOr(T:int)(T n) const
  374. {
  375. return or(this,cast(Digit)n);
  376. }
  377. ///
  378. BigInt opOr(T:const(BigInt))(T n) const
  379. {
  380. return or(this,n);
  381. }
  382. ///
  383. void opOrAssign(T)(T n)
  384. {
  385. auto r = opOr(n);
  386. digits = r.digits;
  387. }
  388. ///
  389. BigInt opXor(T)(T n) const
  390. {
  391. return opXor(BigInt(n));
  392. }
  393. ///
  394. BigInt opXor(T:int)(T n) const
  395. {
  396. return xor(this,cast(Digit)n);
  397. }
  398. ///
  399. BigInt opXor(T:const(BigInt))(T n) const
  400. {
  401. return xor(this,n);
  402. }
  403. ///
  404. void opXorAssign(T)(T n)
  405. {
  406. auto r = opXor(n);
  407. digits = r.digits;
  408. }
  409. ///
  410. BigInt opShl(uint n) const
  411. {
  412. uint hi = n >> 5;
  413. uint lo = n & 0x1F;
  414. Big r = this;
  415. if (lo != 0) r = shl(r,lo);
  416. if (hi != 0) r = shlDigits(r,hi);
  417. return r;
  418. }
  419. ///
  420. void opShlAssign(uint n)
  421. {
  422. auto r = opShl(n);
  423. digits = r.digits;
  424. }
  425. ///
  426. BigInt opShr(uint n) const
  427. {
  428. uint hi = n >> 5;
  429. uint lo = n & 0x1F;
  430. Big r = this;
  431. if (lo != 0) r = shr(r,lo).q;
  432. if (hi != 0) r = shrDigits(r,hi);
  433. return r;
  434. }
  435. ///
  436. void opShrAssign(uint n)
  437. {
  438. auto r = opShr(n);
  439. digits = r.digits;
  440. }
  441. ///
  442. BigInt opUShr(T)(T n) const
  443. {
  444. if (sgn >= 0) return opShr(n);
  445. else throw new Exception(">>> cannot be applied to negative numbers");
  446. }
  447. ///
  448. void opUShrAssign(T)(T n)
  449. {
  450. if (sgn >= 0) opShrAssign(n);
  451. else throw new Exception(">>>= cannot be applied to negative numbers");
  452. }
  453. ///
  454. int opEquals(T)(T n) const
  455. {
  456. return opEquals(BigInt(n));
  457. }
  458. ///
  459. int opEquals(T:int)(T n) const
  460. {
  461. return digits.length == 1 && digits[0] == n;
  462. }
  463. ///
  464. int opEquals(T:const(BigInt))(T n) const
  465. {
  466. return digits == n.digits;
  467. }
  468. ///
  469. int opCmp(T)(T n) const
  470. {
  471. return opCmp(BigInt(n));
  472. }
  473. ///
  474. int opCmp(T:int)(T n) const
  475. {
  476. int t = cmp(this,n);
  477. return t == 0 ? 0 : (t > 0 ? 1 : -1);
  478. }
  479. ///
  480. int opCmp(T:const(BigInt))(T n) const
  481. {
  482. int t = cmp(this,n);
  483. return t == 0 ? 0 : (t > 0 ? 1 : -1);
  484. }
  485. ///
  486. string toString() const
  487. {
  488. return decimal(this);
  489. }
  490. ///
  491. hash_t toHash() const
  492. {
  493. hash_t h = 0;
  494. foreach(Digit d;digits) { h += d; }
  495. return h;
  496. }
  497. private int sgn() const
  498. {
  499. int t = cmp(this,0);
  500. return t == 0 ? 0 : (t > 0 ? 1 : -1);
  501. }
  502. private BigInt abs() const
  503. {
  504. return sgn >= 0 ? opPos : opNeg;
  505. }
  506. }
  507. // ----------- EVERYTHING PRIVATE BEYOND THIS POINT -----------
  508. private:
  509. // Aliases and Typedefs
  510. alias BigInt Big;
  511. alias invariant(Digit)[] Digits;
  512. typedef Digit[] DownArray;
  513. typedef Digit* DownPtr;
  514. alias int SignedDigit;
  515. alias long SignedWideDigit;
  516. alias Digit Unused;
  517. typedef Digit[] UpArray;
  518. typedef Digit* UpPtr;
  519. alias ulong WideDigit;
  520. struct Big_Digit { Big q; Digit r; }
  521. struct Big_Big{ Big q; Big r; }
  522. // Endianness
  523. // The constant BIG_ENDIAN determines the ordering of digits within arrays.
  524. // If BIG_ENDIAN is true, then bigints are stored most significant digit first.
  525. // If BIG_ENDIAN is true, then bigints are stored most significant digit last.
  526. // Note that this does not necessarily have to be the same as the endianness
  527. // of the platform architecture.
  528. // Setting BIG_ENDIAN opposite to platform endianness allows unittests
  529. // to run in reverse endianness. (And they still pass).
  530. version(BigEndian) { enum bool BIG_ENDIAN = true; }
  531. else { enum bool BIG_ENDIAN = false; }
  532. // String conversion
  533. void parseError()
  534. {
  535. throw new Exception("Parse Error");
  536. }
  537. Big fromString(string s)
  538. {
  539. if (s.length == 0) parseError();
  540. if (s[0] == '-')
  541. {
  542. return -fromString(s[1..$]);
  543. }
  544. if (s.length > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
  545. {
  546. return fromHex(s[2..$]);
  547. }
  548. return fromDecimal(s);
  549. }
  550. Big fromDecimal(string s)
  551. {
  552. bool invalid = true;
  553. Big r = Big.ZERO;
  554. foreach(char c;s)
  555. {
  556. if (c == '_') continue;
  557. if (c < '0' || c > '9') parseError();
  558. invalid = false;
  559. //r = 10 * r + (c - '0');
  560. r *= 10;
  561. r += (c - '0');
  562. }
  563. if (invalid) parseError();
  564. return r;
  565. }
  566. Big fromHex(string s)
  567. {
  568. bool invalid = true;
  569. Big r = Big.ZERO;
  570. foreach(char c;s)
  571. {
  572. switch(c)
  573. {
  574. case '_':
  575. continue;
  576. case '0','1','2','3','4','5','6','7','8','9':
  577. r = (r << 4) + (c - '0');
  578. invalid = false;
  579. break;
  580. case 'A','B','C','D','E','F':
  581. r = (r << 4) + (c - 'A' + 10);
  582. invalid = false;
  583. break;
  584. case 'a','b','c','d','e','f':
  585. r = (r << 4) + (c - 'a' + 10);
  586. invalid = false;
  587. break;
  588. default:
  589. parseError();
  590. }
  591. }
  592. if (invalid) parseError();
  593. return r;
  594. }
  595. string decimal(Big b)
  596. {
  597. if (b == 0) return "0";
  598. if (b < 0) return "-" ~ decimal(-b);
  599. char[] result;
  600. while (b != Big.ZERO) {
  601. auto t = div(b, 10);
  602. b = t.q;
  603. result ~= t.r + '0';
  604. }
  605. reverse(result);
  606. return assumeUnique(result);
  607. }
  608. // Shrinking
  609. Big bigInt(DownArray a)
  610. {
  611. if (a.length == 0) return Big.ZERO;
  612. Big r;
  613. if (a.length == 1)
  614. {
  615. r.digits = cast(Digits)a;
  616. }
  617. else
  618. {
  619. auto xp = begin(a);
  620. auto xe = end(a);
  621. auto d1 = peek(xp);
  622. xp = next(xp);
  623. auto s = signOf(d1);
  624. while (xp != xe)
  625. {
  626. if (d1 != s) break;
  627. auto d2 = peek(xp);
  628. if (signOf(d2) != s) break;
  629. xp = next(xp);
  630. d1 = d2;
  631. }
  632. r.digits = freezeRange(xp, xe);
  633. }
  634. return r;
  635. }
  636. static if(BIG_ENDIAN)
  637. {
  638. alias UpArray BwdArray;
  639. alias UpPtr BwdPtr;
  640. alias DownArray FwdArray;
  641. alias DownPtr FwdPtr;
  642. Digit[] join(Digit[] t, Digit[] u) { return t ~ u; }
  643. T head(T)(T t,size_t n) { return cast(T)(t[0..n]); }
  644. T tail(T)(T t,size_t n) { return cast(T)(t[$-n..$]); }
  645. }
  646. else
  647. {
  648. alias DownArray BwdArray;
  649. alias DownPtr BwdPtr;
  650. alias UpArray FwdArray;
  651. alias UpPtr FwdPtr;
  652. Digit[] join(Digit[] t, Digit[] u) { return u ~ t; }
  653. T head(T)(T t,size_t n) { return cast(T)(t[$-n..$]); }
  654. T tail(T)(T t,size_t n) { return cast(T)(t[0..n]); }
  655. }
  656. // Really simple functions
  657. FwdPtr advance(FwdPtr p,size_t n) { return p + n; }
  658. BwdPtr advance(BwdPtr p,size_t n) { return p - n; }
  659. Digit begin(Digit a) { return a; }
  660. FwdPtr begin(FwdArray a) { return cast(FwdPtr)(a.ptr); }
  661. BwdPtr begin(BwdArray a) { return cast(BwdPtr)(a.ptr + a.length - 1); }
  662. Big bigInt(Digit a) { Digit[] t; t.length = 1; t[0] = a; return bigInt(cast(DownArray)t); }
  663. Big bigInt(Digits a) { return bigInt(cast(DownArray)a); }
  664. Big bigInt(Digit[] a) { return bigInt(cast(DownArray)a); }
  665. Big bigInt(UpArray a) { return bigInt(cast(DownArray)a); }
  666. Digit downArray(Digit a) { return a; }
  667. DownArray downArray(Digit[] a) { return cast(DownArray)a; }
  668. DownArray downArray(Big a) { return cast(DownArray)(a.digits); }
  669. Digit end(Digit a) { return a; }
  670. FwdPtr end(FwdArray a) { return cast(FwdPtr)(a.ptr + a.length); }
  671. BwdPtr end(BwdArray a) { return cast(BwdPtr)(a.ptr + - 1); }
  672. Digit first(Digit a) { return a; }
  673. Digit first(FwdArray a) { return a[0]; }
  674. Digit first(BwdArray a) { return a[$-1]; }
  675. Digits freezeRange(FwdPtr p, FwdPtr q) { return cast(Digits)((p-1)[0..(q-p+1)]); }
  676. Digits freezeRange(BwdPtr p, BwdPtr q) { return cast(Digits)((q+1)[0..(p-q+1)]); }
  677. Digit last(Digit a) { return a; }
  678. Digit last(FwdArray a) { return a[$-1]; }
  679. Digit last(BwdArray a) { return a[0]; }
  680. Digit lsd(Digit a) { return a; }
  681. Digit lsd(DownArray a) { return last(a); }
  682. Digit lsd(UpArray a) { return first(a); }
  683. Digit msd(Digit a) { return a; }
  684. Digit msd(DownArray a) { return first(a); }
  685. Digit msd(UpArray a) { return last(a); }
  686. size_t lengthOf(Digit a) { return 1; }
  687. size_t lengthOf(Big a) { return a.digits.length; }
  688. size_t lengthOf(DownArray a) { return a.length; }
  689. size_t lengthOf(UpArray a) { return a.length; }
  690. Digit next(ulong d) { return cast(Digit)d; }
  691. Digit next(Digit d) { return d; }
  692. FwdPtr next(FwdPtr p) { return p + 1; }
  693. BwdPtr next(BwdPtr p) { return p - 1; }
  694. Digit peek(ulong d) { return cast(Digit)d; }
  695. Digit peek(Digit d) { return d; }
  696. Digit peek(Digit* p) { return *p; }
  697. void poke(DownPtr p,Digit d) { *p = d; }
  698. void poke(DownPtr p,WideDigit d) { *p = cast(Digit)d; }
  699. void poke(DownPtr p,SignedWideDigit d) { *p = cast(Digit)d; }
  700. void poke(UpPtr p,Digit d) { *p = d; }
  701. void poke(UpPtr p,WideDigit d) { *p = cast(Digit)d; }
  702. void poke(UpPtr p,SignedWideDigit d) { *p = cast(Digit)d; }
  703. Big shrink(Big a) { return bigInt(cast(DownArray)(a.digits)); }
  704. FwdArray slice(FwdPtr ptr, size_t len) { return cast(FwdArray)(ptr[0..len]); }
  705. BwdArray slice(BwdPtr ptr, size_t len) { return cast(BwdArray)((ptr-len+1)[0..len]); }
  706. Digit signOf(SignedDigit d) { return d < 0 ? -1 : 0; }
  707. Digit upArray(Digit a) { return a; }
  708. UpArray upArray(Digit[] a) { return cast(UpArray)a; }
  709. UpArray upArray(in Big a) { return cast(UpArray)(a.digits); }
  710. // Core functions
  711. WideDigit addCore(Digit x,Digit y,WideDigit c) { return (c + x) + y; }
  712. Digit andCore(Digit x,Digit y,Digit c) { return x & y; }
  713. WideDigit divCore(Digit x,Digit y,WideDigit c)
  714. {
  715. c <<= 32;
  716. c += x;
  717. WideDigit r = c % y;
  718. c /= y;
  719. c += r << 32;
  720. return c;
  721. }
  722. WideDigit shlCore(Digit x,Digit y,WideDigit c) { return c + (cast(WideDigit)x << y); }
  723. WideDigit shrCore(Digit x,Digit y,WideDigit c) { return c + (x >> y) + (cast(WideDigit)x << (64-y)); }
  724. WideDigit mulCore(Digit x,Digit y,WideDigit c) { return c + (cast(WideDigit)x * y); }
  725. WideDigit subCore(Digit x,Digit y,WideDigit c) { return (c + x) - y; }
  726. Digit orCore(Digit x,Digit y,Digit c) { return x | y; }
  727. Digit xorCore(Digit x,Digit y,Digit c) { return x ^ y; }
  728. // Update functions
  729. Digit updateDigit(Digit c) { return c; }
  730. WideDigit updateShr(WideDigit c) { return cast(WideDigit)(cast(SignedWideDigit)c >> 32); }
  731. WideDigit updateUShr(WideDigit c) { return c >> 32; }
  732. // Helper functions
  733. int cmp(DownPtr xp, DownPtr xe, DownPtr yp)
  734. {
  735. while (xp != xe)
  736. {
  737. auto xd = peek(xp);
  738. auto yd = peek(yp);
  739. if (xd < yd) return -1;
  740. if (xd > yd) return 1;
  741. xp = next(xp);
  742. yp = next(yp);
  743. }
  744. return 0;
  745. }
  746. void mulInner(Big a, UpPtr rp, WideDigit y)
  747. {
  748. WideDigit c;
  749. mixin(setUp("x","a"));
  750. while (xp != xe)
  751. {
  752. c += y * peek(xp) + peek(rp);
  753. poke(rp,c);
  754. xp = next(xp);
  755. rp = next(rp);
  756. c = updateShr(c);
  757. }
  758. mixin(runOnce( "mulCore","updateShr","xs","y"));
  759. }
  760. void divInner(DownPtr xp, DownPtr cachePtr, size_t len)
  761. {
  762. Digit result;
  763. debug // sanity checking
  764. {
  765. DownArray _divisor = slice(cachePtr,32*len);
  766. _divisor = tail(_divisor,len);
  767. }
  768. DownPtr rp = xp;
  769. xp = next(xp);
  770. DownPtr xe = advance(xp,len);
  771. debug // sanity checking
  772. {
  773. DownArray _remainder = slice(xp,len); // will be modified in-place
  774. DownArray _original = cast(DownArray)_remainder.dup; // but we'll keep this one
  775. }
  776. for (Digit mask=0x80000000; mask!=0; mask>>=1)
  777. {
  778. int t = cmp(xp,xe,cachePtr);
  779. if (t >= 0)
  780. {
  781. debug // sanity checking
  782. {
  783. DownArray _after = slice(xp,len); // will be modified in-place
  784. DownArray _before = cast(DownArray)_after.dup; // but we'll keep this one
  785. DownArray _test = slice(cachePtr,len);
  786. }
  787. result += mask;
  788. Digit carry = subInPlace(xp,cachePtr,len);
  789. debug
  790. {
  791. BigInt before = bigInt(_before);
  792. BigInt test = bigInt(_test);
  793. BigInt after = bigInt(_after);
  794. assert(after + test == before);
  795. assert(carry == 0);
  796. }
  797. }
  798. cachePtr = advance(cachePtr,len);
  799. }
  800. debug // sanity checking
  801. {
  802. // in theory, quotient * _divisor + _remainder == _original
  803. BigInt quotient = result;
  804. BigInt divisor = bigInt(_divisor);
  805. BigInt remainder = bigInt(_remainder);
  806. BigInt original = bigInt(_original);
  807. assert(quotient * divisor + remainder == original);
  808. }
  809. poke(rp,result);
  810. }
  811. Digit subInPlace(DownPtr downPtrX, DownPtr downPtrY, size_t len)
  812. {
  813. UpPtr xp = cast(UpPtr)(advance(downPtrX,len-1));
  814. UpPtr yp = cast(UpPtr)(advance(downPtrY,len-1));
  815. UpPtr xe = advance(xp,len);
  816. SignedWideDigit c;
  817. while (xp != xe)
  818. {
  819. c += peek(xp);
  820. c -= peek(yp);
  821. poke(xp,c);
  822. c >>= 32;
  823. xp = next(xp);
  824. yp = next(yp);
  825. }
  826. return cast(Digit)c;
  827. }
  828. DownPtr makeDivCache(DownArray y)
  829. {
  830. // Pad with a leading zero
  831. auto paddedY = cast(UpArray)(join([Digit.init],y));
  832. auto upCache = cast(UpArray)new Digit[32 * paddedY.length];
  833. auto rp = begin(upCache);
  834. // Fill upCache by successively leftshifting x by one bit
  835. for (int i=0; i<32; ++i)
  836. {
  837. auto xp = begin(paddedY);
  838. auto xe = end(paddedY);
  839. WideDigit c;
  840. // Shift lefy by one bit
  841. while (xp != xe)
  842. {
  843. Digit xd = peek(xp);
  844. poke(rp,xd);
  845. c += xd;
  846. c += xd;
  847. poke(xp,c);
  848. c >>= 32;
  849. xp = next(xp);
  850. rp = next(rp);
  851. }
  852. }
  853. auto downCache = cast(DownArray)upCache;
  854. static if(false) // make true to display cache
  855. {
  856. for (int j=0; j<32; ++j)
  857. {
  858. writefln("bit %02d: ",31-j,hex(downCache[paddedY.length*j..paddedY.length*(j+1)]));
  859. }
  860. }
  861. return begin(downCache);
  862. }
  863. // Mixins
  864. string runOnce(string core, string updater, string xp, string yp)
  865. {
  866. return
  867. "{
  868. auto xd = peek("~xp~");
  869. auto yd = peek("~yp~");
  870. c = "~core~"(xd,yd,c);
  871. poke(rp,c);
  872. "~xp~" = next("~xp~");
  873. "~yp~" = next("~yp~");
  874. rp = next(rp);
  875. c = "~updater~"(c);
  876. }";
  877. }
  878. string runTo(string dest, string core, string updater, string xp, string yp)
  879. {
  880. string s = runOnce(core,updater,xp,yp);
  881. return
  882. "
  883. static if(isIntegral!(typeof("~dest~"))) {"~s~"}
  884. else
  885. {
  886. while("~dest[0..1]~"p!="~dest~") {"~s~"}
  887. }
  888. ";
  889. }
  890. string setDown(string x,string a)
  891. {
  892. return
  893. "
  894. auto "~x~" = downArray("~a~");
  895. auto "~x~"p = begin("~x~");
  896. auto "~x~"e = end("~x~");
  897. auto "~x~"s = signOf(msd("~x~"));
  898. ";
  899. }
  900. string setUp(string x,string a)
  901. {
  902. return
  903. "
  904. auto "~x~" = upArray("~a~");
  905. auto "~x~"p = begin("~x~");
  906. auto "~x~"e = end("~x~");
  907. auto "~x~"s = signOf(msd("~x~"));
  908. ";
  909. }
  910. // BigInt functions
  911. Big neg(Big b)
  912. {
  913. auto r = upArray(new Digit[lengthOf(b) + 1]);
  914. auto rp = begin(r);
  915. SignedDigit a;
  916. WideDigit c;
  917. mixin(setUp("x","a"));
  918. mixin(setUp("y","b"));
  919. mixin(runOnce( "subCore","updateShr","xp","yp"));
  920. mixin(runTo("ye","subCore","updateShr","xs","yp"));
  921. mixin(runOnce( "subCore","updateShr","xs","ys"));
  922. return bigInt(r);
  923. }
  924. Big com(Big a)
  925. {
  926. auto r = upArray(new Digit[lengthOf(a)]);
  927. auto rp = begin(r);
  928. Digit c;
  929. mixin(setUp("x","a"));
  930. Digit ys = uint.max;
  931. mixin(runTo("xe","xorCore","updateDigit","xp","ys"));
  932. return bigInt(r);
  933. }
  934. Big add(Other)(Big a,Other b)
  935. {
  936. static if(is(Other==BigInt)) if (lengthOf(a) < lengthOf(b))
  937. {
  938. swap(a,b);
  939. }
  940. auto r = upArray(new Digit[max(lengthOf(a),lengthOf(b)) + 1]);
  941. auto rp = begin(r);
  942. WideDigit c;
  943. mixin(setUp("x","a"));
  944. mixin(setUp("y","b"));
  945. mixin(runTo("ye","addCore","updateShr","xp","yp"));
  946. mixin(runTo("xe","addCore","updateShr","xp","ys"));
  947. mixin(runOnce( "addCore","updateShr","xs","ys"));
  948. return bigInt(r);
  949. }
  950. Big sub(Big a,Big b)
  951. {
  952. auto r = upArray(new Digit[max(lengthOf(a),lengthOf(b)) + 1]);
  953. auto rp = begin(r);
  954. auto re = advance(rp,min(lengthOf(a),lengthOf(b)));
  955. WideDigit c;
  956. mixin(setUp("x","a"));
  957. mixin(setUp("y","b"));
  958. mixin(runTo("re","subCore","updateShr","xp","yp"));
  959. if (lengthOf(x) >= lengthOf(y))
  960. {
  961. mixin(runTo("xe","subCore","updateShr","xp","ys"));
  962. }
  963. else
  964. {
  965. mixin(runTo("ye","subCore","updateShr","xs","yp"));
  966. }
  967. mixin(runOnce("subCore","updateShr","xs","ys"));
  968. return bigInt(r);
  969. }
  970. Big sub(Big a, Digit b)
  971. {
  972. auto r = upArray(new Digit[lengthOf(a) + 1]);
  973. auto rp = begin(r);
  974. WideDigit c;
  975. mixin(setUp("x","a"));
  976. mixin(setUp("y","b"));
  977. mixin(runOnce( "subCore","updateShr","xp","yp"));
  978. mixin(runTo("xe","subCore","updateShr","xp","ys"));
  979. mixin(runOnce( "subCore","updateShr","xs","ys"));
  980. return bigInt(r);
  981. }
  982. Big mul(Big a, Big b) // a and b must be positive
  983. {
  984. auto r = upArray(new Digit[lengthOf(a) + lengthOf(b)]);
  985. auto rp = begin(r);
  986. mixin(setUp("y","b"));
  987. while (yp != ye)
  988. {
  989. mulInner(a,rp,peek(yp));
  990. yp = next(yp);
  991. rp = next(rp);
  992. }
  993. return bigInt(r);
  994. }
  995. Big mul(Big a, Digit b) // a and b must be positive
  996. {
  997. auto r = upArray(new Digit[lengthOf(a) + 1]);
  998. auto rp = begin(r);
  999. WideDigit c;
  1000. mixin(setUp("x","a"));
  1001. mixin(runTo("xe","mulCore","updateShr","xp","b"));
  1002. poke(rp,c);
  1003. return bigInt(r);
  1004. }
  1005. Big_Big div(Big a, Big b) // a and b must be positive
  1006. {
  1007. auto lenX = lengthOf(a);
  1008. auto lenY = lengthOf(b) + 1;
  1009. auto r = cast(DownArray)join(new Digit[lenY], cast(Digit[])a.digits);
  1010. auto rp = begin(r);
  1011. auto re = advance(rp,lenX);
  1012. auto y = downArray(b);
  1013. auto cache = makeDivCache(y);
  1014. while (rp != re)
  1015. {
  1016. divInner(rp, cache, lenY);
  1017. rp = next(rp);
  1018. }
  1019. Big quotient = bigInt(cast(DownArray)(head(r,lenX)));
  1020. Big remainder = bigInt(cast(DownArray)(tail(r,lenY)));
  1021. return Big_Big(quotient,remainder);
  1022. }
  1023. Big_Digit div(Big a, Digit b) // a and b must be positive
  1024. {
  1025. auto r = downArray(new Digit[lengthOf(a)]);
  1026. auto rp = begin(r);
  1027. WideDigit c;
  1028. mixin(setDown("x","a"));
  1029. mixin(runTo("xe","divCore","updateUShr","xp","b"));
  1030. return Big_Digit(bigInt(r),cast(Digit)c);
  1031. }
  1032. Big and(Other)(Big a, Other b)
  1033. {
  1034. static if(is(Other==BigInt)) if (lengthOf(a) < lengthOf(b)) { swap(a,b); }
  1035. auto r = upArray(new Digit[max(lengthOf(a),lengthOf(b))]);
  1036. auto rp = begin(r);
  1037. Digit c;
  1038. mixin(setUp("x","a"));
  1039. mixin(setUp("y","b"));
  1040. mixin(runTo("ye","andCore","updateDigit","xp","yp"));
  1041. mixin(runTo("xe","andCore","updateDigit","xp","ys"));
  1042. return bigInt(r);
  1043. }
  1044. Big or(Other)(Big a, Other b)
  1045. {
  1046. static if(is(Other==BigInt)) if (lengthOf(a) < lengthOf(b)) { swap(a,b); }
  1047. auto r = upArray(new Digit[max(lengthOf(a),lengthOf(b))]);
  1048. auto rp = begin(r);
  1049. Digit c;
  1050. mixin(setUp("x","a"));
  1051. mixin(setUp("y","b"));
  1052. mixin(runTo("ye","orCore","updateDigit","xp","yp"));
  1053. mixin(runTo("xe","orCore","updateDigit","xp","ys"));
  1054. return bigInt(r);
  1055. }
  1056. Big xor(Other)(Big a, Other b)
  1057. {
  1058. static if(is(Other==BigInt)) if (lengthOf(a) < lengthOf(b)) { swap(a,b); }
  1059. auto r = upArray(new Digit[max(lengthOf(a),lengthOf(b))]);
  1060. auto rp = begin(r);
  1061. Digit c;
  1062. mixin(setUp("x","a"));
  1063. mixin(setUp("y","b"));
  1064. mixin(runTo("ye","xorCore","updateDigit","xp","yp"));
  1065. mixin(runTo("xe","xorCore","updateDigit","xp","ys"));
  1066. return bigInt(r);
  1067. }
  1068. Big shl(Big a, Digit b)
  1069. {
  1070. auto r = upArray(new Digit[lengthOf(a) + 1]);
  1071. auto rp = begin(r);
  1072. WideDigit c;
  1073. mixin(setUp("x","a"));
  1074. mixin(runTo("xe","shlCore","updateShr","xp","b"));
  1075. poke(rp,c);
  1076. return bigInt(r);
  1077. }
  1078. Big shlDigits(Big a, uint n)
  1079. {
  1080. Big b;
  1081. b.digits = cast(Digits)join(a.digits.dup, new Digit[n]);
  1082. return b;
  1083. }
  1084. Big_Digit shr(Big a, Digit b)
  1085. {
  1086. auto r = downArray(new Digit[lengthOf(a)]);
  1087. auto rp = begin(r);
  1088. mixin(setDown("x","a"));
  1089. WideDigit c = (signOf(msd(x)) << (32-b)) & uint.max;
  1090. mixin(runTo("xe","shrCore","updateUShr","xp","b"));
  1091. return Big_Digit(bigInt(r),cast(Digit)(c >> (32-b)));
  1092. }
  1093. Big shrDigits(Big a, uint n)
  1094. {
  1095. if (lengthOf(a) < n)
  1096. {
  1097. return bigInt(signOf(msd(downArray(a))));
  1098. }
  1099. Big b;
  1100. b.digits = cast(Digits)head(a.digits, a.digits.length-n);
  1101. return b;
  1102. }
  1103. int cmp(Big a, Big b) // assumes a and b are both shrunk
  1104. {
  1105. mixin(setDown("x","a"));
  1106. mixin(setDown("y","b"));
  1107. if (xs != ys) return xs - ys;
  1108. if (lengthOf(x) > lengthOf(y)) return cast(SignedDigit)xs < 0 ? -1 : 1;
  1109. if (lengthOf(x) < lengthOf(y)) return cast(SignedDigit)ys < 0 ? 1 : -1;
  1110. return cmp(xp,xe,yp);
  1111. }
  1112. int cmp(Big a, Digit b) // assumes a is shrunk
  1113. {
  1114. mixin(setDown("x","a"));
  1115. Digit ys = signOf(b);
  1116. if (xs != ys) return xs - ys;
  1117. if (lengthOf(x) > 1) return cast(SignedDigit)xs < 0 ? -1 : 1;
  1118. return peek(xp) - b;
  1119. }
  1120. // Debugging functions
  1121. Big makeBig(Digits array...)
  1122. {
  1123. Big r;
  1124. static if(BIG_ENDIAN)
  1125. {
  1126. r.digits = array;
  1127. }
  1128. else
  1129. {
  1130. r.digits = cast(Digits)(array.dup.reverse);
  1131. }
  1132. return r;
  1133. }
  1134. string hex(Big x)
  1135. {
  1136. return "\r" ~ hex(x.digits);
  1137. }
  1138. string hex(in Digit[] x)
  1139. {
  1140. string r;
  1141. static if(BIG_ENDIAN)
  1142. {
  1143. auto array = x;
  1144. }
  1145. else
  1146. {
  1147. auto array = x.dup.reverse;
  1148. }
  1149. for (int i=array.length; i<4; ++i)
  1150. {
  1151. r ~= "----------, ";
  1152. }
  1153. foreach(d;array)
  1154. {
  1155. r ~= format("0x%08X, ",d);
  1156. }
  1157. return r;
  1158. }
  1159. string dump(string name)
  1160. {
  1161. return
  1162. "{ writef(\"(%d) "~name~" = \",__LINE__);
  1163. static if(is(typeof("~name~") == Digit)) writefln(\"Digit %08X\","~name~");
  1164. else static if(is(typeof("~name~") == WideDigit)) writefln(\"WideDigit %016X\","~name~");
  1165. else static if(is(typeof("~name~") == SignedDigit)) writefln(\"SignedDigit %08X\","~name~");
  1166. else static if(is(typeof("~name~") == SignedWideDigit)) writefln(\"SignedWideDigit %016X\","~name~");
  1167. else writefln(typeof("~name~").stringof,\" \","~name~");
  1168. }";
  1169. }
  1170. void diag(int line = __LINE__, string file = __FILE__)
  1171. {
  1172. writefln("%s(%d) executed.", file, line);
  1173. }
  1174. // Unittests
  1175. unittest
  1176. {
  1177. // This block of unittests demonstrates that we can shrink arrays correctly
  1178. {
  1179. auto a = makeBig( 0x00000000 );
  1180. auto r = shrink(a);
  1181. assert(r.digits == a.digits, hex(r));
  1182. }{
  1183. auto a = makeBig( 0xFFFFFFFF );
  1184. auto r = shrink(a);
  1185. assert(r.digits == a.digits, hex(r));
  1186. }{
  1187. auto a = makeBig( 0x44444444 );
  1188. auto r = shrink(a);
  1189. assert(r.digits == a.digits, hex(r));
  1190. }{
  1191. auto a = makeBig( 0xCCCCCCCC );
  1192. auto r = shrink(a);
  1193. assert(r.digits == a.digits, hex(r));
  1194. }{
  1195. auto a = makeBig( 0x00000000, 0x00000000, 0x44444444, 0x44444444 );
  1196. auto b = makeBig( 0x44444444, 0x44444444 );
  1197. auto r = shrink(a);
  1198. assert(r.digits == b.digits, hex(r));
  1199. }{
  1200. auto a = makeBig( 0x00000000, 0x00000000, 0xCCCCCCCC, 0xCCCCCCCC );
  1201. auto b = makeBig( 0x00000000, 0xCCCCCCCC, 0xCCCCCCCC );
  1202. auto r = shrink(a);
  1203. assert(r.digits == b.digits, hex(r));
  1204. }{
  1205. auto a = makeBig( 0xFFFFFFFF, 0xFFFFFFFF, 0x44444444, 0x44444444 );
  1206. auto b = makeBig( 0xFFFFFFFF, 0x44444444, 0x44444444 );
  1207. auto r = shrink(a);
  1208. assert(r.digits == b.digits, hex(r));
  1209. }
  1210. // This block of unittests demonstrates that neg(Big) works
  1211. {
  1212. auto x = makeBig( 0x66666666, 0x66666660 );
  1213. auto z = makeBig( 0x99999999, 0x999999A0 );
  1214. auto r = neg(x);
  1215. assert(r.digits == z.digits, hex(r));
  1216. }{
  1217. auto x = makeBig( 0x80000000, 0x00000000 );
  1218. auto z = makeBig( 0x00000000, 0x80000000, 0x00000000 );
  1219. auto r = neg(x);
  1220. assert(r.digits == z.digits, hex(r));
  1221. }{
  1222. auto x = makeBig( 0x00000000, 0x80000000, 0x00000000 );
  1223. auto z = makeBig( 0x80000000, 0x00000000 );
  1224. auto r = neg(x);
  1225. assert(r.digits == z.digits, hex(r));
  1226. }
  1227. // This block of unittests demonstrates that com(Big) works
  1228. {
  1229. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1230. auto z = makeBig( 0xFEDCBA98, 0x76543210 );
  1231. auto r = com(x);
  1232. assert(r.digits == z.digits, hex(r));
  1233. }
  1234. // This block of unittests demonstrates that add(Big,Big) works
  1235. {
  1236. auto x = makeBig( 0x66666666, 0x66666660 );
  1237. auto y = makeBig( 0x77777777, 0x77777770 );
  1238. auto z = makeBig( 0x00000000, 0xDDDDDDDD, 0xDDDDDDD0 );
  1239. auto r = add(x,y);
  1240. assert(r.digits == z.digits, hex(r));
  1241. }{
  1242. auto x = makeBig( 0x99999999, 0x99999990 );
  1243. auto y = makeBig( 0xAAAAAAAA, 0xAAAAAAA0 );
  1244. auto z = makeBig( 0xFFFFFFFF, 0x44444444, 0x44444430 );
  1245. auto r = add(x,y);
  1246. assert(r.digits == z.digits, hex(r));
  1247. }{
  1248. auto x = makeBig( 0xEEEEEEEE, 0xEEEEEEE0 );
  1249. auto y = makeBig( 0x66666666, 0x66666660 );
  1250. auto z = makeBig( 0x55555555, 0x55555540 );
  1251. auto r = add(x,y);
  1252. assert(r.digits == z.digits, hex(r));
  1253. }{
  1254. auto x = makeBig( 0x99999999, 0x99999990 );
  1255. auto y = makeBig( 0x66666666, 0x66666660 );
  1256. auto z = makeBig( 0xFFFFFFF0 );
  1257. auto r = add(x,y);
  1258. assert(r.digits == z.digits, hex(r));
  1259. }
  1260. // This block of unittests demonstrates that add(Big,int) works
  1261. {
  1262. auto x = makeBig( 0x66666666, 0x66666660 );
  1263. auto y = 0x77777770 ;
  1264. auto z = makeBig( 0x66666666, 0xDDDDDDD0 );
  1265. auto r = add(x,y);
  1266. assert(r.digits == z.digits, hex(r));
  1267. }{
  1268. auto x = makeBig( 0x99999999, 0x99999990 );
  1269. auto y = 0xAAAAAAA0 ;
  1270. auto z = makeBig( 0x99999999, 0x44444430 );
  1271. auto r = add(x,y);
  1272. assert(r.digits == z.digits, hex(r));
  1273. }{
  1274. auto x = makeBig( 0xEEEEEEEE, 0xEEEEEEE0 );
  1275. auto y = 0x66666660 ;
  1276. auto z = makeBig( 0xEEEEEEEF, 0x55555540 );
  1277. auto r = add(x,y);
  1278. assert(r.digits == z.digits, hex(r));
  1279. }{
  1280. auto x = makeBig( 0x99999999, 0x99999990 );
  1281. auto y = 0x66666660 ;
  1282. auto z = makeBig( 0x99999999, 0xFFFFFFF0 );
  1283. auto r = add(x,y);
  1284. assert(r.digits == z.digits, hex(r));
  1285. }
  1286. // This block of unittests demonstrates that sub(Big,Big) works
  1287. {
  1288. auto x = makeBig( 0x22222222, 0x22222222, 0x22222222 );
  1289. auto y = makeBig( 0x11111111, 0x11111111 );
  1290. auto z = makeBig( 0x22222222, 0x11111111, 0x11111111 );
  1291. auto r = sub(x,y);
  1292. assert(r.digits == z.digits, hex(r));
  1293. }{
  1294. auto x = makeBig( 0x22222222, 0x22222222 );
  1295. auto y = makeBig( 0x11111111, 0x11111111, 0x11111111 );
  1296. auto z = makeBig( 0xEEEEEEEF, 0x11111111, 0x11111111 );
  1297. auto r = sub(x,y);
  1298. assert(r.digits == z.digits, hex(r));
  1299. }
  1300. // This block of unittests demonstrates that sub(Big,int) works
  1301. {
  1302. auto x = makeBig( 0x22222222, 0x22222222 );
  1303. auto y = 0x11111111 ;
  1304. auto z = makeBig( 0x22222222, 0x11111111 );
  1305. auto r = sub(x,y);
  1306. assert(r.digits == z.digits, hex(r));
  1307. }{
  1308. auto x = makeBig( 0x22222222, 0x22222222 );
  1309. auto y = 0x80000000 ;
  1310. auto z = makeBig( 0x22222222, 0xA2222222 );
  1311. auto r = sub(x,y);
  1312. assert(r.digits == z.digits, hex(r));
  1313. }
  1314. // This block of unittests demonstrates that mul(Big,Big) works
  1315. {
  1316. auto x = makeBig( 0x01111111, 0x11111111 );
  1317. auto y = makeBig( 0x01111111, 0x11111111 );
  1318. auto z = makeBig( 0x00012345, 0x6789ABCD, 0xEFEDCBA9, 0x87654321 );
  1319. auto r = mul(x,y);
  1320. assert(r.digits == z.digits, hex(r));
  1321. }
  1322. // This block of unittests demonstrates that mul(Big,uint) works
  1323. {
  1324. auto x = makeBig( 0x11111111, 0x11111111 );
  1325. auto y = 0x11111111 ;
  1326. auto z = makeBig( 0x01234567, 0x88888888, 0x87654321 );
  1327. auto r = mul(x,y);
  1328. assert(r.digits == z.digits, hex(r));
  1329. }
  1330. // This block of unittests demonstrates that div(Big,Big) works
  1331. {
  1332. auto x = makeBig( 0x00000014 );
  1333. auto y = makeBig( 0x00000007 );
  1334. auto z = makeBig( 0x00000002 );
  1335. auto w = makeBig( 0x00000006 );
  1336. auto t = div(x,y);
  1337. assert(t.q.digits == z.digits, hex(t.q));
  1338. assert(t.r.digits == w.digits, hex(t.r));
  1339. }{
  1340. auto x = makeBig( 0x00012345, 0x6789ABCD, 0xEFEDCBA9, 0x87654321 );
  1341. auto y = makeBig( 0x01111111, 0x11111111 );
  1342. auto z = makeBig( 0x01111111, 0x11111111 );
  1343. auto w = makeBig( 0x00000000 );
  1344. auto t = div(x,y);
  1345. assert(t.q.digits == z.digits, hex(t.q));
  1346. assert(t.r.digits == w.digits, hex(t.r));
  1347. }{
  1348. auto x = makeBig( 0x00012345, 0x6789ABCD, 0xEFEDCBA9, 0x98765432 );
  1349. auto y = makeBig( 0x01111111, 0x11111111 );
  1350. auto z = makeBig( 0x01111111, 0x11111111 );
  1351. auto w = makeBig( 0x11111111 );
  1352. auto t = div(x,y);
  1353. assert(t.q.digits == z.digits, hex(t.q));
  1354. assert(t.r.digits == w.digits, hex(t.r));
  1355. }
  1356. // This block of unittests demonstrates that div(Big,uint) works
  1357. {
  1358. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1359. auto y = 0x01234567 ;
  1360. auto z = makeBig( 0x00000001, 0x00000079 );
  1361. auto t = div(x,y);
  1362. assert(t.q.digits == z.digits, hex(t.q));
  1363. assert(t.r == 0x00000040, format("remainder = %08X",t.r));
  1364. }{
  1365. auto x = makeBig( 0x00000000, 0xAB54A98C, 0xEB1F0AD2 );
  1366. auto y = 0x0000000A ;
  1367. auto z = makeBig( 0x112210F4, 0x7DE98115 );
  1368. auto t = div(x,y);
  1369. assert(t.q.digits == z.digits, hex(t.q));
  1370. assert(t.r == 0x00000000, format("remainder = %08X",t.r));
  1371. }
  1372. // This block of unittests demonstrates that and(Big,Big) works
  1373. {
  1374. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1375. auto y = makeBig( 0X33333333, 0X33333333 );
  1376. auto z = makeBig( 0x01230123, 0x01230123 );
  1377. auto r = and(x,y);
  1378. assert(r.digits == z.digits, hex(r));
  1379. }{
  1380. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1381. auto y = makeBig( 0X33333333 );
  1382. auto z = makeBig( 0x01230123 );
  1383. auto r = and(x,y);
  1384. assert(r.digits == z.digits, hex(r));
  1385. }{
  1386. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1387. auto y = makeBig( 0XCCCCCCCC );
  1388. auto z = makeBig( 0x01234567, 0x8888CCCC );
  1389. auto r = and(x,y);
  1390. assert(r.digits == z.digits, hex(r));
  1391. }
  1392. // This block of unittests demonstrates that and(Big,int) works
  1393. {
  1394. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1395. auto y = 0X33333333 ;
  1396. auto z = makeBig( 0x01230123 );
  1397. auto r = and(x,y);
  1398. assert(r.digits == z.digits, hex(r));
  1399. }{
  1400. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1401. auto y = 0XCCCCCCCC ;
  1402. auto z = makeBig( 0x01234567, 0x8888CCCC );
  1403. auto r = and(x,y);
  1404. assert(r.digits == z.digits, hex(r));
  1405. }
  1406. // This block of unittests demonstrates that or(Big,Big) works
  1407. {
  1408. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1409. auto y = makeBig( 0X33333333, 0X33333333 );
  1410. auto z = makeBig( 0x33337777, 0xBBBBFFFF );
  1411. auto r = or(x,y);
  1412. assert(r.digits == z.digits, hex(r));
  1413. }{
  1414. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1415. auto y = makeBig( 0X33333333 );
  1416. auto z = makeBig( 0x01234567, 0xBBBBFFFF );
  1417. auto r = or(x,y);
  1418. assert(r.digits == z.digits, hex(r));
  1419. }{
  1420. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1421. auto y = makeBig( 0XCCCCCCCC );
  1422. auto z = makeBig( 0xCDEFCDEF );
  1423. auto r = or(x,y);
  1424. assert(r.digits == z.digits, hex(r));
  1425. }
  1426. // This block of unittests demonstrates that or(Big,int) works
  1427. {
  1428. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1429. auto y = 0X33333333 ;
  1430. auto z = makeBig( 0x01234567, 0xBBBBFFFF );
  1431. auto r = or(x,y);
  1432. assert(r.digits == z.digits, hex(r));
  1433. }{
  1434. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1435. auto y = 0XCCCCCCCC ;
  1436. auto z = makeBig( 0xCDEFCDEF );
  1437. auto r = or(x,y);
  1438. assert(r.digits == z.digits, hex(r));
  1439. }
  1440. // This block of unittests demonstrates that xor(Big,int) works
  1441. {
  1442. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1443. auto y = makeBig( 0X33333333, 0X33333333 );
  1444. auto z = makeBig( 0x32107654, 0xBA98FEDC );
  1445. auto r = xor(x,y);
  1446. assert(r.digits == z.digits, hex(r));
  1447. }{
  1448. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1449. auto y = makeBig( 0X33333333 );
  1450. auto z = makeBig( 0x01234567, 0xBA98FEDC );
  1451. auto r = xor(x,y);
  1452. assert(r.digits == z.digits, hex(r));
  1453. }{
  1454. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1455. auto y = makeBig( 0XCCCCCCCC );
  1456. auto z = makeBig( 0xFEDCBA98, 0x45670123 );
  1457. auto r = xor(x,y);
  1458. assert(r.digits == z.digits, hex(r));
  1459. }
  1460. // This block of unittests demonstrates that xor(Big,int) works
  1461. {
  1462. auto x = makeBig( 0x01234567, 0x89ABCDEF );
  1463. auto y = 0X33333333 ;
  1464. auto z = makeBig( 0x01234567, 0xBA98FEDC );
  1465. auto r = xor(x,y);
  1466. assert(r.digits == z.digits, hex(r));
  1467. }
  1468. // This block of unittests demonstrates that shl(Big,uint) works
  1469. {
  1470. Big x = makeBig( 0x01234567, 0x89ABCDEF );
  1471. Big z = makeBig( 0x00000123, 0x456789AB, 0xCDEF0000 );
  1472. Big r = shl(x,16);
  1473. assert(r.digits == z.digits, hex(r));
  1474. }
  1475. // This block of unittests demonstrates that shlDigits(Big,uint) works
  1476. {
  1477. Big x = makeBig( 0x01234567, 0x89ABCDEF );
  1478. Big z = makeBig( 0x01234567, 0x89ABCDEF, 0x00000000, 0x00000000 );
  1479. Big r = shlDigits(x,2);
  1480. assert(r.digits == z.digits, hex(r));
  1481. }
  1482. // This block of unittests demonstrates that shr(Big,uint) works
  1483. {
  1484. Big x = makeBig( 0x00000123, 0x456789AB, 0xCDEF4444 );
  1485. Big z = makeBig( 0x12345678, 0x9ABCDEF4 );
  1486. auto t = shr(x,12);
  1487. assert(t.q.digits == z.digits, hex(t.q));
  1488. assert(t.r == 0x00000444, format("remainder = %08X",t.r));
  1489. }{
  1490. auto x = makeBig( 0x80000000, 0x00000000 );
  1491. auto z = makeBig( 0xFFFF8000, 0x00000000 );
  1492. auto t = shr(x,16);
  1493. assert(t.q.digits == z.digits, hex(t.q));
  1494. assert(t.r == 0x00000000, format("remainder = %08X",t.r));
  1495. }
  1496. // This block of unittests demonstrates that shrDigits(Big,uint) works
  1497. {
  1498. Big x = makeBig( 0x01234567, 0x89ABCDEF, 0xFEDCBA98, 0x76543210 );
  1499. Big z = makeBig( 0x01234567, 0x89ABCDEF );
  1500. Big r = shrDigits(x,2);
  1501. assert(r.digits == z.digits, hex(r));
  1502. }
  1503. // This block of unittests demonstrates that cmp(Big,Big) works
  1504. {
  1505. Big x = makeBig( 0x11111111, 0x11111111, 0x11111111 );
  1506. Big y = makeBig( 0x11111111, 0x11111111 );
  1507. assert(cmp(x,y) > 0);
  1508. }{
  1509. Big x = makeBig( 0x11111111, 0x11111111 );
  1510. Big y = makeBig( 0x11111111, 0x11111111, 0x11111111 );
  1511. assert(cmp(x,y) < 0);
  1512. }{
  1513. Big x = makeBig( 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE );
  1514. Big y = makeBig( 0xEEEEEEEE, 0xEEEEEEEE );
  1515. assert(cmp(x,y) < 0);
  1516. }{
  1517. Big x = makeBig( 0xEEEEEEEE, 0xEEEEEEEE );
  1518. Big y = makeBig( 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE );
  1519. assert(cmp(x,y) > 0);
  1520. }{
  1521. Big x = makeBig( 0x33333333, 0x22222222, 0xEEEEEEEE );
  1522. Big y = makeBig( 0x33333333, 0x11111111, 0xEEEEEEEE );
  1523. assert(cmp(x,y) > 0);
  1524. }{
  1525. Big x = makeBig( 0x33333333, 0x11111111, 0xEEEEEEEE );
  1526. Big y = makeBig( 0x33333333, 0x22222222, 0xEEEEEEEE );
  1527. assert(cmp(x,y) < 0);
  1528. }{
  1529. Big x = makeBig( 0x33333333, 0x11111111, 0xEEEEEEEE );
  1530. Big y = makeBig( 0xEEEEEEEE, 0x22222222, 0xEEEEEEEE );
  1531. assert(cmp(x,y) > 0);
  1532. }{
  1533. Big x = makeBig( 0x01234567, 0x88888888, 0x76543210 );
  1534. Big y = makeBig( 0x01234567, 0x88888888, 0x76543210 );
  1535. assert(cmp(x,y) == 0);
  1536. }
  1537. // This block of unittests demonstrates that cmp(Big,uint) works
  1538. {
  1539. Big x = makeBig( 0x11111111, 0x11111111, 0x11111111 );
  1540. Digit y = 0x11111111 ;
  1541. assert(cmp(x,y) > 0);
  1542. }{
  1543. Big x = makeBig( 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE );
  1544. Digit y = 0xEEEEEEEE ;
  1545. assert(cmp(x,y) < 0);
  1546. }{
  1547. Big x = makeBig( 0x22222222 );
  1548. Digit y = 0x11111111 ;
  1549. assert(cmp(x,y) > 0);
  1550. }{
  1551. Big x = makeBig( 0x11111111 );
  1552. Digit y = 0x22222222 ;
  1553. assert(cmp(x,y) < 0);
  1554. }{
  1555. Big x = makeBig( 0x76543210 );
  1556. Digit y = 0x76543210 ;
  1557. assert(cmp(x,y) == 0);
  1558. }
  1559. // This block of unittests demonstrates that fromString(string) works
  1560. {
  1561. Big r = fromString("123");
  1562. Big z = makeBig( 0x0000007B );
  1563. assert(r.digits == z.digits, hex(r));
  1564. }{
  1565. Big r = fromString("12_345_678_901_234_567_890");
  1566. Big z = makeBig( 0x00000000, 0xAB54A98C, 0xEB1F0AD2 );
  1567. assert(r.digits == z.digits, hex(r));
  1568. }{
  1569. Big r = fromString("-12_345_678_901_234_567_890");
  1570. Big z = makeBig( 0xFFFFFFFF, 0x54AB5673, 0x14E0F52E );
  1571. assert(r.digits == z.digits, hex(r));
  1572. }{
  1573. Big r = fromString("0x0123_4567_89AB_CDEF");
  1574. Big z = makeBig( 0x01234567, 0x89ABCDEF );
  1575. assert(r.digits == z.digits, hex(r));
  1576. }{
  1577. Big r = fromString("-0x0123_4567_89AB_CDEF");
  1578. Big z = makeBig( 0xFEDCBA98, 0x76543211 );
  1579. assert(r.digits == z.digits, hex(r));
  1580. }
  1581. // This block of unittests demonstrates that decimal(Big) works
  1582. {
  1583. Big x = makeBig( 0x0000007B );
  1584. string r = decimal(x);
  1585. assert(r == "123", r);
  1586. }{
  1587. Big x = makeBig( 0x00000000, 0xAB54A98C, 0xEB1F0AD2 );
  1588. string r = decimal(x);
  1589. ass

Large files files are truncated, but you can click here to view the full file