BigInt.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "BigInt.h"
  4. #include "../Container/Pair.h"
  5. #include "../Core/StringUtils.h"
  6. #include "../DebugNew.h"
  7. namespace Urho3D
  8. {
  9. #if true
  10. static constexpr BigInt::Digit BASE = 1000'000'000; // 10^9
  11. // Number of decimal digits in each magnitude_ element
  12. static constexpr i32 BASE_DIGITS = 9;
  13. #else // For tests
  14. static constexpr BigInt::Digit BASE = 10;
  15. static constexpr i32 BASE_DIGITS = 1;
  16. #endif
  17. // Compare magnitudes
  18. static bool FirstIsLess(const Vector<BigInt::Digit>& first, const Vector<BigInt::Digit>& second)
  19. {
  20. if (first.Size() != second.Size())
  21. return first.Size() < second.Size();
  22. for (i32 i = first.Size() - 1; i >= 0; --i)
  23. {
  24. if (first[i] != second[i])
  25. return first[i] < second[i];
  26. }
  27. return false; // first == b
  28. }
  29. // a + b
  30. static Vector<BigInt::Digit> SumMagnitudes(const Vector<BigInt::Digit>& a, const Vector<BigInt::Digit>& b)
  31. {
  32. Vector<BigInt::Digit> ret;
  33. i32 maxSize = Max(a.Size(), b.Size());
  34. ret.Resize(maxSize, 0);
  35. for (i32 i = 0; i < maxSize; ++i)
  36. {
  37. BigInt::Digit a_element = i < a.Size() ? a[i] : 0;
  38. BigInt::Digit b_element = i < b.Size() ? b[i] : 0;
  39. BigInt::Digit sum = a_element + b_element;
  40. ret[i] += sum; // ret[i] can be not zero
  41. while (ret[i] >= BASE)
  42. {
  43. ret[i] -= BASE; // Use div & mod instead loop?
  44. if (i + 1 < ret.Size())
  45. ++ret[i + 1];
  46. else
  47. ret.Push(1);
  48. }
  49. }
  50. return ret;
  51. }
  52. // a - b (a must be >= b)
  53. static Vector<BigInt::Digit> DiffMagnitudes(const Vector<BigInt::Digit>& a, const Vector<BigInt::Digit>& b)
  54. {
  55. Vector<BigInt::Digit> ret;
  56. ret.Resize(a.Size(), 0);
  57. for (i32 i = 0; i < a.Size(); ++i)
  58. {
  59. BigInt::Digit a_element = a[i];
  60. BigInt::Digit b_element = i < b.Size() ? b[i] : 0;
  61. BigInt::Digit diff = a_element - b_element;
  62. ret[i] += diff; // ret[i] can be not zero
  63. while (ret[i] < 0)
  64. {
  65. ret[i] += BASE;
  66. assert(i + 1 < ret.Size());
  67. --ret[i + 1];
  68. }
  69. }
  70. // Remove leading zeros
  71. while (ret.Size() >= 2 && ret.Back() == 0)
  72. ret.Pop();
  73. return ret;
  74. }
  75. // Return quotient and remainder.
  76. // If denominator == 0, then return {0, 0}
  77. Pair<BigInt, BigInt> DivMod(BigInt numerator, BigInt denominator)
  78. {
  79. if (denominator == 0)
  80. return {0, 0};
  81. BigInt absNum = Abs(numerator);
  82. BigInt absDenom = Abs(denominator);
  83. BigInt quotient = 0;
  84. BigInt remainder = absNum;
  85. // The Simplest and slowest way
  86. while (remainder >= absDenom)
  87. {
  88. ++quotient;
  89. remainder -= absDenom;
  90. String strQ = quotient.ToString();
  91. String strRem = remainder.ToString();
  92. int a = 0;
  93. }
  94. // https://en.cppreference.com/w/cpp/language/operator_arithmetic
  95. // (a/b)*b + a%b == a
  96. // 7/3 = {2, 1} | 2*3 + 1 == 7
  97. // -7/3 = {-2, -1} | -2*3 + -1 == -7
  98. // 7/-3 = {-2, 1} | -2*-3 + 1 == 7
  99. // -7/-3 = {2, -1} | 2*-3 + -1 == -7
  100. if (numerator.IsPositive() != denominator.IsPositive())
  101. quotient = -quotient;
  102. if (numerator.IsNegative())
  103. remainder = -remainder;
  104. return {quotient, remainder};
  105. }
  106. BigInt::BigInt()
  107. {
  108. // Init as zero
  109. positive_ = true;
  110. magnitude_.Resize(1, 0);
  111. }
  112. BigInt::BigInt(const String& str)
  113. {
  114. if (str.Empty())
  115. {
  116. // Init as zero
  117. positive_ = true;
  118. magnitude_.Resize(1, 0);
  119. return;
  120. }
  121. i32 firstDigitPos;
  122. if (str[0] == '-')
  123. {
  124. positive_ = false;
  125. firstDigitPos = 1;
  126. }
  127. else if (str[0] == '+')
  128. {
  129. positive_ = true;
  130. firstDigitPos = 1;
  131. }
  132. else
  133. {
  134. positive_ = true;
  135. firstDigitPos = 0;
  136. }
  137. // Skip leading zeros
  138. for (i32 i = firstDigitPos; i < (i32)str.Length(); ++i)
  139. {
  140. if (str[i] != '0')
  141. break;
  142. ++firstDigitPos;
  143. }
  144. i32 lastDigitPos = -1;
  145. for (i32 i = firstDigitPos; i < (i32)str.Length(); ++i)
  146. {
  147. if (!IsDigit(str[i]))
  148. break;
  149. lastDigitPos = i;
  150. }
  151. if (lastDigitPos == -1)
  152. {
  153. // Init as zero
  154. positive_ = true;
  155. magnitude_.Resize(1, 0);
  156. return;
  157. }
  158. i32 numDigits = lastDigitPos - firstDigitPos + 1;
  159. magnitude_.Reserve(numDigits / BASE_DIGITS + 1);
  160. // Retrieve chunks of 9 digits in reverse order and save to single i32
  161. i32 i = lastDigitPos - BASE_DIGITS + 1;
  162. for (; i > firstDigitPos; i -= BASE_DIGITS)
  163. {
  164. String chunk = str.Substring(i, BASE_DIGITS);
  165. magnitude_.Push(ToI64(chunk)); // To Digit
  166. }
  167. String lastChunk = str.Substring(firstDigitPos, BASE_DIGITS + i - firstDigitPos);
  168. magnitude_.Push(ToI64(lastChunk)); // To Digit
  169. }
  170. BigInt::BigInt(i32 value)
  171. {
  172. positive_ = (value >= 0);
  173. value = Urho3D::Abs(value);
  174. while (value != 0)
  175. {
  176. Digit mod = value % BASE;
  177. magnitude_.Push(mod);
  178. value /= BASE;
  179. }
  180. if (!magnitude_.Size()) // value == 0
  181. magnitude_.Push(0);
  182. }
  183. BigInt::BigInt(i64 value)
  184. {
  185. positive_ = (value >= 0);
  186. value = Urho3D::Abs(value);
  187. while (value != 0)
  188. {
  189. Digit mod = value % BASE;
  190. magnitude_.Push(mod);
  191. value /= BASE;
  192. }
  193. if (!magnitude_.Size()) // value == 0
  194. magnitude_.Push(0);
  195. }
  196. BigInt::BigInt(u32 value)
  197. {
  198. positive_ = true;
  199. while (value != 0)
  200. {
  201. Digit mod = value % BASE;
  202. magnitude_.Push(mod);
  203. value /= BASE;
  204. }
  205. if (!magnitude_.Size()) // value == 0
  206. magnitude_.Push(0);
  207. }
  208. BigInt::BigInt(u64 value)
  209. {
  210. positive_ = true;
  211. while (value != 0)
  212. {
  213. Digit mod = (Digit)(value % BASE);
  214. magnitude_.Push(mod);
  215. value /= BASE;
  216. }
  217. if (!magnitude_.Size()) // value == 0
  218. magnitude_.Push(0);
  219. }
  220. bool BigInt::IsZero() const
  221. {
  222. assert(magnitude_.Size() > 0);
  223. if (magnitude_.Size() == 1 && magnitude_[0] == 0)
  224. {
  225. assert(positive_);
  226. return true;
  227. }
  228. return false;
  229. }
  230. bool BigInt::operator <(const BigInt& rhs) const
  231. {
  232. if (positive_ != rhs.positive_)
  233. return !positive_;
  234. if (positive_)
  235. return FirstIsLess(magnitude_, rhs.magnitude_);
  236. else
  237. return FirstIsLess(rhs.magnitude_, magnitude_);
  238. }
  239. String BigInt::ToString() const
  240. {
  241. assert(magnitude_.Size() > 0);
  242. String ret;
  243. if (!positive_)
  244. ret = "-";
  245. // Beginning of the number without leading zeros
  246. i32 i = (i32)magnitude_.Size() - 1;
  247. ret += String(magnitude_[i]);
  248. --i;
  249. // Another chunks with leading zeros
  250. for (; i >= 0; --i)
  251. {
  252. String str(magnitude_[i]);
  253. if (str.Length() < BASE_DIGITS)
  254. {
  255. String zeros('0', BASE_DIGITS - str.Length());
  256. str = zeros + str;
  257. }
  258. ret += str;
  259. }
  260. return ret;
  261. }
  262. BigInt BigInt::operator +(const BigInt& rhs) const
  263. {
  264. BigInt ret;
  265. if (positive_ == rhs.positive_)
  266. {
  267. ret.positive_ = positive_;
  268. ret.magnitude_ = SumMagnitudes(magnitude_, rhs.magnitude_);
  269. }
  270. else
  271. {
  272. if (FirstIsLess(magnitude_, rhs.magnitude_))
  273. {
  274. ret.positive_ = rhs.positive_;
  275. ret.magnitude_ = DiffMagnitudes(rhs.magnitude_, magnitude_);
  276. }
  277. else
  278. {
  279. ret.positive_ = positive_;
  280. ret.magnitude_ = DiffMagnitudes(magnitude_, rhs.magnitude_);
  281. }
  282. }
  283. return ret;
  284. }
  285. BigInt BigInt::operator -(const BigInt& rhs) const
  286. {
  287. BigInt ret;
  288. if (positive_ != rhs.positive_)
  289. {
  290. ret.positive_ = positive_;
  291. ret.magnitude_ = SumMagnitudes(magnitude_, rhs.magnitude_);
  292. }
  293. else
  294. {
  295. if (FirstIsLess(magnitude_, rhs.magnitude_))
  296. {
  297. ret.positive_ = !rhs.positive_;
  298. ret.magnitude_ = DiffMagnitudes(rhs.magnitude_, magnitude_);
  299. }
  300. else
  301. {
  302. ret.positive_ = positive_;
  303. ret.magnitude_ = DiffMagnitudes(magnitude_, rhs.magnitude_);
  304. }
  305. }
  306. return ret;
  307. }
  308. BigInt BigInt::operator *(const BigInt& rhs) const
  309. {
  310. BigInt ret;
  311. ret.magnitude_.Resize(magnitude_.Size() + rhs.magnitude_.Size(), 0);
  312. if (positive_ == rhs.positive_)
  313. ret.positive_ = true;
  314. else
  315. ret.positive_ = false;
  316. for (i32 this_index = 0; this_index < magnitude_.Size(); ++this_index)
  317. {
  318. for (i32 rhs_index = 0; rhs_index < rhs.magnitude_.Size(); ++rhs_index)
  319. ret.magnitude_[this_index + rhs_index] += magnitude_[this_index] * rhs.magnitude_[rhs_index];
  320. }
  321. for (i32 i = 0; i < ret.magnitude_.Size() - 1; ++i)
  322. {
  323. ret.magnitude_[i + 1] += ret.magnitude_[i] / BASE;
  324. ret.magnitude_[i] %= BASE;
  325. }
  326. // Remove leading zeros
  327. while (ret.magnitude_.Size() >= 2 && ret.magnitude_.Back() == 0)
  328. ret.magnitude_.Pop();
  329. return ret;
  330. }
  331. BigInt BigInt::operator /(const BigInt& rhs) const
  332. {
  333. Pair<BigInt, BigInt> divMod = DivMod(*this, rhs);
  334. return divMod.first_;
  335. }
  336. BigInt BigInt::operator %(const BigInt& rhs) const
  337. {
  338. Pair<BigInt, BigInt> divMod = DivMod(*this, rhs);
  339. return divMod.second_;
  340. }
  341. BigInt BigInt::operator -() const
  342. {
  343. BigInt ret = *this;
  344. if (!ret.IsZero())
  345. ret.positive_ = !ret.positive_;
  346. return ret;
  347. }
  348. BigInt& BigInt::operator +=(const BigInt& rhs)
  349. {
  350. BigInt result = *this + rhs;
  351. Swap(this->positive_, result.positive_);
  352. Swap(this->magnitude_, result.magnitude_);
  353. return *this;
  354. }
  355. BigInt& BigInt::operator -=(const BigInt& rhs)
  356. {
  357. BigInt result = *this - rhs;
  358. Swap(this->positive_, result.positive_);
  359. Swap(this->magnitude_, result.magnitude_);
  360. return *this;
  361. }
  362. BigInt& BigInt::operator *=(const BigInt& rhs)
  363. {
  364. BigInt result = *this * rhs;
  365. Swap(this->positive_, result.positive_);
  366. Swap(this->magnitude_, result.magnitude_);
  367. return *this;
  368. }
  369. BigInt& BigInt::operator /=(const BigInt& rhs)
  370. {
  371. BigInt result = *this / rhs;
  372. Swap(this->positive_, result.positive_);
  373. Swap(this->magnitude_, result.magnitude_);
  374. return *this;
  375. }
  376. BigInt& BigInt::operator %=(const BigInt& rhs)
  377. {
  378. BigInt result = *this % rhs;
  379. Swap(this->positive_, result.positive_);
  380. Swap(this->magnitude_, result.magnitude_);
  381. return *this;
  382. }
  383. } // namespace Urho3D