SignedBigInteger.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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(const u8* 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 doesnt 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(const SignedBigInteger& 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(const SignedBigInteger& 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), true };
  95. }
  96. // The result will be either zero, or negative.
  97. // y - x = - (x - y)
  98. return SignedBigInteger { m_unsigned_data.minus(other.m_unsigned_data) };
  99. }
  100. FLATTEN SignedBigInteger SignedBigInteger::plus(const UnsignedBigInteger& other) const
  101. {
  102. if (m_sign) {
  103. if (other < m_unsigned_data)
  104. return { m_unsigned_data.minus(other), true };
  105. return { other.minus(m_unsigned_data), false };
  106. }
  107. return { m_unsigned_data.plus(other), false };
  108. }
  109. FLATTEN SignedBigInteger SignedBigInteger::minus(const UnsignedBigInteger& other) const
  110. {
  111. if (m_sign)
  112. return { m_unsigned_data.plus(m_unsigned_data), true };
  113. if (other < m_unsigned_data)
  114. return { m_unsigned_data.minus(other), false };
  115. return { other.minus(m_unsigned_data), true };
  116. }
  117. FLATTEN SignedBigInteger SignedBigInteger::bitwise_or(const UnsignedBigInteger& other) const
  118. {
  119. return { unsigned_value().bitwise_or(other), m_sign };
  120. }
  121. FLATTEN SignedBigInteger SignedBigInteger::bitwise_and(const UnsignedBigInteger& other) const
  122. {
  123. return { unsigned_value().bitwise_and(other), false };
  124. }
  125. FLATTEN SignedBigInteger SignedBigInteger::bitwise_xor(const UnsignedBigInteger& other) const
  126. {
  127. return { unsigned_value().bitwise_xor(other), m_sign };
  128. }
  129. FLATTEN SignedBigInteger SignedBigInteger::bitwise_not() const
  130. {
  131. return { unsigned_value().bitwise_not(), !m_sign };
  132. }
  133. FLATTEN SignedBigInteger SignedBigInteger::multiplied_by(UnsignedBigInteger const& other) const
  134. {
  135. return { unsigned_value().multiplied_by(other), m_sign };
  136. }
  137. FLATTEN SignedDivisionResult SignedBigInteger::divided_by(UnsignedBigInteger const& divisor) const
  138. {
  139. auto division_result = unsigned_value().divided_by(divisor);
  140. return {
  141. { move(division_result.quotient), m_sign },
  142. { move(division_result.remainder), m_sign },
  143. };
  144. }
  145. FLATTEN SignedBigInteger SignedBigInteger::bitwise_or(const SignedBigInteger& other) const
  146. {
  147. auto result = bitwise_or(other.unsigned_value());
  148. // The sign bit will have to be OR'd manually.
  149. result.m_sign = is_negative() || other.is_negative();
  150. return result;
  151. }
  152. FLATTEN SignedBigInteger SignedBigInteger::bitwise_and(const SignedBigInteger& other) const
  153. {
  154. auto result = bitwise_and(other.unsigned_value());
  155. // The sign bit will have to be AND'd manually.
  156. result.m_sign = is_negative() && other.is_negative();
  157. return result;
  158. }
  159. FLATTEN SignedBigInteger SignedBigInteger::bitwise_xor(const SignedBigInteger& other) const
  160. {
  161. auto result = bitwise_xor(other.unsigned_value());
  162. // The sign bit will have to be XOR'd manually.
  163. result.m_sign = is_negative() ^ other.is_negative();
  164. return result;
  165. }
  166. bool SignedBigInteger::operator==(const UnsignedBigInteger& other) const
  167. {
  168. if (m_sign)
  169. return false;
  170. return m_unsigned_data == other;
  171. }
  172. bool SignedBigInteger::operator!=(const UnsignedBigInteger& other) const
  173. {
  174. if (m_sign)
  175. return true;
  176. return m_unsigned_data != other;
  177. }
  178. bool SignedBigInteger::operator<(const UnsignedBigInteger& other) const
  179. {
  180. if (m_sign)
  181. return true;
  182. return m_unsigned_data < other;
  183. }
  184. bool SignedBigInteger::operator>(const UnsignedBigInteger& other) const
  185. {
  186. return *this != other && !(*this < other);
  187. }
  188. FLATTEN SignedBigInteger SignedBigInteger::shift_left(size_t num_bits) const
  189. {
  190. return SignedBigInteger { m_unsigned_data.shift_left(num_bits), m_sign };
  191. }
  192. FLATTEN SignedBigInteger SignedBigInteger::multiplied_by(const SignedBigInteger& other) const
  193. {
  194. bool result_sign = m_sign ^ other.m_sign;
  195. return { m_unsigned_data.multiplied_by(other.m_unsigned_data), result_sign };
  196. }
  197. FLATTEN SignedDivisionResult SignedBigInteger::divided_by(const SignedBigInteger& divisor) const
  198. {
  199. // Aa / Bb -> (A^B)q, Ar
  200. bool result_sign = m_sign ^ divisor.m_sign;
  201. auto unsigned_division_result = m_unsigned_data.divided_by(divisor.m_unsigned_data);
  202. return {
  203. { move(unsigned_division_result.quotient), result_sign },
  204. { move(unsigned_division_result.remainder), m_sign }
  205. };
  206. }
  207. u32 SignedBigInteger::hash() const
  208. {
  209. return m_unsigned_data.hash() * (1 - (2 * m_sign));
  210. }
  211. void SignedBigInteger::set_bit_inplace(size_t bit_index)
  212. {
  213. m_unsigned_data.set_bit_inplace(bit_index);
  214. }
  215. bool SignedBigInteger::operator==(const SignedBigInteger& other) const
  216. {
  217. if (is_invalid() != other.is_invalid())
  218. return false;
  219. if (m_unsigned_data == 0 && other.m_unsigned_data == 0)
  220. return true;
  221. return m_sign == other.m_sign && m_unsigned_data == other.m_unsigned_data;
  222. }
  223. bool SignedBigInteger::operator!=(const SignedBigInteger& other) const
  224. {
  225. return !(*this == other);
  226. }
  227. bool SignedBigInteger::operator<(const SignedBigInteger& other) const
  228. {
  229. if (m_sign ^ other.m_sign)
  230. return m_sign;
  231. if (m_sign)
  232. return other.m_unsigned_data < m_unsigned_data;
  233. return m_unsigned_data < other.m_unsigned_data;
  234. }
  235. bool SignedBigInteger::operator<=(const SignedBigInteger& other) const
  236. {
  237. return *this < other || *this == other;
  238. }
  239. bool SignedBigInteger::operator>(const SignedBigInteger& other) const
  240. {
  241. return *this != other && !(*this < other);
  242. }
  243. bool SignedBigInteger::operator>=(const SignedBigInteger& other) const
  244. {
  245. return !(*this < other);
  246. }
  247. }