SignedBigInteger.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "SignedBigInteger.h"
  7. #include <AK/StringBuilder.h>
  8. namespace Crypto {
  9. SignedBigInteger SignedBigInteger::import_data(u8 const* ptr, size_t length)
  10. {
  11. bool sign = *ptr;
  12. auto unsigned_data = UnsignedBigInteger::import_data(ptr + 1, length - 1);
  13. return { move(unsigned_data), sign };
  14. }
  15. size_t SignedBigInteger::export_data(Bytes data, bool remove_leading_zeros) const
  16. {
  17. // FIXME: Support this:
  18. // m <0XX> -> m <XX> (if remove_leading_zeros)
  19. VERIFY(!remove_leading_zeros);
  20. data[0] = m_sign;
  21. auto bytes_view = data.slice(1, data.size() - 1);
  22. return m_unsigned_data.export_data(bytes_view, remove_leading_zeros) + 1;
  23. }
  24. SignedBigInteger SignedBigInteger::from_base(u16 N, StringView str)
  25. {
  26. auto sign = false;
  27. if (str.length() > 1) {
  28. auto maybe_sign = str[0];
  29. if (maybe_sign == '-') {
  30. str = str.substring_view(1);
  31. sign = true;
  32. }
  33. if (maybe_sign == '+')
  34. str = str.substring_view(1);
  35. }
  36. auto unsigned_data = UnsignedBigInteger::from_base(N, str);
  37. return { move(unsigned_data), sign };
  38. }
  39. String SignedBigInteger::to_base(u16 N) const
  40. {
  41. StringBuilder builder;
  42. if (m_sign)
  43. builder.append('-');
  44. builder.append(m_unsigned_data.to_base(N));
  45. return builder.to_string();
  46. }
  47. u64 SignedBigInteger::to_u64() const
  48. {
  49. u64 unsigned_value = m_unsigned_data.to_u64();
  50. if (!m_sign)
  51. return unsigned_value;
  52. return ~(unsigned_value - 1); // equivalent to `-unsigned_value`, but doesn't trigger UBSAN
  53. }
  54. double SignedBigInteger::to_double() const
  55. {
  56. double unsigned_value = m_unsigned_data.to_double();
  57. if (!m_sign)
  58. return unsigned_value;
  59. return -unsigned_value;
  60. }
  61. FLATTEN SignedBigInteger SignedBigInteger::plus(SignedBigInteger const& other) const
  62. {
  63. // If both are of the same sign, just add the unsigned data and return.
  64. if (m_sign == other.m_sign)
  65. return { other.m_unsigned_data.plus(m_unsigned_data), m_sign };
  66. // One value is signed while the other is not.
  67. return m_sign ? other.minus(this->m_unsigned_data) : minus(other.m_unsigned_data);
  68. }
  69. FLATTEN SignedBigInteger SignedBigInteger::minus(SignedBigInteger const& other) const
  70. {
  71. // If the signs are different, convert the op to an addition.
  72. if (m_sign != other.m_sign) {
  73. // -x - y = - (x + y)
  74. // x - -y = (x + y)
  75. SignedBigInteger result { other.m_unsigned_data.plus(this->m_unsigned_data) };
  76. if (m_sign)
  77. result.negate();
  78. return result;
  79. }
  80. if (!m_sign) {
  81. // Both operands are positive.
  82. // x - y = - (y - x)
  83. if (m_unsigned_data < other.m_unsigned_data) {
  84. // The result will be negative.
  85. return { other.m_unsigned_data.minus(m_unsigned_data), true };
  86. }
  87. // The result will be either zero, or positive.
  88. return SignedBigInteger { m_unsigned_data.minus(other.m_unsigned_data) };
  89. }
  90. // Both operands are negative.
  91. // -x - -y = y - x
  92. if (m_unsigned_data < other.m_unsigned_data) {
  93. // The result will be positive.
  94. return SignedBigInteger { other.m_unsigned_data.minus(m_unsigned_data) };
  95. }
  96. // y - x = - (x - y)
  97. if (m_unsigned_data > other.m_unsigned_data) {
  98. // The result will be negative.
  99. return SignedBigInteger { m_unsigned_data.minus(other.m_unsigned_data), true };
  100. }
  101. // Both operands have the same magnitude, the result is positive zero.
  102. return SignedBigInteger { 0 };
  103. }
  104. FLATTEN SignedBigInteger SignedBigInteger::plus(UnsignedBigInteger const& other) const
  105. {
  106. if (m_sign) {
  107. if (other < m_unsigned_data)
  108. return { m_unsigned_data.minus(other), true };
  109. return { other.minus(m_unsigned_data), false };
  110. }
  111. return { m_unsigned_data.plus(other), false };
  112. }
  113. FLATTEN SignedBigInteger SignedBigInteger::minus(UnsignedBigInteger const& other) const
  114. {
  115. if (m_sign)
  116. return { m_unsigned_data.plus(m_unsigned_data), true };
  117. if (other < m_unsigned_data)
  118. return { m_unsigned_data.minus(other), false };
  119. return { other.minus(m_unsigned_data), true };
  120. }
  121. FLATTEN SignedBigInteger SignedBigInteger::bitwise_not() const
  122. {
  123. // Bitwise operators assume two's complement, while SignedBigInteger uses sign-magnitude.
  124. // In two's complement, -x := ~x + 1.
  125. // Hence, ~x == -x -1 == -(x + 1).
  126. SignedBigInteger result = plus(SignedBigInteger { 1 });
  127. result.negate();
  128. return result;
  129. }
  130. FLATTEN SignedBigInteger SignedBigInteger::multiplied_by(UnsignedBigInteger const& other) const
  131. {
  132. return { unsigned_value().multiplied_by(other), m_sign };
  133. }
  134. FLATTEN SignedDivisionResult SignedBigInteger::divided_by(UnsignedBigInteger const& divisor) const
  135. {
  136. auto division_result = unsigned_value().divided_by(divisor);
  137. return {
  138. { move(division_result.quotient), m_sign },
  139. { move(division_result.remainder), m_sign },
  140. };
  141. }
  142. FLATTEN SignedBigInteger SignedBigInteger::bitwise_or(SignedBigInteger const& other) const
  143. {
  144. // See bitwise_and() for derivations.
  145. if (!is_negative() && !other.is_negative())
  146. return { unsigned_value().bitwise_or(other.unsigned_value()), false };
  147. // -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.
  148. // That can be simplified to:
  149. // -(-A | B) == ~(~(A - 1) | B) + 1 = (A - 1) & ~B + 1
  150. // This saves one ~.
  151. if (is_negative() && !other.is_negative()) {
  152. size_t index = unsigned_value().one_based_index_of_highest_set_bit();
  153. return { unsigned_value().minus(1).bitwise_and(other.unsigned_value().bitwise_not_fill_to_one_based_index(index)).plus(1), true };
  154. }
  155. // -(A | -B) == ~A & (B - 1) + 1
  156. if (!is_negative() && other.is_negative()) {
  157. size_t index = other.unsigned_value().one_based_index_of_highest_set_bit();
  158. return { unsigned_value().bitwise_not_fill_to_one_based_index(index).bitwise_and(other.unsigned_value().minus(1)).plus(1), true };
  159. }
  160. return { unsigned_value().minus(1).bitwise_and(other.unsigned_value().minus(1)).plus(1), true };
  161. }
  162. FLATTEN SignedBigInteger SignedBigInteger::bitwise_and(SignedBigInteger const& other) const
  163. {
  164. if (!is_negative() && !other.is_negative())
  165. return { unsigned_value().bitwise_and(other.unsigned_value()), false };
  166. // These two just use that -x == ~x + 1 (see below).
  167. // -A & B == (~A + 1) & B.
  168. if (is_negative() && !other.is_negative()) {
  169. size_t index = other.unsigned_value().one_based_index_of_highest_set_bit();
  170. return { unsigned_value().bitwise_not_fill_to_one_based_index(index).plus(1).bitwise_and(other.unsigned_value()), false };
  171. }
  172. // A & -B == A & (~B + 1).
  173. if (!is_negative() && other.is_negative()) {
  174. size_t index = unsigned_value().one_based_index_of_highest_set_bit();
  175. return { unsigned_value().bitwise_and(other.unsigned_value().bitwise_not_fill_to_one_based_index(index).plus(1)), false };
  176. }
  177. // Both numbers are negative.
  178. // x + ~x == 0xff...ff, up to however many bits x is wide.
  179. // In two's complement, x + ~x + 1 == 0 since the 1 in the overflowing bit position is masked out.
  180. // Rearranging terms, ~x = -x - 1 (eq1).
  181. // Substituting x = y - 1, ~(y - 1) == -(y - 1) - 1 == -y +1 -1 == -y, or ~(y - 1) == -y (eq2).
  182. // Since both numbers are negative, we want to compute -A & -B.
  183. // Per (eq2):
  184. // -A & -B == ~(A - 1) & ~(B - 1)
  185. // Inverting both sides:
  186. // ~(-A & -B) == ~(~(A - 1) & ~(B - 1)) == ~~(A - 1) | ~~(B - 1) == (A - 1) | (B - 1).
  187. // Applying (q1) on the LHS:
  188. // -(-A & -B) - 1 == (A - 1) | (B - 1)
  189. // Adding 1 on both sides and then multiplying both sides by -1:
  190. // -A & -B == -( (A - 1) | (B - 1) + 1)
  191. // So we can compute the bitwise and by returning a negative number with magnitude (A - 1) | (B - 1) + 1.
  192. // 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.
  193. return { unsigned_value().minus(1).bitwise_or(other.unsigned_value().minus(1)).plus(1), true };
  194. }
  195. FLATTEN SignedBigInteger SignedBigInteger::bitwise_xor(SignedBigInteger const& other) const
  196. {
  197. return bitwise_or(other).minus(bitwise_and(other));
  198. }
  199. bool SignedBigInteger::operator==(UnsignedBigInteger const& other) const
  200. {
  201. if (m_sign)
  202. return false;
  203. return m_unsigned_data == other;
  204. }
  205. bool SignedBigInteger::operator!=(UnsignedBigInteger const& other) const
  206. {
  207. if (m_sign)
  208. return true;
  209. return m_unsigned_data != other;
  210. }
  211. bool SignedBigInteger::operator<(UnsignedBigInteger const& other) const
  212. {
  213. if (m_sign)
  214. return true;
  215. return m_unsigned_data < other;
  216. }
  217. bool SignedBigInteger::operator>(UnsignedBigInteger const& other) const
  218. {
  219. return *this != other && !(*this < other);
  220. }
  221. FLATTEN SignedBigInteger SignedBigInteger::shift_left(size_t num_bits) const
  222. {
  223. return SignedBigInteger { m_unsigned_data.shift_left(num_bits), m_sign };
  224. }
  225. FLATTEN SignedBigInteger SignedBigInteger::multiplied_by(SignedBigInteger const& other) const
  226. {
  227. bool result_sign = m_sign ^ other.m_sign;
  228. return { m_unsigned_data.multiplied_by(other.m_unsigned_data), result_sign };
  229. }
  230. FLATTEN SignedDivisionResult SignedBigInteger::divided_by(SignedBigInteger const& divisor) const
  231. {
  232. // Aa / Bb -> (A^B)q, Ar
  233. bool result_sign = m_sign ^ divisor.m_sign;
  234. auto unsigned_division_result = m_unsigned_data.divided_by(divisor.m_unsigned_data);
  235. return {
  236. { move(unsigned_division_result.quotient), result_sign },
  237. { move(unsigned_division_result.remainder), m_sign }
  238. };
  239. }
  240. u32 SignedBigInteger::hash() const
  241. {
  242. return m_unsigned_data.hash() * (1 - (2 * m_sign));
  243. }
  244. void SignedBigInteger::set_bit_inplace(size_t bit_index)
  245. {
  246. m_unsigned_data.set_bit_inplace(bit_index);
  247. }
  248. bool SignedBigInteger::operator==(SignedBigInteger const& other) const
  249. {
  250. if (is_invalid() != other.is_invalid())
  251. return false;
  252. if (m_unsigned_data == 0 && other.m_unsigned_data == 0)
  253. return true;
  254. return m_sign == other.m_sign && m_unsigned_data == other.m_unsigned_data;
  255. }
  256. bool SignedBigInteger::operator!=(SignedBigInteger const& other) const
  257. {
  258. return !(*this == other);
  259. }
  260. bool SignedBigInteger::operator<(SignedBigInteger const& other) const
  261. {
  262. if (m_sign ^ other.m_sign)
  263. return m_sign;
  264. if (m_sign)
  265. return other.m_unsigned_data < m_unsigned_data;
  266. return m_unsigned_data < other.m_unsigned_data;
  267. }
  268. bool SignedBigInteger::operator<=(SignedBigInteger const& other) const
  269. {
  270. return *this < other || *this == other;
  271. }
  272. bool SignedBigInteger::operator>(SignedBigInteger const& other) const
  273. {
  274. return *this != other && !(*this < other);
  275. }
  276. bool SignedBigInteger::operator>=(SignedBigInteger const& other) const
  277. {
  278. return !(*this < other);
  279. }
  280. }
  281. ErrorOr<void> AK::Formatter<Crypto::SignedBigInteger>::format(FormatBuilder& fmtbuilder, Crypto::SignedBigInteger const& value)
  282. {
  283. if (value.is_negative())
  284. TRY(fmtbuilder.put_string("-"));
  285. return Formatter<Crypto::UnsignedBigInteger>::format(fmtbuilder, value.unsigned_value());
  286. }