UnsignedBigInteger.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*
  2. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "UnsignedBigInteger.h"
  27. #include <AK/StringBuilder.h>
  28. namespace Crypto {
  29. UnsignedBigInteger UnsignedBigInteger::from_base10(const String& str)
  30. {
  31. UnsignedBigInteger result;
  32. UnsignedBigInteger ten { 10 };
  33. for (auto& c : str) {
  34. result = result.multiply(ten).add(c - '0');
  35. }
  36. return result;
  37. }
  38. String UnsignedBigInteger::to_base10() const
  39. {
  40. StringBuilder builder;
  41. UnsignedBigInteger temp(*this);
  42. while (temp != UnsignedBigInteger { 0 }) {
  43. auto div_result = temp.divide({ 10 });
  44. ASSERT(div_result.remainder.words()[0] < 10);
  45. builder.append(static_cast<char>(div_result.remainder.words()[0] + '0'));
  46. temp = div_result.quotient;
  47. }
  48. auto reversed_string = builder.to_string();
  49. builder.clear();
  50. for (int i = reversed_string.length() - 1; i >= 0; --i) {
  51. builder.append(reversed_string[i]);
  52. }
  53. return builder.to_string();
  54. }
  55. bool UnsignedBigInteger::operator!=(const UnsignedBigInteger& other) const
  56. {
  57. return !(*this == other);
  58. }
  59. /**
  60. * Complexity: O(N) where N is the number of words in the larger number
  61. */
  62. UnsignedBigInteger UnsignedBigInteger::add(const UnsignedBigInteger& other) const
  63. {
  64. const UnsignedBigInteger* const longer = (length() > other.length()) ? this : &other;
  65. const UnsignedBigInteger* const shorter = (longer == &other) ? this : &other;
  66. UnsignedBigInteger result;
  67. u8 carry = 0;
  68. result.m_words.ensure_capacity(longer->length() + 1);
  69. for (size_t i = 0; i < shorter->length(); ++i) {
  70. u32 word_addition_result = shorter->m_words[i] + longer->m_words[i];
  71. u8 carry_out = 0;
  72. // if there was a carry, the result will be smaller than any of the operands
  73. if (word_addition_result + carry < shorter->m_words[i]) {
  74. carry_out = 1;
  75. }
  76. if (carry) {
  77. word_addition_result++;
  78. }
  79. carry = carry_out;
  80. result.m_words.append(word_addition_result);
  81. }
  82. for (size_t i = shorter->length(); i < longer->length(); ++i) {
  83. u32 word_addition_result = longer->m_words[i] + carry;
  84. carry = 0;
  85. if (word_addition_result < longer->m_words[i]) {
  86. carry = 1;
  87. }
  88. result.m_words.append(word_addition_result);
  89. }
  90. if (carry) {
  91. result.m_words.append(carry);
  92. }
  93. return result;
  94. }
  95. /**
  96. * Complexity: O(N) where N is the number of words in the larger number
  97. */
  98. UnsignedBigInteger UnsignedBigInteger::sub(const UnsignedBigInteger& other) const
  99. {
  100. UnsignedBigInteger result;
  101. if (*this < other) {
  102. return UnsignedBigInteger::create_invalid();
  103. }
  104. u8 borrow = 0;
  105. auto own_length = length(), other_length = other.length();
  106. result.m_words.ensure_capacity(own_length);
  107. for (size_t i = 0; i < own_length; ++i) {
  108. u32 other_word = (i < other_length) ? other.m_words[i] : 0;
  109. i64 temp = static_cast<i64>(m_words[i]) - static_cast<i64>(other_word) - static_cast<i64>(borrow);
  110. // If temp < 0, we had an underflow
  111. borrow = (temp >= 0) ? 0 : 1;
  112. if (temp < 0) {
  113. temp += (UINT32_MAX + 1);
  114. }
  115. result.m_words.append(temp);
  116. }
  117. // This assertion should not fail, because we verified that *this>=other at the beginning of the function
  118. ASSERT(borrow == 0);
  119. return result;
  120. }
  121. /**
  122. * Complexity: O(N^2) where N is the number of words in the larger number
  123. * Multiplcation method:
  124. * An integer is equal to the sum of the powers of two
  125. * according to the indexes of its 'on' bits.
  126. * So to multiple x*y, we go over each '1' bit in x (say the i'th bit),
  127. * and add y<<i to the result.
  128. */
  129. UnsignedBigInteger UnsignedBigInteger::multiply(const UnsignedBigInteger& other) const
  130. {
  131. UnsignedBigInteger result;
  132. // iterate all bits
  133. for (size_t word_index = 0; word_index < length(); ++word_index) {
  134. for (size_t bit_index = 0; bit_index < UnsignedBigInteger::BITS_IN_WORD; ++bit_index) {
  135. // If the bit is off - skip over it
  136. if (!(m_words[word_index] & (1 << bit_index)))
  137. continue;
  138. const size_t shift_amount = word_index * UnsignedBigInteger::BITS_IN_WORD + bit_index;
  139. auto shift_result = other.shift_left(shift_amount);
  140. result = result.add(shift_result);
  141. }
  142. }
  143. return result;
  144. }
  145. /**
  146. * Complexity: O(N^2) where N is the number of words in the larger number
  147. * Division method:
  148. * We loop over the bits of the divisor, attempting to subtract divisor<<i from the dividend.
  149. * If the result is non-negative, it means that divisor*2^i "fits" in the dividend,
  150. * so we set the ith bit in the quotient and reduce divisor<<i from the dividend.
  151. * When we're done, what's left from the dividend is the remainder.
  152. */
  153. UnsignedDivisionResult UnsignedBigInteger::divide(const UnsignedBigInteger& divisor) const
  154. {
  155. UnsignedBigInteger leftover_dividend(*this);
  156. UnsignedBigInteger quotient;
  157. // iterate all bits
  158. for (int word_index = trimmed_length() - 1; word_index >= 0; --word_index) {
  159. for (int bit_index = UnsignedBigInteger::BITS_IN_WORD - 1; bit_index >= 0; --bit_index) {
  160. const size_t shift_amount = word_index * UnsignedBigInteger::BITS_IN_WORD + bit_index;
  161. UnsignedBigInteger divisor_shifted = divisor.shift_left(shift_amount);
  162. UnsignedBigInteger temp_subtraction_result = leftover_dividend.sub(divisor_shifted);
  163. if (!temp_subtraction_result.is_invalid()) {
  164. leftover_dividend = temp_subtraction_result;
  165. quotient.set_bit_inplace(shift_amount);
  166. }
  167. }
  168. }
  169. return UnsignedDivisionResult { quotient, leftover_dividend };
  170. }
  171. void UnsignedBigInteger::set_bit_inplace(size_t bit_index)
  172. {
  173. const size_t word_index = bit_index / UnsignedBigInteger::BITS_IN_WORD;
  174. const size_t inner_word_index = bit_index % UnsignedBigInteger::BITS_IN_WORD;
  175. m_words.ensure_capacity(word_index);
  176. for (size_t i = length(); i <= word_index; ++i) {
  177. m_words.append(0);
  178. }
  179. m_words[word_index] |= (1 << inner_word_index);
  180. }
  181. UnsignedBigInteger UnsignedBigInteger::shift_left(size_t num_bits) const
  182. {
  183. // We can only do shift operations on individual words
  184. // where the shift amount is <= size of word (32).
  185. // But we do know how to shift by a multiple of word size (e.g 64=32*2)
  186. // So we first shift the result by how many whole words fit in 'num_bits'
  187. UnsignedBigInteger temp_result = shift_left_by_n_words(num_bits / UnsignedBigInteger::BITS_IN_WORD);
  188. // And now we shift by the leftover amount of bits
  189. num_bits %= UnsignedBigInteger::BITS_IN_WORD;
  190. UnsignedBigInteger result(temp_result);
  191. for (size_t i = 0; i < temp_result.length(); ++i) {
  192. u32 current_word_of_temp_result = temp_result.shift_left_get_one_word(num_bits, i);
  193. result.m_words[i] = current_word_of_temp_result;
  194. }
  195. // Shifting the last word can produce a carry
  196. u32 carry_word = temp_result.shift_left_get_one_word(num_bits, temp_result.length());
  197. if (carry_word != 0) {
  198. result = result.add(UnsignedBigInteger(carry_word).shift_left_by_n_words(temp_result.length()));
  199. }
  200. return result;
  201. }
  202. UnsignedBigInteger UnsignedBigInteger::shift_left_by_n_words(const size_t number_of_words) const
  203. {
  204. // shifting left by N words means just inserting N zeroes to the beginning of the words vector
  205. UnsignedBigInteger result;
  206. for (size_t i = 0; i < number_of_words; ++i) {
  207. result.m_words.append(0);
  208. }
  209. for (size_t i = 0; i < length(); ++i) {
  210. result.m_words.append(m_words[i]);
  211. }
  212. return result;
  213. }
  214. /**
  215. * Returns the word at a requested index in the result of a shift operation
  216. */
  217. u32 UnsignedBigInteger::shift_left_get_one_word(const size_t num_bits, const size_t result_word_index) const
  218. {
  219. // "<= length()" (rather than length() - 1) is intentional,
  220. // The result inedx of length() is used when calculating the carry word
  221. ASSERT(result_word_index <= length());
  222. ASSERT(num_bits <= UnsignedBigInteger::BITS_IN_WORD);
  223. u32 result = 0;
  224. // we need to check for "num_bits != 0" since shifting right by 32 is apparently undefined behaviour!
  225. if (result_word_index > 0 && num_bits != 0) {
  226. result += m_words[result_word_index - 1] >> (UnsignedBigInteger::BITS_IN_WORD - num_bits);
  227. }
  228. if (result_word_index < length() && num_bits < 32) {
  229. result += m_words[result_word_index] << num_bits;
  230. }
  231. return result;
  232. }
  233. bool UnsignedBigInteger::operator==(const UnsignedBigInteger& other) const
  234. {
  235. auto length = trimmed_length();
  236. if (length != other.trimmed_length()) {
  237. return false;
  238. }
  239. if (is_invalid() != other.is_invalid()) {
  240. return false;
  241. }
  242. return !__builtin_memcmp(m_words.data(), other.words().data(), length);
  243. }
  244. bool UnsignedBigInteger::operator<(const UnsignedBigInteger& other) const
  245. {
  246. auto length = trimmed_length();
  247. auto other_length = other.trimmed_length();
  248. if (length < other_length) {
  249. return true;
  250. }
  251. if (length > other_length) {
  252. return false;
  253. }
  254. if (length == 0) {
  255. return false;
  256. }
  257. for (int i = length - 1; i >= 0; --i) {
  258. if (m_words[i] == other.m_words[i])
  259. continue;
  260. return m_words[i] < other.m_words[i];
  261. }
  262. return false;
  263. }
  264. size_t UnsignedBigInteger::trimmed_length() const
  265. {
  266. size_t num_leading_zeroes = 0;
  267. for (int i = length() - 1; i >= 0; --i, ++num_leading_zeroes) {
  268. if (m_words[i] != 0)
  269. break;
  270. }
  271. return length() - num_leading_zeroes;
  272. }
  273. UnsignedBigInteger UnsignedBigInteger::create_invalid()
  274. {
  275. UnsignedBigInteger invalid(0);
  276. invalid.invalidate();
  277. return invalid;
  278. }
  279. // FIXME: in great need of optimisation
  280. UnsignedBigInteger UnsignedBigInteger::import_data(const u8* ptr, size_t length)
  281. {
  282. UnsignedBigInteger integer { 0 };
  283. for (size_t i = 0; i < length; ++i) {
  284. auto part = UnsignedBigInteger { ptr[length - i - 1] }.shift_left(8 * i);
  285. integer = integer.add(part);
  286. }
  287. return integer;
  288. }
  289. size_t UnsignedBigInteger::export_data(AK::ByteBuffer& data)
  290. {
  291. UnsignedBigInteger copy { *this };
  292. size_t size = trimmed_length() * sizeof(u32);
  293. size_t i = 0;
  294. for (; i < size; ++i) {
  295. if (copy.length() == 0)
  296. break;
  297. data[size - i - 1] = copy.m_words[0] & 0xff;
  298. copy = copy.divide(256).quotient;
  299. }
  300. return i;
  301. }
  302. }