BigInt.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "CommonDataStructuresPch.h"
  6. #include "DataStructures/BigInt.h"
  7. #include "Common/NumberUtilitiesBase.h"
  8. #include "Common/NumberUtilities.h"
  9. namespace Js
  10. {
  11. BigInt & BigInt::operator= (BigInt &bi)
  12. {
  13. AssertMsg(false, "can't assign BigInts");
  14. return *this;
  15. }
  16. #if DBG
  17. void BigInt::AssertValid(bool fCheckVal)
  18. {
  19. Assert(m_cluMax >= kcluMaxInit);
  20. Assert(m_prglu != 0);
  21. Assert(m_clu >= 0 && m_clu <= m_cluMax);
  22. Assert(!fCheckVal || 0 == m_clu || 0 != m_prglu[m_clu - 1]);
  23. Assert((m_prglu == m_rgluInit) == (m_cluMax == kcluMaxInit));
  24. }
  25. #endif
  26. BigInt::BigInt(void)
  27. {
  28. m_cluMax = kcluMaxInit;
  29. m_clu = 0;
  30. m_prglu = m_rgluInit;
  31. AssertBi(this);
  32. }
  33. BigInt::~BigInt(void)
  34. {
  35. if (m_prglu != m_rgluInit)
  36. free(m_prglu);
  37. }
  38. int32 BigInt::Clu(void)
  39. {
  40. return m_clu;
  41. }
  42. uint32 BigInt::Lu(int32 ilu)
  43. {
  44. AssertBi(this);
  45. Assert(ilu < m_clu);
  46. return m_prglu[ilu];
  47. }
  48. bool BigInt::FResize(int32 clu)
  49. {
  50. AssertBiNoVal(this);
  51. uint32 *prglu;
  52. if (clu <= m_cluMax)
  53. return true;
  54. clu += clu;
  55. if (m_prglu == m_rgluInit)
  56. {
  57. if ((INT_MAX / sizeof(uint32) < clu) || (NULL == (prglu = (uint32 *)malloc(clu * sizeof(uint32)))))
  58. return false;
  59. if (0 < m_clu)
  60. js_memcpy_s(prglu, clu * sizeof(uint32), m_prglu, m_clu * sizeof(uint32));
  61. }
  62. else if (NULL == (prglu = (uint32 *)realloc(m_prglu, clu * sizeof(uint32))))
  63. return false;
  64. m_prglu = prglu;
  65. m_cluMax = clu;
  66. AssertBiNoVal(this);
  67. return true;
  68. }
  69. bool BigInt::FInitFromRglu(uint32 *prglu, int32 clu)
  70. {
  71. AssertBi(this);
  72. Assert(clu >= 0);
  73. Assert(prglu != 0);
  74. if (clu > m_cluMax && !FResize(clu))
  75. return false;
  76. m_clu = clu;
  77. if (clu > 0)
  78. js_memcpy_s(m_prglu, m_clu * sizeof(uint32), prglu, clu * sizeof(uint32));
  79. AssertBi(this);
  80. return true;
  81. }
  82. bool BigInt::FInitFromBigint(BigInt *pbiSrc)
  83. {
  84. AssertBi(this);
  85. AssertBi(pbiSrc);
  86. Assert(this != pbiSrc);
  87. return FInitFromRglu(pbiSrc->m_prglu, pbiSrc->m_clu);
  88. }
  89. template <typename EncodedChar>
  90. bool BigInt::FInitFromDigits(const EncodedChar *prgch, int32 cch, int32 *pcchDig)
  91. {
  92. AssertBi(this);
  93. Assert(cch >= 0);
  94. Assert(prgch != 0);
  95. Assert(pcchDig != 0);
  96. uint32 luAdd;
  97. uint32 luMul;
  98. int32 clu = (cch + 8) / 9;
  99. const EncodedChar *pchLim = prgch + cch;
  100. if (clu > m_cluMax && !FResize(clu))
  101. return false;
  102. m_clu = 0;
  103. luAdd = 0;
  104. luMul = 1;
  105. for (*pcchDig = cch; prgch < pchLim; prgch++)
  106. {
  107. if (*prgch == '.')
  108. {
  109. (*pcchDig)--;
  110. continue;
  111. }
  112. Assert(NumberUtilities::IsDigit(*prgch));
  113. if (luMul == 1000000000)
  114. {
  115. AssertVerify(FMulAdd(luMul, luAdd));
  116. luMul = 1;
  117. luAdd = 0;
  118. }
  119. luMul *= 10;
  120. luAdd = luAdd * 10 + *prgch - '0';
  121. }
  122. Assert(1 < luMul);
  123. AssertVerify(FMulAdd(luMul, luAdd));
  124. AssertBi(this);
  125. return true;
  126. }
  127. bool BigInt::FMulAdd(uint32 luMul, uint32 luAdd)
  128. {
  129. AssertBi(this);
  130. Assert(luMul != 0);
  131. uint32 luT;
  132. uint32 *plu = m_prglu;
  133. uint32 *pluLim = plu + m_clu;
  134. for (; plu < pluLim; plu++)
  135. {
  136. *plu = NumberUtilities::MulLu(*plu, luMul, &luT);
  137. if (luAdd)
  138. luT += NumberUtilities::AddLu(plu, luAdd);
  139. luAdd = luT;
  140. }
  141. if (0 == luAdd)
  142. goto LDone;
  143. if (m_clu >= m_cluMax && !FResize(m_clu + 1))
  144. return false;
  145. m_prglu[m_clu++] = luAdd;
  146. LDone:
  147. AssertBi(this);
  148. return true;
  149. }
  150. bool BigInt::FMulPow5(int32 c5)
  151. {
  152. AssertBi(this);
  153. Assert(c5 >= 0);
  154. const uint32 k5to13 = 1220703125;
  155. int32 clu = (c5 + 12) / 13;
  156. uint32 luT;
  157. if (0 == m_clu || 0 == c5)
  158. return true;
  159. if (m_clu + clu > m_cluMax && !FResize(m_clu + clu))
  160. return false;
  161. for (; c5 >= 13; c5 -= 13)
  162. AssertVerify(FMulAdd(k5to13, 0));
  163. if (c5 > 0)
  164. {
  165. for (luT = 5; --c5 > 0; )
  166. luT *= 5;
  167. AssertVerify(FMulAdd(luT, 0));
  168. }
  169. AssertBi(this);
  170. return true;
  171. }
  172. bool BigInt::FShiftLeft(int32 cbit)
  173. {
  174. AssertBi(this);
  175. Assert(cbit >= 0);
  176. int32 ilu;
  177. int32 clu;
  178. uint32 luExtra;
  179. if (0 == cbit || 0 == m_clu)
  180. return true;
  181. clu = cbit >> 5;
  182. cbit &= 0x001F;
  183. if (cbit > 0)
  184. {
  185. ilu = m_clu - 1;
  186. luExtra = m_prglu[ilu] >> (32 - cbit);
  187. for (; ; ilu--)
  188. {
  189. m_prglu[ilu] <<= cbit;
  190. if (0 == ilu)
  191. break;
  192. m_prglu[ilu] |= m_prglu[ilu - 1] >> (32 - cbit);
  193. }
  194. }
  195. else
  196. luExtra = 0;
  197. if (clu > 0 || 0 != luExtra)
  198. {
  199. // Make sure there's enough room.
  200. ilu = m_clu + (0 != luExtra) + clu;
  201. if (ilu > m_cluMax && !FResize(ilu))
  202. return false;
  203. if (clu > 0)
  204. {
  205. // Shift the uint32s.
  206. memmove(m_prglu + clu, m_prglu, m_clu * sizeof(uint32));
  207. memset(m_prglu, 0, clu * sizeof(uint32));
  208. m_clu += clu;
  209. }
  210. // Throw on the extra one.
  211. if (0 != luExtra)
  212. m_prglu[m_clu++] = luExtra;
  213. }
  214. AssertBi(this);
  215. return true;
  216. }
  217. void BigInt::ShiftLusRight(int32 clu)
  218. {
  219. AssertBi(this);
  220. Assert(clu >= 0);
  221. if (clu >= m_clu)
  222. {
  223. m_clu = 0;
  224. AssertBi(this);
  225. return;
  226. }
  227. if (clu > 0)
  228. {
  229. memmove(m_prglu, m_prglu + clu, (m_clu - clu) * sizeof(uint32));
  230. m_clu -= clu;
  231. }
  232. AssertBi(this);
  233. }
  234. void BigInt::ShiftRight(int32 cbit)
  235. {
  236. AssertBi(this);
  237. Assert(cbit >= 0);
  238. int32 ilu;
  239. int32 clu = cbit >> 5;
  240. cbit &= 0x001F;
  241. if (clu > 0)
  242. ShiftLusRight(clu);
  243. if (cbit == 0 || m_clu == 0)
  244. {
  245. AssertBi(this);
  246. return;
  247. }
  248. for (ilu = 0; ; )
  249. {
  250. m_prglu[ilu] >>= cbit;
  251. if (++ilu >= m_clu)
  252. {
  253. // Last one.
  254. if (0 == m_prglu[ilu - 1])
  255. m_clu--;
  256. break;
  257. }
  258. m_prglu[ilu - 1] |= m_prglu[ilu] << (32 - cbit);
  259. }
  260. AssertBi(this);
  261. }
  262. int BigInt::Compare(BigInt *pbi)
  263. {
  264. AssertBi(this);
  265. AssertBi(pbi);
  266. int32 ilu;
  267. if (m_clu > pbi->m_clu)
  268. return 1;
  269. if (m_clu < pbi->m_clu)
  270. return -1;
  271. if (0 == m_clu)
  272. return 0;
  273. #pragma prefast(suppress:__WARNING_LOOP_ONLY_EXECUTED_ONCE,"noise")
  274. for (ilu = m_clu - 1; m_prglu[ilu] == pbi->m_prglu[ilu]; ilu--)
  275. {
  276. if (0 == ilu)
  277. return 0;
  278. }
  279. Assert(ilu >= 0 && ilu < m_clu);
  280. Assert(m_prglu[ilu] != pbi->m_prglu[ilu]);
  281. return (m_prglu[ilu] > pbi->m_prglu[ilu]) ? 1 : -1;
  282. }
  283. bool BigInt::FAdd(BigInt *pbi)
  284. {
  285. AssertBi(this);
  286. AssertBi(pbi);
  287. Assert(this != pbi);
  288. int32 cluMax, cluMin;
  289. int32 ilu;
  290. int wCarry;
  291. if ((cluMax = m_clu) < (cluMin = pbi->m_clu))
  292. {
  293. cluMax = pbi->m_clu;
  294. cluMin = m_clu;
  295. if (cluMax > m_cluMax && !FResize(cluMax + 1))
  296. return false;
  297. }
  298. wCarry = 0;
  299. for (ilu = 0; ilu < cluMin; ilu++)
  300. {
  301. if (0 != wCarry)
  302. wCarry = NumberUtilities::AddLu(&m_prglu[ilu], wCarry);
  303. wCarry += NumberUtilities::AddLu(&m_prglu[ilu], pbi->m_prglu[ilu]);
  304. }
  305. if (m_clu < pbi->m_clu)
  306. {
  307. for (; ilu < cluMax; ilu++)
  308. {
  309. m_prglu[ilu] = pbi->m_prglu[ilu];
  310. if (0 != wCarry)
  311. wCarry = NumberUtilities::AddLu(&m_prglu[ilu], wCarry);
  312. }
  313. m_clu = cluMax;
  314. }
  315. else
  316. {
  317. for (; 0 != wCarry && ilu < cluMax; ilu++)
  318. wCarry = NumberUtilities::AddLu(&m_prglu[ilu], wCarry);
  319. }
  320. if (0 != wCarry)
  321. {
  322. if (m_clu >= m_cluMax && !FResize(m_clu + 1))
  323. return false;
  324. m_prglu[m_clu++] = wCarry;
  325. }
  326. AssertBi(this);
  327. return true;
  328. }
  329. void BigInt::Subtract(BigInt *pbi)
  330. {
  331. AssertBi(this);
  332. AssertBi(pbi);
  333. Assert(this != pbi);
  334. int32 ilu;
  335. int wCarry;
  336. uint32 luT;
  337. if (m_clu < pbi->m_clu)
  338. goto LNegative;
  339. wCarry = 1;
  340. for (ilu = 0; (ilu < pbi->m_clu) && (ilu < pbi->m_cluMax); ilu++)
  341. {
  342. Assert(wCarry == 0 || wCarry == 1);
  343. luT = pbi->m_prglu[ilu];
  344. // NOTE: We should really do:
  345. // wCarry = AddLu(&m_prglu[ilu], wCarry);
  346. // wCarry += AddLu(&m_prglu[ilu], ~luT);
  347. // The only case where this is different than
  348. // wCarry = AddLu(&m_prglu[ilu], ~luT + wCarry);
  349. // is when luT == 0 and 1 == wCarry, in which case we don't
  350. // need to add anything and wCarry should still be 1, so we can
  351. // just skip the operations.
  352. if (0 != luT || 0 == wCarry)
  353. wCarry = NumberUtilities::AddLu(&m_prglu[ilu], ~luT + wCarry);
  354. }
  355. while ((0 == wCarry) && (ilu < m_clu) && (ilu < m_cluMax))
  356. wCarry = NumberUtilities::AddLu(&m_prglu[ilu], 0xFFFFFFFF);
  357. if (0 == wCarry)
  358. {
  359. LNegative:
  360. // pbi was bigger than this.
  361. AssertMsg(false, "Who's subtracting to negative?");
  362. m_clu = 0;
  363. }
  364. else if (ilu == m_clu)
  365. {
  366. // Trim off zeros.
  367. while (--ilu >= 0 && 0 == m_prglu[ilu])
  368. ;
  369. m_clu = ilu + 1;
  370. }
  371. AssertBi(this);
  372. }
  373. int BigInt::DivRem(BigInt *pbi)
  374. {
  375. AssertBi(this);
  376. AssertBi(pbi);
  377. Assert(this != pbi);
  378. int32 ilu, clu;
  379. int wCarry;
  380. int wQuo;
  381. int wT;
  382. uint32 luT, luHi, luLo;
  383. clu = pbi->m_clu;
  384. Assert(m_clu <= clu);
  385. if ((m_clu < clu) || (clu <= 0))
  386. return 0;
  387. // Get a lower bound on the quotient.
  388. wQuo = (int)(m_prglu[clu - 1] / (pbi->m_prglu[clu - 1] + 1));
  389. Assert(wQuo >= 0 && wQuo <= 9);
  390. // Handle 0 and 1 as special cases.
  391. switch (wQuo)
  392. {
  393. case 0:
  394. break;
  395. case 1:
  396. Subtract(pbi);
  397. break;
  398. default:
  399. luHi = 0;
  400. wCarry = 1;
  401. for (ilu = 0; ilu < clu; ilu++)
  402. {
  403. Assert(wCarry == 0 || wCarry == 1);
  404. // Compute the product.
  405. luLo = NumberUtilities::MulLu(wQuo, pbi->m_prglu[ilu], &luT);
  406. luHi = luT + NumberUtilities::AddLu(&luLo, luHi);
  407. // Subtract the product. See note in BigInt::Subtract.
  408. if (0 != luLo || 0 == wCarry)
  409. wCarry = NumberUtilities::AddLu(&m_prglu[ilu], ~luLo + wCarry);
  410. }
  411. Assert(1 == wCarry);
  412. Assert(ilu == clu);
  413. // Trim off zeros.
  414. while (--ilu >= 0 && 0 == m_prglu[ilu])
  415. ;
  416. m_clu = ilu + 1;
  417. }
  418. if (wQuo < 9 && (wT = Compare(pbi)) >= 0)
  419. {
  420. // Quotient was off too small (by one).
  421. wQuo++;
  422. if (wT == 0)
  423. m_clu = 0;
  424. else
  425. Subtract(pbi);
  426. }
  427. Assert(Compare(pbi) < 0);
  428. return wQuo;
  429. }
  430. double BigInt::GetDbl(void)
  431. {
  432. double dbl;
  433. uint32 luHi, luLo;
  434. uint32 lu1, lu2, lu3;
  435. int32 ilu;
  436. int cbit;
  437. switch (m_clu)
  438. {
  439. case 0:
  440. return 0;
  441. case 1:
  442. return m_prglu[0];
  443. case 2:
  444. dbl = m_prglu[1];
  445. NumberUtilities::LuHiDbl(dbl) += 0x02000000;
  446. return dbl + m_prglu[0];
  447. }
  448. Assert(3 <= m_clu);
  449. if (m_clu > 32)
  450. {
  451. // Result is infinite.
  452. NumberUtilities::LuHiDbl(dbl) = 0x7FF00000;
  453. NumberUtilities::LuLoDbl(dbl) = 0;
  454. return dbl;
  455. }
  456. lu1 = m_prglu[m_clu - 1];
  457. lu2 = m_prglu[m_clu - 2];
  458. lu3 = m_prglu[m_clu - 3];
  459. Assert(0 != lu1);
  460. cbit = 31 - NumberUtilities::CbitZeroLeft(lu1);
  461. if (cbit == 0)
  462. {
  463. luHi = lu2;
  464. luLo = lu3;
  465. }
  466. else
  467. {
  468. luHi = (lu1 << (32 - cbit)) | (lu2 >> cbit);
  469. // Or 1 if there are any remaining nonzero bits in lu3, so we take
  470. // them into account when rounding.
  471. luLo = (lu2 << (32 - cbit)) | (lu3 >> cbit) | (0 != (lu3 << (32 - cbit)));
  472. }
  473. // Set the mantissa bits.
  474. NumberUtilities::LuHiDbl(dbl) = luHi >> 12;
  475. NumberUtilities::LuLoDbl(dbl) = (luHi << 20) | (luLo >> 12);
  476. // Set the exponent field.
  477. NumberUtilities::LuHiDbl(dbl) |= (0x03FF + cbit + (m_clu - 1) * 0x0020) << 20;
  478. // Do IEEE rounding.
  479. if (luLo & 0x0800)
  480. {
  481. if ((luLo & 0x07FF) || (NumberUtilities::LuLoDbl(dbl) & 1))
  482. {
  483. if (0 == ++NumberUtilities::LuLoDbl(dbl))
  484. ++NumberUtilities::LuHiDbl(dbl);
  485. }
  486. else
  487. {
  488. // If there are any non-zero bits in m_prglu from 0 to m_clu - 4, round up.
  489. for (ilu = m_clu - 4; ilu >= 0; ilu--)
  490. {
  491. if (0 != m_prglu[ilu])
  492. {
  493. if (0 == ++NumberUtilities::LuLoDbl(dbl))
  494. ++NumberUtilities::LuHiDbl(dbl);
  495. break;
  496. }
  497. }
  498. }
  499. }
  500. return dbl;
  501. }
  502. template bool BigInt::FInitFromDigits<char16>(const char16 *prgch, int32 cch, int32 *pcchDig);
  503. template bool BigInt::FInitFromDigits<utf8char_t>(const utf8char_t *prgch, int32 cch, int32 *pcchDig);
  504. }