SignedBigInteger.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. * Copyright (c) 2022, David Tuin <davidot@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "SignedBigInteger.h"
  8. #include <AK/StringBuilder.h>
  9. #include <math.h>
  10. namespace Crypto {
  11. SignedBigInteger::SignedBigInteger(double value)
  12. : m_sign(value < 0.0)
  13. , m_unsigned_data(fabs(value))
  14. {
  15. }
  16. SignedBigInteger SignedBigInteger::import_data(u8 const* ptr, size_t length)
  17. {
  18. bool sign = *ptr;
  19. auto unsigned_data = UnsignedBigInteger::import_data(ptr + 1, length - 1);
  20. return { move(unsigned_data), sign };
  21. }
  22. size_t SignedBigInteger::export_data(Bytes data, bool remove_leading_zeros) const
  23. {
  24. // FIXME: Support this:
  25. // m <0XX> -> m <XX> (if remove_leading_zeros)
  26. VERIFY(!remove_leading_zeros);
  27. data[0] = m_sign;
  28. auto bytes_view = data.slice(1, data.size() - 1);
  29. return m_unsigned_data.export_data(bytes_view, remove_leading_zeros) + 1;
  30. }
  31. SignedBigInteger SignedBigInteger::from_base(u16 N, StringView str)
  32. {
  33. auto sign = false;
  34. if (str.length() > 1) {
  35. auto maybe_sign = str[0];
  36. if (maybe_sign == '-') {
  37. str = str.substring_view(1);
  38. sign = true;
  39. }
  40. if (maybe_sign == '+')
  41. str = str.substring_view(1);
  42. }
  43. auto unsigned_data = UnsignedBigInteger::from_base(N, str);
  44. return { move(unsigned_data), sign };
  45. }
  46. String SignedBigInteger::to_base(u16 N) const
  47. {
  48. StringBuilder builder;
  49. if (m_sign)
  50. builder.append('-');
  51. builder.append(m_unsigned_data.to_base(N));
  52. return builder.to_string();
  53. }
  54. u64 SignedBigInteger::to_u64() const
  55. {
  56. u64 unsigned_value = m_unsigned_data.to_u64();
  57. if (!m_sign)
  58. return unsigned_value;
  59. return ~(unsigned_value - 1); // equivalent to `-unsigned_value`, but doesn't trigger UBSAN
  60. }
  61. double SignedBigInteger::to_double(UnsignedBigInteger::RoundingMode rounding_mode) const
  62. {
  63. double unsigned_value = m_unsigned_data.to_double(rounding_mode);
  64. if (!m_sign)
  65. return unsigned_value;
  66. VERIFY(!is_zero());
  67. return -unsigned_value;
  68. }
  69. FLATTEN SignedBigInteger SignedBigInteger::plus(SignedBigInteger const& other) const
  70. {
  71. // If both are of the same sign, just add the unsigned data and return.
  72. if (m_sign == other.m_sign)
  73. return { other.m_unsigned_data.plus(m_unsigned_data), m_sign };
  74. // One value is signed while the other is not.
  75. return m_sign ? other.minus(this->m_unsigned_data) : minus(other.m_unsigned_data);
  76. }
  77. FLATTEN SignedBigInteger SignedBigInteger::minus(SignedBigInteger const& other) const
  78. {
  79. // If the signs are different, convert the op to an addition.
  80. if (m_sign != other.m_sign) {
  81. // -x - y = - (x + y)
  82. // x - -y = (x + y)
  83. SignedBigInteger result { other.m_unsigned_data.plus(this->m_unsigned_data) };
  84. if (m_sign)
  85. result.negate();
  86. return result;
  87. }
  88. if (!m_sign) {
  89. // Both operands are positive.
  90. // x - y = - (y - x)
  91. if (m_unsigned_data < other.m_unsigned_data) {
  92. // The result will be negative.
  93. return { other.m_unsigned_data.minus(m_unsigned_data), true };
  94. }
  95. // The result will be either zero, or positive.
  96. return SignedBigInteger { m_unsigned_data.minus(other.m_unsigned_data) };
  97. }
  98. // Both operands are negative.
  99. // -x - -y = y - x
  100. if (m_unsigned_data < other.m_unsigned_data) {
  101. // The result will be positive.
  102. return SignedBigInteger { other.m_unsigned_data.minus(m_unsigned_data) };
  103. }
  104. // y - x = - (x - y)
  105. if (m_unsigned_data > other.m_unsigned_data) {
  106. // The result will be negative.
  107. return SignedBigInteger { m_unsigned_data.minus(other.m_unsigned_data), true };
  108. }
  109. // Both operands have the same magnitude, the result is positive zero.
  110. return SignedBigInteger { 0 };
  111. }
  112. FLATTEN SignedBigInteger SignedBigInteger::plus(UnsignedBigInteger const& other) const
  113. {
  114. if (m_sign) {
  115. if (other < m_unsigned_data)
  116. return { m_unsigned_data.minus(other), true };
  117. return { other.minus(m_unsigned_data), false };
  118. }
  119. return { m_unsigned_data.plus(other), false };
  120. }
  121. FLATTEN SignedBigInteger SignedBigInteger::minus(UnsignedBigInteger const& other) const
  122. {
  123. if (m_sign)
  124. return { m_unsigned_data.plus(m_unsigned_data), true };
  125. if (other < m_unsigned_data)
  126. return { m_unsigned_data.minus(other), false };
  127. return { other.minus(m_unsigned_data), true };
  128. }
  129. FLATTEN SignedBigInteger SignedBigInteger::bitwise_not() const
  130. {
  131. // Bitwise operators assume two's complement, while SignedBigInteger uses sign-magnitude.
  132. // In two's complement, -x := ~x + 1.
  133. // Hence, ~x == -x -1 == -(x + 1).
  134. SignedBigInteger result = plus(SignedBigInteger { 1 });
  135. result.negate();
  136. return result;
  137. }
  138. FLATTEN SignedBigInteger SignedBigInteger::multiplied_by(UnsignedBigInteger const& other) const
  139. {
  140. return { unsigned_value().multiplied_by(other), m_sign };
  141. }
  142. FLATTEN SignedDivisionResult SignedBigInteger::divided_by(UnsignedBigInteger const& divisor) const
  143. {
  144. auto division_result = unsigned_value().divided_by(divisor);
  145. return {
  146. { move(division_result.quotient), m_sign },
  147. { move(division_result.remainder), m_sign },
  148. };
  149. }
  150. FLATTEN SignedBigInteger SignedBigInteger::bitwise_or(SignedBigInteger const& other) const
  151. {
  152. // See bitwise_and() for derivations.
  153. if (!is_negative() && !other.is_negative())
  154. return { unsigned_value().bitwise_or(other.unsigned_value()), false };
  155. // -A | B == (~A + 1) | B == ~(A - 1) | B. The result is negative, so need to two's complement at the end to move the sign into the m_sign field.
  156. // That can be simplified to:
  157. // -(-A | B) == ~(~(A - 1) | B) + 1 = (A - 1) & ~B + 1
  158. // This saves one ~.
  159. if (is_negative() && !other.is_negative()) {
  160. size_t index = unsigned_value().one_based_index_of_highest_set_bit();
  161. return { unsigned_value().minus(1).bitwise_and(other.unsigned_value().bitwise_not_fill_to_one_based_index(index)).plus(1), true };
  162. }
  163. // -(A | -B) == ~A & (B - 1) + 1
  164. if (!is_negative() && other.is_negative()) {
  165. size_t index = other.unsigned_value().one_based_index_of_highest_set_bit();
  166. return { unsigned_value().bitwise_not_fill_to_one_based_index(index).bitwise_and(other.unsigned_value().minus(1)).plus(1), true };
  167. }
  168. return { unsigned_value().minus(1).bitwise_and(other.unsigned_value().minus(1)).plus(1), true };
  169. }
  170. FLATTEN SignedBigInteger SignedBigInteger::bitwise_and(SignedBigInteger const& other) const
  171. {
  172. if (!is_negative() && !other.is_negative())
  173. return { unsigned_value().bitwise_and(other.unsigned_value()), false };
  174. // These two just use that -x == ~x + 1 (see below).
  175. // -A & B == (~A + 1) & B.
  176. if (is_negative() && !other.is_negative()) {
  177. size_t index = other.unsigned_value().one_based_index_of_highest_set_bit();
  178. return { unsigned_value().bitwise_not_fill_to_one_based_index(index).plus(1).bitwise_and(other.unsigned_value()), false };
  179. }
  180. // A & -B == A & (~B + 1).
  181. if (!is_negative() && other.is_negative()) {
  182. size_t index = unsigned_value().one_based_index_of_highest_set_bit();
  183. return { unsigned_value().bitwise_and(other.unsigned_value().bitwise_not_fill_to_one_based_index(index).plus(1)), false };
  184. }
  185. // Both numbers are negative.
  186. // x + ~x == 0xff...ff, up to however many bits x is wide.
  187. // In two's complement, x + ~x + 1 == 0 since the 1 in the overflowing bit position is masked out.
  188. // Rearranging terms, ~x = -x - 1 (eq1).
  189. // Substituting x = y - 1, ~(y - 1) == -(y - 1) - 1 == -y +1 -1 == -y, or ~(y - 1) == -y (eq2).
  190. // Since both numbers are negative, we want to compute -A & -B.
  191. // Per (eq2):
  192. // -A & -B == ~(A - 1) & ~(B - 1)
  193. // Inverting both sides:
  194. // ~(-A & -B) == ~(~(A - 1) & ~(B - 1)) == ~~(A - 1) | ~~(B - 1) == (A - 1) | (B - 1).
  195. // Applying (q1) on the LHS:
  196. // -(-A & -B) - 1 == (A - 1) | (B - 1)
  197. // Adding 1 on both sides and then multiplying both sides by -1:
  198. // -A & -B == -( (A - 1) | (B - 1) + 1)
  199. // So we can compute the bitwise and by returning a negative number with magnitude (A - 1) | (B - 1) + 1.
  200. // This is better than the naive (~A + 1) & (~B + 1) because it needs just one O(n) scan for the or instead of 2 for the ~s.
  201. return { unsigned_value().minus(1).bitwise_or(other.unsigned_value().minus(1)).plus(1), true };
  202. }
  203. FLATTEN SignedBigInteger SignedBigInteger::bitwise_xor(SignedBigInteger const& other) const
  204. {
  205. return bitwise_or(other).minus(bitwise_and(other));
  206. }
  207. bool SignedBigInteger::operator==(UnsignedBigInteger const& other) const
  208. {
  209. if (m_sign)
  210. return false;
  211. return m_unsigned_data == other;
  212. }
  213. bool SignedBigInteger::operator!=(UnsignedBigInteger const& other) const
  214. {
  215. if (m_sign)
  216. return true;
  217. return m_unsigned_data != other;
  218. }
  219. bool SignedBigInteger::operator<(UnsignedBigInteger const& other) const
  220. {
  221. if (m_sign)
  222. return true;
  223. return m_unsigned_data < other;
  224. }
  225. bool SignedBigInteger::operator>(UnsignedBigInteger const& other) const
  226. {
  227. return *this != other && !(*this < other);
  228. }
  229. FLATTEN SignedBigInteger SignedBigInteger::shift_left(size_t num_bits) const
  230. {
  231. return SignedBigInteger { m_unsigned_data.shift_left(num_bits), m_sign };
  232. }
  233. FLATTEN SignedBigInteger SignedBigInteger::multiplied_by(SignedBigInteger const& other) const
  234. {
  235. bool result_sign = m_sign ^ other.m_sign;
  236. return { m_unsigned_data.multiplied_by(other.m_unsigned_data), result_sign };
  237. }
  238. FLATTEN SignedDivisionResult SignedBigInteger::divided_by(SignedBigInteger const& divisor) const
  239. {
  240. // Aa / Bb -> (A^B)q, Ar
  241. bool result_sign = m_sign ^ divisor.m_sign;
  242. auto unsigned_division_result = m_unsigned_data.divided_by(divisor.m_unsigned_data);
  243. return {
  244. { move(unsigned_division_result.quotient), result_sign },
  245. { move(unsigned_division_result.remainder), m_sign }
  246. };
  247. }
  248. u32 SignedBigInteger::hash() const
  249. {
  250. return m_unsigned_data.hash() * (1 - (2 * m_sign));
  251. }
  252. void SignedBigInteger::set_bit_inplace(size_t bit_index)
  253. {
  254. m_unsigned_data.set_bit_inplace(bit_index);
  255. }
  256. bool SignedBigInteger::operator==(SignedBigInteger const& other) const
  257. {
  258. if (is_invalid() != other.is_invalid())
  259. return false;
  260. if (m_unsigned_data == 0 && other.m_unsigned_data == 0)
  261. return true;
  262. return m_sign == other.m_sign && m_unsigned_data == other.m_unsigned_data;
  263. }
  264. bool SignedBigInteger::operator!=(SignedBigInteger const& other) const
  265. {
  266. return !(*this == other);
  267. }
  268. bool SignedBigInteger::operator<(SignedBigInteger const& other) const
  269. {
  270. if (m_sign ^ other.m_sign)
  271. return m_sign;
  272. if (m_sign)
  273. return other.m_unsigned_data < m_unsigned_data;
  274. return m_unsigned_data < other.m_unsigned_data;
  275. }
  276. bool SignedBigInteger::operator<=(SignedBigInteger const& other) const
  277. {
  278. return *this < other || *this == other;
  279. }
  280. bool SignedBigInteger::operator>(SignedBigInteger const& other) const
  281. {
  282. return *this != other && !(*this < other);
  283. }
  284. bool SignedBigInteger::operator>=(SignedBigInteger const& other) const
  285. {
  286. return !(*this < other);
  287. }
  288. SignedBigInteger::CompareResult SignedBigInteger::compare_to_double(double value) const
  289. {
  290. VERIFY(!isnan(value));
  291. if (isinf(value)) {
  292. bool is_positive_infinity = __builtin_isinf_sign(value) > 0;
  293. return is_positive_infinity ? CompareResult::DoubleGreaterThanBigInt : CompareResult::DoubleLessThanBigInt;
  294. }
  295. bool bigint_is_negative = m_sign;
  296. bool value_is_negative = value < 0;
  297. if (value_is_negative != bigint_is_negative)
  298. return bigint_is_negative ? CompareResult::DoubleGreaterThanBigInt : CompareResult::DoubleLessThanBigInt;
  299. // Value is zero, and from above the signs must be the same.
  300. if (value == 0.0) {
  301. VERIFY(!value_is_negative && !bigint_is_negative);
  302. // Either we are also zero or value is certainly less than us.
  303. return is_zero() ? CompareResult::DoubleEqualsBigInt : CompareResult::DoubleLessThanBigInt;
  304. }
  305. // If value is not zero but we are, then since the signs are the same value must be greater.
  306. if (is_zero())
  307. return CompareResult::DoubleGreaterThanBigInt;
  308. constexpr u64 mantissa_size = 52;
  309. constexpr u64 exponent_size = 11;
  310. constexpr auto exponent_bias = (1 << (exponent_size - 1)) - 1;
  311. union FloatExtractor {
  312. struct {
  313. unsigned long long mantissa : mantissa_size;
  314. unsigned exponent : exponent_size;
  315. unsigned sign : 1;
  316. };
  317. double d;
  318. } extractor;
  319. extractor.d = value;
  320. VERIFY(extractor.exponent != (1 << exponent_size) - 1);
  321. // Exponent cannot be filled as than we must be NaN or infinity.
  322. i32 real_exponent = extractor.exponent - exponent_bias;
  323. if (real_exponent < 0) {
  324. // |value| is less than 1, and we cannot be zero so if we are negative
  325. // value must be greater and vice versa.
  326. return bigint_is_negative ? CompareResult::DoubleGreaterThanBigInt : CompareResult::DoubleLessThanBigInt;
  327. }
  328. u64 bigint_bits_needed = m_unsigned_data.one_based_index_of_highest_set_bit();
  329. VERIFY(bigint_bits_needed > 0);
  330. // Double value is `-1^sign (1.mantissa) * 2^(exponent - bias)` so we need
  331. // `exponent - bias + 1` bit to represent doubles value,
  332. // for example `exponent - bias` = 3, sign = 0 and mantissa = 0 we get
  333. // `-1^0 * 2^3 * 1 = 8` which needs 4 bits to store 8 (0b1000).
  334. u32 double_bits_needed = real_exponent + 1;
  335. if (bigint_bits_needed > double_bits_needed) {
  336. // If we need more bits to represent us, we must be of greater magnitude
  337. // this means that if we are negative we are below value and if positive above value.
  338. return bigint_is_negative ? CompareResult::DoubleGreaterThanBigInt : CompareResult::DoubleLessThanBigInt;
  339. }
  340. if (bigint_bits_needed < double_bits_needed)
  341. return bigint_is_negative ? CompareResult::DoubleLessThanBigInt : CompareResult::DoubleGreaterThanBigInt;
  342. u64 mantissa_bits = extractor.mantissa;
  343. // We add the bit which represents the 1. of the double value calculation
  344. constexpr u64 mantissa_extended_bit = 1ull << mantissa_size;
  345. mantissa_bits |= mantissa_extended_bit;
  346. // Now we shift value to the left virtually, with `exponent - bias` steps
  347. // we then pretend both it and the big int are extended with virtual zeros.
  348. using Word = UnsignedBigInteger::Word;
  349. auto next_bigint_word = (UnsignedBigInteger::BITS_IN_WORD - 1 + bigint_bits_needed) / UnsignedBigInteger::BITS_IN_WORD;
  350. VERIFY(next_bigint_word + 1 == trimmed_length());
  351. auto msb_in_top_word_index = (bigint_bits_needed - 1) % UnsignedBigInteger::BITS_IN_WORD;
  352. VERIFY(msb_in_top_word_index == (UnsignedBigInteger::BITS_IN_WORD - count_leading_zeroes(words()[next_bigint_word - 1]) - 1));
  353. // We will keep the bits which are still valid in the mantissa at the top of mantissa bits.
  354. mantissa_bits <<= 64 - (mantissa_size + 1);
  355. auto bits_left_in_mantissa = mantissa_size + 1;
  356. auto get_next_value_bits = [&](size_t num_bits) -> Word {
  357. VERIFY(num_bits < 63);
  358. VERIFY(bits_left_in_mantissa > 0);
  359. if (num_bits > bits_left_in_mantissa)
  360. num_bits = bits_left_in_mantissa;
  361. bits_left_in_mantissa -= num_bits;
  362. u64 extracted_bits = mantissa_bits & (((1ull << num_bits) - 1) << (64 - num_bits));
  363. // Now shift the bits down to put the most significant bit on the num_bits position
  364. // this means the rest will be "virtual" zeros.
  365. extracted_bits >>= 32;
  366. // Now shift away the used bits and fit the result into a Word.
  367. mantissa_bits <<= num_bits;
  368. VERIFY(extracted_bits <= NumericLimits<Word>::max());
  369. return static_cast<Word>(extracted_bits);
  370. };
  371. auto bits_in_next_bigint_word = msb_in_top_word_index + 1;
  372. while (next_bigint_word > 0 && bits_left_in_mantissa > 0) {
  373. Word bigint_word = words()[next_bigint_word - 1];
  374. Word double_word = get_next_value_bits(bits_in_next_bigint_word);
  375. // For the first bit we have to align it with the top bit of bigint
  376. // and for all the other cases bits_in_next_bigint_word is 32 so this does nothing.
  377. double_word >>= 32 - bits_in_next_bigint_word;
  378. if (bigint_word < double_word)
  379. return value_is_negative ? CompareResult::DoubleLessThanBigInt : CompareResult::DoubleGreaterThanBigInt;
  380. if (bigint_word > double_word)
  381. return value_is_negative ? CompareResult::DoubleGreaterThanBigInt : CompareResult::DoubleLessThanBigInt;
  382. --next_bigint_word;
  383. bits_in_next_bigint_word = UnsignedBigInteger::BITS_IN_WORD;
  384. }
  385. // If there are still bits left in bigint than any non zero bit means it has greater magnitude.
  386. if (next_bigint_word > 0) {
  387. VERIFY(bits_left_in_mantissa == 0);
  388. while (next_bigint_word > 0) {
  389. if (words()[next_bigint_word - 1] != 0)
  390. return value_is_negative ? CompareResult::DoubleGreaterThanBigInt : CompareResult::DoubleLessThanBigInt;
  391. --next_bigint_word;
  392. }
  393. } else if (bits_left_in_mantissa > 0) {
  394. VERIFY(next_bigint_word == 0);
  395. // Similarly if there are still any bits set in the mantissa it has greater magnitude.
  396. if (mantissa_bits != 0)
  397. return value_is_negative ? CompareResult::DoubleLessThanBigInt : CompareResult::DoubleGreaterThanBigInt;
  398. }
  399. // Otherwise if both don't have bits left or the rest of the bits are zero they are equal.
  400. return CompareResult::DoubleEqualsBigInt;
  401. }
  402. }
  403. ErrorOr<void> AK::Formatter<Crypto::SignedBigInteger>::format(FormatBuilder& fmtbuilder, Crypto::SignedBigInteger const& value)
  404. {
  405. if (value.is_negative())
  406. TRY(fmtbuilder.put_string("-"sv));
  407. return Formatter<Crypto::UnsignedBigInteger>::format(fmtbuilder, value.unsigned_value());
  408. }