/src/serenity/Userland/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com> |
3 | | * Copyright (c) 2022, David Tuin <davidot@serenityos.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include "UnsignedBigInteger.h" |
9 | | #include <AK/BuiltinWrappers.h> |
10 | | #include <AK/CharacterTypes.h> |
11 | | #include <AK/FloatingPoint.h> |
12 | | #include <AK/StringBuilder.h> |
13 | | #include <AK/StringHash.h> |
14 | | #include <LibCrypto/BigInt/Algorithms/UnsignedBigIntegerAlgorithms.h> |
15 | | #include <math.h> |
16 | | |
17 | | namespace Crypto { |
18 | | |
19 | | UnsignedBigInteger::UnsignedBigInteger(u8 const* ptr, size_t length) |
20 | 7.98k | { |
21 | 7.98k | m_words.resize_and_keep_capacity((length + sizeof(u32) - 1) / sizeof(u32)); |
22 | 7.98k | size_t in = length, out = 0; |
23 | 6.50M | while (in >= sizeof(u32)) { |
24 | 6.50M | in -= sizeof(u32); |
25 | 6.50M | u32 word = ((u32)ptr[in] << 24) | ((u32)ptr[in + 1] << 16) | ((u32)ptr[in + 2] << 8) | (u32)ptr[in + 3]; |
26 | 6.50M | m_words[out++] = word; |
27 | 6.50M | } |
28 | 7.98k | if (in > 0) { |
29 | 6.87k | u32 word = 0; |
30 | 16.2k | for (size_t i = 0; i < in; i++) { |
31 | 9.37k | word <<= 8; |
32 | 9.37k | word |= (u32)ptr[i]; |
33 | 9.37k | } |
34 | 6.87k | m_words[out++] = word; |
35 | 6.87k | } |
36 | 7.98k | } |
37 | | |
38 | | UnsignedBigInteger::UnsignedBigInteger(double value) |
39 | 0 | { |
40 | | // Because this is currently only used for LibJS we VERIFY some preconditions |
41 | | // also these values don't have a clear BigInteger representation. |
42 | 0 | VERIFY(!isnan(value)); |
43 | 0 | VERIFY(!isinf(value)); |
44 | 0 | VERIFY(trunc(value) == value); |
45 | 0 | VERIFY(value >= 0.0); |
46 | | |
47 | 0 | if (value <= NumericLimits<u32>::max()) { |
48 | 0 | m_words.append(static_cast<u32>(value)); |
49 | 0 | return; |
50 | 0 | } |
51 | | |
52 | 0 | auto extractor = FloatExtractor<double>::from_float(value); |
53 | 0 | VERIFY(!extractor.sign); |
54 | | |
55 | 0 | i32 real_exponent = extractor.exponent - extractor.exponent_bias; |
56 | 0 | VERIFY(real_exponent > 0); |
57 | | |
58 | | // Ensure we have enough space, we will need 2^exponent bits, so round up in words |
59 | 0 | auto word_index = (real_exponent + BITS_IN_WORD) / BITS_IN_WORD; |
60 | 0 | m_words.resize_and_keep_capacity(word_index); |
61 | | |
62 | | // Now we just need to put the mantissa with explicit 1 bit at the top at the proper location |
63 | 0 | u64 raw_mantissa = extractor.mantissa | (1ull << extractor.mantissa_bits); |
64 | 0 | VERIFY((raw_mantissa & 0xfff0000000000000) == 0x0010000000000000); |
65 | | // Shift it so the bits we need are at the top |
66 | 0 | raw_mantissa <<= 64 - extractor.mantissa_bits - 1; |
67 | | |
68 | | // The initial bit needs to be exactly aligned with exponent, this is 1-indexed |
69 | 0 | auto top_word_bit_offset = real_exponent % BITS_IN_WORD + 1; |
70 | |
|
71 | 0 | auto top_word_bits_from_mantissa = raw_mantissa >> (64 - top_word_bit_offset); |
72 | 0 | VERIFY(top_word_bits_from_mantissa <= NumericLimits<Word>::max()); |
73 | 0 | m_words[word_index - 1] = top_word_bits_from_mantissa; |
74 | |
|
75 | 0 | --word_index; |
76 | | // Shift used bits away |
77 | 0 | raw_mantissa <<= top_word_bit_offset; |
78 | 0 | i32 bits_in_mantissa = extractor.mantissa_bits + 1 - top_word_bit_offset; |
79 | | // Now just put everything at the top of the next words |
80 | |
|
81 | 0 | constexpr auto to_word_shift = 64 - BITS_IN_WORD; |
82 | |
|
83 | 0 | while (word_index > 0 && bits_in_mantissa > 0) { |
84 | 0 | VERIFY((raw_mantissa >> to_word_shift) <= NumericLimits<Word>::max()); |
85 | 0 | m_words[word_index - 1] = raw_mantissa >> to_word_shift; |
86 | 0 | raw_mantissa <<= to_word_shift; |
87 | |
|
88 | 0 | bits_in_mantissa -= BITS_IN_WORD; |
89 | 0 | --word_index; |
90 | 0 | } |
91 | | |
92 | 0 | VERIFY(m_words.size() > word_index); |
93 | 0 | VERIFY((m_words.size() - word_index) <= 3); |
94 | | |
95 | | // No bits left, otherwise we would have to round |
96 | 0 | VERIFY(raw_mantissa == 0); |
97 | 0 | } |
98 | | |
99 | | UnsignedBigInteger UnsignedBigInteger::create_invalid() |
100 | 0 | { |
101 | 0 | UnsignedBigInteger invalid(0); |
102 | 0 | invalid.invalidate(); |
103 | 0 | return invalid; |
104 | 0 | } |
105 | | |
106 | | size_t UnsignedBigInteger::export_data(Bytes data, bool remove_leading_zeros) const |
107 | 0 | { |
108 | 0 | size_t word_count = trimmed_length(); |
109 | 0 | size_t out = 0; |
110 | 0 | if (word_count > 0) { |
111 | 0 | ssize_t leading_zeros = -1; |
112 | 0 | if (remove_leading_zeros) { |
113 | 0 | UnsignedBigInteger::Word word = m_words[word_count - 1]; |
114 | 0 | u8 value[4] {}; |
115 | 0 | for (size_t i = 0; i < sizeof(u32); i++) { |
116 | 0 | u8 byte = (u8)(word >> ((sizeof(u32) - i - 1) * 8)); |
117 | 0 | value[i] = byte; |
118 | 0 | if (leading_zeros < 0 && byte != 0) |
119 | 0 | leading_zeros = (int)i; |
120 | 0 | } |
121 | 0 | data.overwrite(out, value, array_size(value)); |
122 | 0 | out += array_size(value); |
123 | 0 | } |
124 | 0 | for (size_t i = word_count - (remove_leading_zeros ? 1 : 0); i > 0; i--) { |
125 | 0 | auto word = m_words[i - 1]; |
126 | 0 | u8 value[] { (u8)(word >> 24), (u8)(word >> 16), (u8)(word >> 8), (u8)word }; |
127 | 0 | data.overwrite(out, value, array_size(value)); |
128 | 0 | out += array_size(value); |
129 | 0 | } |
130 | 0 | if (leading_zeros > 0) |
131 | 0 | out -= leading_zeros; |
132 | 0 | } |
133 | 0 | return out; |
134 | 0 | } |
135 | | |
136 | | ErrorOr<UnsignedBigInteger> UnsignedBigInteger::from_base(u16 N, StringView str) |
137 | 80 | { |
138 | 80 | VERIFY(N <= 36); |
139 | 80 | UnsignedBigInteger result; |
140 | 80 | UnsignedBigInteger base { N }; |
141 | | |
142 | 1.76k | for (auto const& c : str) { |
143 | 1.76k | if (c == '_') |
144 | 0 | continue; |
145 | 1.76k | if (!is_ascii_base36_digit(c)) |
146 | 0 | return Error::from_string_literal("Invalid Base36 digit"); |
147 | 1.76k | auto digit = parse_ascii_base36_digit(c); |
148 | 1.76k | if (digit >= N) |
149 | 0 | return Error::from_string_literal("Base36 digit out of range"); |
150 | | |
151 | 1.76k | result = result.multiplied_by(base).plus(digit); |
152 | 1.76k | } |
153 | 80 | return result; |
154 | 80 | } |
155 | | |
156 | | ErrorOr<String> UnsignedBigInteger::to_base(u16 N) const |
157 | 0 | { |
158 | 0 | VERIFY(N <= 36); |
159 | 0 | if (*this == UnsignedBigInteger { 0 }) |
160 | 0 | return "0"_string; |
161 | | |
162 | 0 | StringBuilder builder; |
163 | 0 | UnsignedBigInteger temp(*this); |
164 | 0 | UnsignedBigInteger quotient; |
165 | 0 | UnsignedBigInteger remainder; |
166 | |
|
167 | 0 | while (temp != UnsignedBigInteger { 0 }) { |
168 | 0 | UnsignedBigIntegerAlgorithms::divide_u16_without_allocation(temp, N, quotient, remainder); |
169 | 0 | VERIFY(remainder.words()[0] < N); |
170 | 0 | TRY(builder.try_append(to_ascii_base36_digit(remainder.words()[0]))); |
171 | 0 | temp.set_to(quotient); |
172 | 0 | } |
173 | | |
174 | 0 | return TRY(builder.to_string()).reverse(); |
175 | 0 | } |
176 | | |
177 | | ByteString UnsignedBigInteger::to_base_deprecated(u16 N) const |
178 | 0 | { |
179 | 0 | return MUST(to_base(N)).to_byte_string(); |
180 | 0 | } |
181 | | |
182 | | u64 UnsignedBigInteger::to_u64() const |
183 | 3.35k | { |
184 | 3.35k | static_assert(sizeof(Word) == 4); |
185 | 3.35k | if (!length()) |
186 | 576 | return 0; |
187 | 2.77k | u64 value = m_words[0]; |
188 | 2.77k | if (length() > 1) |
189 | 148 | value |= static_cast<u64>(m_words[1]) << 32; |
190 | 2.77k | return value; |
191 | 3.35k | } |
192 | | |
193 | | double UnsignedBigInteger::to_double(UnsignedBigInteger::RoundingMode rounding_mode) const |
194 | 0 | { |
195 | 0 | VERIFY(!is_invalid()); |
196 | 0 | auto highest_bit = one_based_index_of_highest_set_bit(); |
197 | 0 | if (highest_bit == 0) |
198 | 0 | return 0; |
199 | 0 | --highest_bit; |
200 | |
|
201 | 0 | using Extractor = FloatExtractor<double>; |
202 | | |
203 | | // Simple case if less than 2^53 since those number are all exactly representable in doubles |
204 | 0 | if (highest_bit < Extractor::mantissa_bits + 1) |
205 | 0 | return static_cast<double>(to_u64()); |
206 | | |
207 | | // If it uses too many bit to represent in a double return infinity |
208 | 0 | if (highest_bit > Extractor::exponent_bias) |
209 | 0 | return __builtin_huge_val(); |
210 | | |
211 | | // Otherwise we have to take the top 53 bits, use those as the mantissa, |
212 | | // and the amount of bits as the exponent. Note that the mantissa has an implicit top bit of 1 |
213 | | // so we have to ignore the very top bit. |
214 | | |
215 | | // Since we extract at most 53 bits it will take at most 3 words |
216 | 0 | static_assert(BITS_IN_WORD * 3 >= (Extractor::mantissa_bits + 1)); |
217 | 0 | constexpr auto bits_in_u64 = 64; |
218 | 0 | static_assert(bits_in_u64 > Extractor::mantissa_bits + 1); |
219 | |
|
220 | 0 | auto bits_to_read = min(static_cast<size_t>(Extractor::mantissa_bits), highest_bit); |
221 | |
|
222 | 0 | auto last_word_index = trimmed_length(); |
223 | 0 | VERIFY(last_word_index > 0); |
224 | | |
225 | | // Note that highest bit is 0-indexed at this point. |
226 | 0 | auto highest_bit_index_in_top_word = highest_bit % BITS_IN_WORD; |
227 | | |
228 | | // Shift initial word until highest bit is just beyond top of u64. |
229 | 0 | u64 mantissa = m_words[last_word_index - 1]; |
230 | 0 | if (highest_bit_index_in_top_word != 0) |
231 | 0 | mantissa <<= (bits_in_u64 - highest_bit_index_in_top_word); |
232 | 0 | else |
233 | 0 | mantissa = 0; |
234 | |
|
235 | 0 | auto bits_written = highest_bit_index_in_top_word; |
236 | |
|
237 | 0 | --last_word_index; |
238 | |
|
239 | 0 | Optional<Word> dropped_bits_for_rounding; |
240 | 0 | u8 bits_dropped_from_final_word = 0; |
241 | |
|
242 | 0 | if (bits_written < bits_to_read && last_word_index > 0) { |
243 | | // Second word can always just cleanly be shifted up to the final bit of the first word |
244 | | // since the first has at most BIT_IN_WORD - 1, 31 |
245 | 0 | u64 next_word = m_words[last_word_index - 1]; |
246 | 0 | VERIFY((mantissa & (next_word << (bits_in_u64 - bits_written - BITS_IN_WORD))) == 0); |
247 | 0 | mantissa |= next_word << (bits_in_u64 - bits_written - BITS_IN_WORD); |
248 | 0 | bits_written += BITS_IN_WORD; |
249 | 0 | --last_word_index; |
250 | |
|
251 | 0 | if (bits_written > bits_to_read) { |
252 | 0 | bits_dropped_from_final_word = bits_written - bits_to_read; |
253 | 0 | dropped_bits_for_rounding = m_words[last_word_index] & ((1 << bits_dropped_from_final_word) - 1); |
254 | 0 | } else if (bits_written < bits_to_read && last_word_index > 0) { |
255 | | // The final word has to be shifted down first to discard any excess bits. |
256 | 0 | u64 final_word = m_words[last_word_index - 1]; |
257 | 0 | --last_word_index; |
258 | |
|
259 | 0 | auto bits_to_write = bits_to_read - bits_written; |
260 | |
|
261 | 0 | bits_dropped_from_final_word = BITS_IN_WORD - bits_to_write; |
262 | 0 | dropped_bits_for_rounding = final_word & ((1 << bits_dropped_from_final_word) - 1u); |
263 | 0 | final_word >>= bits_dropped_from_final_word; |
264 | | |
265 | | // Then move the bits right up to the lowest bits of the second word |
266 | 0 | VERIFY((mantissa & (final_word << (bits_in_u64 - bits_written - bits_to_write))) == 0); |
267 | 0 | mantissa |= final_word << (bits_in_u64 - bits_written - bits_to_write); |
268 | 0 | } |
269 | 0 | } |
270 | | |
271 | | // Now the mantissa should be complete so shift it down |
272 | 0 | mantissa >>= bits_in_u64 - Extractor::mantissa_bits; |
273 | |
|
274 | 0 | if (rounding_mode == RoundingMode::IEEERoundAndTiesToEvenMantissa) { |
275 | 0 | bool round_up = false; |
276 | |
|
277 | 0 | if (bits_dropped_from_final_word == 0) { |
278 | 0 | if (last_word_index > 0) { |
279 | 0 | Word next_word = m_words[last_word_index - 1]; |
280 | 0 | last_word_index--; |
281 | 0 | if ((next_word & 0x80000000) != 0) { |
282 | | // next top bit set check for any other bits |
283 | 0 | if ((next_word ^ 0x80000000) != 0) { |
284 | 0 | round_up = true; |
285 | 0 | } else { |
286 | 0 | while (last_word_index > 0) { |
287 | 0 | if (m_words[last_word_index - 1] != 0) { |
288 | 0 | round_up = true; |
289 | 0 | break; |
290 | 0 | } |
291 | 0 | } |
292 | | |
293 | | // All other bits are 0 which is a tie thus round to even exponent |
294 | | // Since we are halfway, if exponent ends with 1 we round up, if 0 we round down |
295 | 0 | round_up = (mantissa & 1) != 0; |
296 | 0 | } |
297 | 0 | } else { |
298 | 0 | round_up = false; |
299 | 0 | } |
300 | 0 | } else { |
301 | | // If there are no words left the rest is implicitly 0 so just round down |
302 | 0 | round_up = false; |
303 | 0 | } |
304 | |
|
305 | 0 | } else { |
306 | 0 | VERIFY(dropped_bits_for_rounding.has_value()); |
307 | 0 | VERIFY(bits_dropped_from_final_word >= 1); |
308 | | |
309 | | // In this case the top bit comes form the dropped bits |
310 | 0 | auto top_bit_extractor = 1u << (bits_dropped_from_final_word - 1u); |
311 | 0 | if ((*dropped_bits_for_rounding & top_bit_extractor) != 0) { |
312 | | // Possible tie again, if any other bit is set we round up |
313 | 0 | if ((*dropped_bits_for_rounding ^ top_bit_extractor) != 0) { |
314 | 0 | round_up = true; |
315 | 0 | } else { |
316 | 0 | while (last_word_index > 0) { |
317 | 0 | if (m_words[last_word_index - 1] != 0) { |
318 | 0 | round_up = true; |
319 | 0 | break; |
320 | 0 | } |
321 | 0 | } |
322 | |
|
323 | 0 | round_up = (mantissa & 1) != 0; |
324 | 0 | } |
325 | 0 | } else { |
326 | 0 | round_up = false; |
327 | 0 | } |
328 | 0 | } |
329 | | |
330 | 0 | if (round_up) { |
331 | 0 | ++mantissa; |
332 | 0 | if ((mantissa & (1ull << Extractor::mantissa_bits)) != 0) { |
333 | | // we overflowed the mantissa |
334 | 0 | mantissa = 0; |
335 | 0 | highest_bit++; |
336 | | |
337 | | // In which case it is possible we have to round to infinity |
338 | 0 | if (highest_bit > Extractor::exponent_bias) |
339 | 0 | return __builtin_huge_val(); |
340 | 0 | } |
341 | 0 | } |
342 | 0 | } else { |
343 | 0 | VERIFY(rounding_mode == RoundingMode::RoundTowardZero); |
344 | 0 | } |
345 | | |
346 | 0 | Extractor extractor; |
347 | 0 | extractor.exponent = highest_bit + extractor.exponent_bias; |
348 | |
|
349 | 0 | VERIFY((mantissa & 0xfff0000000000000) == 0); |
350 | 0 | extractor.mantissa = mantissa; |
351 | |
|
352 | 0 | return extractor.to_float(); |
353 | 0 | } |
354 | | |
355 | | void UnsignedBigInteger::set_to_0() |
356 | 28.2k | { |
357 | 28.2k | m_words.clear_with_capacity(); |
358 | 28.2k | m_is_invalid = false; |
359 | 28.2k | m_cached_trimmed_length = {}; |
360 | 28.2k | m_cached_hash = 0; |
361 | 28.2k | } |
362 | | |
363 | | void UnsignedBigInteger::set_to(UnsignedBigInteger::Word other) |
364 | 0 | { |
365 | 0 | m_is_invalid = false; |
366 | 0 | m_words.resize_and_keep_capacity(1); |
367 | 0 | m_words[0] = other; |
368 | 0 | m_cached_trimmed_length = {}; |
369 | 0 | m_cached_hash = 0; |
370 | 0 | } |
371 | | |
372 | | void UnsignedBigInteger::set_to(UnsignedBigInteger const& other) |
373 | 24.7k | { |
374 | 24.7k | m_is_invalid = other.m_is_invalid; |
375 | 24.7k | m_words.resize_and_keep_capacity(other.m_words.size()); |
376 | 24.7k | __builtin_memcpy(m_words.data(), other.m_words.data(), other.m_words.size() * sizeof(u32)); |
377 | 24.7k | m_cached_trimmed_length = {}; |
378 | 24.7k | m_cached_hash = 0; |
379 | 24.7k | } |
380 | | |
381 | | bool UnsignedBigInteger::is_zero() const |
382 | 40 | { |
383 | 40 | for (size_t i = 0; i < length(); ++i) { |
384 | 40 | if (m_words[i] != 0) |
385 | 40 | return false; |
386 | 40 | } |
387 | | |
388 | 0 | return true; |
389 | 40 | } |
390 | | |
391 | | size_t UnsignedBigInteger::trimmed_length() const |
392 | 38.3k | { |
393 | 38.3k | if (!m_cached_trimmed_length.has_value()) { |
394 | 34.3k | size_t num_leading_zeroes = 0; |
395 | 39.1k | for (int i = length() - 1; i >= 0; --i, ++num_leading_zeroes) { |
396 | 34.7k | if (m_words[i] != 0) |
397 | 30.0k | break; |
398 | 34.7k | } |
399 | 34.3k | m_cached_trimmed_length = length() - num_leading_zeroes; |
400 | 34.3k | } |
401 | 38.3k | return m_cached_trimmed_length.value(); |
402 | 38.3k | } |
403 | | |
404 | | void UnsignedBigInteger::clamp_to_trimmed_length() |
405 | 0 | { |
406 | 0 | auto length = trimmed_length(); |
407 | 0 | if (m_words.size() > length) |
408 | 0 | m_words.resize(length); |
409 | 0 | } |
410 | | |
411 | | void UnsignedBigInteger::resize_with_leading_zeros(size_t new_length) |
412 | 26.4k | { |
413 | 26.4k | size_t old_length = length(); |
414 | 26.4k | if (old_length < new_length) { |
415 | 4.48k | m_words.resize_and_keep_capacity(new_length); |
416 | 4.48k | __builtin_memset(&m_words.data()[old_length], 0, (new_length - old_length) * sizeof(u32)); |
417 | 4.48k | } |
418 | 26.4k | } |
419 | | |
420 | | size_t UnsignedBigInteger::one_based_index_of_highest_set_bit() const |
421 | 0 | { |
422 | 0 | size_t number_of_words = trimmed_length(); |
423 | 0 | size_t index = 0; |
424 | 0 | if (number_of_words > 0) { |
425 | 0 | index += (number_of_words - 1) * BITS_IN_WORD; |
426 | 0 | index += BITS_IN_WORD - count_leading_zeroes(m_words[number_of_words - 1]); |
427 | 0 | } |
428 | 0 | return index; |
429 | 0 | } |
430 | | |
431 | | FLATTEN UnsignedBigInteger UnsignedBigInteger::plus(UnsignedBigInteger const& other) const |
432 | 1.76k | { |
433 | 1.76k | UnsignedBigInteger result; |
434 | | |
435 | 1.76k | UnsignedBigIntegerAlgorithms::add_without_allocation(*this, other, result); |
436 | | |
437 | 1.76k | return result; |
438 | 1.76k | } |
439 | | |
440 | | FLATTEN UnsignedBigInteger UnsignedBigInteger::minus(UnsignedBigInteger const& other) const |
441 | 0 | { |
442 | 0 | UnsignedBigInteger result; |
443 | |
|
444 | 0 | UnsignedBigIntegerAlgorithms::subtract_without_allocation(*this, other, result); |
445 | |
|
446 | 0 | return result; |
447 | 0 | } |
448 | | |
449 | | FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_or(UnsignedBigInteger const& other) const |
450 | 0 | { |
451 | 0 | UnsignedBigInteger result; |
452 | |
|
453 | 0 | UnsignedBigIntegerAlgorithms::bitwise_or_without_allocation(*this, other, result); |
454 | |
|
455 | 0 | return result; |
456 | 0 | } |
457 | | |
458 | | FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_and(UnsignedBigInteger const& other) const |
459 | 0 | { |
460 | 0 | UnsignedBigInteger result; |
461 | |
|
462 | 0 | UnsignedBigIntegerAlgorithms::bitwise_and_without_allocation(*this, other, result); |
463 | |
|
464 | 0 | return result; |
465 | 0 | } |
466 | | |
467 | | FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_xor(UnsignedBigInteger const& other) const |
468 | 0 | { |
469 | 0 | UnsignedBigInteger result; |
470 | |
|
471 | 0 | UnsignedBigIntegerAlgorithms::bitwise_xor_without_allocation(*this, other, result); |
472 | |
|
473 | 0 | return result; |
474 | 0 | } |
475 | | |
476 | | FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_not_fill_to_one_based_index(size_t size) const |
477 | 0 | { |
478 | 0 | UnsignedBigInteger result; |
479 | |
|
480 | 0 | UnsignedBigIntegerAlgorithms::bitwise_not_fill_to_one_based_index_without_allocation(*this, size, result); |
481 | |
|
482 | 0 | return result; |
483 | 0 | } |
484 | | |
485 | | FLATTEN UnsignedBigInteger UnsignedBigInteger::shift_left(size_t num_bits) const |
486 | 0 | { |
487 | 0 | UnsignedBigInteger output; |
488 | 0 | UnsignedBigInteger temp_result; |
489 | 0 | UnsignedBigInteger temp_plus; |
490 | |
|
491 | 0 | UnsignedBigIntegerAlgorithms::shift_left_without_allocation(*this, num_bits, temp_result, temp_plus, output); |
492 | |
|
493 | 0 | return output; |
494 | 0 | } |
495 | | |
496 | | FLATTEN UnsignedBigInteger UnsignedBigInteger::shift_right(size_t num_bits) const |
497 | 0 | { |
498 | 0 | UnsignedBigInteger output; |
499 | |
|
500 | 0 | UnsignedBigIntegerAlgorithms::shift_right_without_allocation(*this, num_bits, output); |
501 | |
|
502 | 0 | return output; |
503 | 0 | } |
504 | | |
505 | | FLATTEN UnsignedBigInteger UnsignedBigInteger::multiplied_by(UnsignedBigInteger const& other) const |
506 | 1.76k | { |
507 | 1.76k | UnsignedBigInteger result; |
508 | 1.76k | UnsignedBigInteger temp_shift_result; |
509 | 1.76k | UnsignedBigInteger temp_shift_plus; |
510 | 1.76k | UnsignedBigInteger temp_shift; |
511 | | |
512 | 1.76k | UnsignedBigIntegerAlgorithms::multiply_without_allocation(*this, other, temp_shift_result, temp_shift_plus, temp_shift, result); |
513 | | |
514 | 1.76k | return result; |
515 | 1.76k | } |
516 | | |
517 | | FLATTEN UnsignedDivisionResult UnsignedBigInteger::divided_by(UnsignedBigInteger const& divisor) const |
518 | 0 | { |
519 | 0 | UnsignedBigInteger quotient; |
520 | 0 | UnsignedBigInteger remainder; |
521 | | |
522 | | // If we actually have a u16-compatible divisor, short-circuit to the |
523 | | // less computationally-intensive "divide_u16_without_allocation" method. |
524 | 0 | if (divisor.trimmed_length() == 1 && divisor.m_words[0] < (1 << 16)) { |
525 | 0 | UnsignedBigIntegerAlgorithms::divide_u16_without_allocation(*this, divisor.m_words[0], quotient, remainder); |
526 | 0 | return UnsignedDivisionResult { quotient, remainder }; |
527 | 0 | } |
528 | | |
529 | 0 | UnsignedBigInteger temp_shift_result; |
530 | 0 | UnsignedBigInteger temp_shift_plus; |
531 | 0 | UnsignedBigInteger temp_shift; |
532 | 0 | UnsignedBigInteger temp_minus; |
533 | |
|
534 | 0 | UnsignedBigIntegerAlgorithms::divide_without_allocation(*this, divisor, quotient, remainder); |
535 | |
|
536 | 0 | return UnsignedDivisionResult { quotient, remainder }; |
537 | 0 | } |
538 | | |
539 | | u32 UnsignedBigInteger::hash() const |
540 | 0 | { |
541 | 0 | if (m_cached_hash != 0) |
542 | 0 | return m_cached_hash; |
543 | | |
544 | 0 | return m_cached_hash = string_hash((char const*)m_words.data(), sizeof(Word) * m_words.size()); |
545 | 0 | } |
546 | | |
547 | | void UnsignedBigInteger::set_bit_inplace(size_t bit_index) |
548 | 0 | { |
549 | 0 | size_t const word_index = bit_index / UnsignedBigInteger::BITS_IN_WORD; |
550 | 0 | size_t const inner_word_index = bit_index % UnsignedBigInteger::BITS_IN_WORD; |
551 | |
|
552 | 0 | m_words.ensure_capacity(word_index + 1); |
553 | |
|
554 | 0 | for (size_t i = length(); i <= word_index; ++i) { |
555 | 0 | m_words.unchecked_append(0); |
556 | 0 | } |
557 | 0 | m_words[word_index] |= (1 << inner_word_index); |
558 | |
|
559 | 0 | m_cached_trimmed_length = {}; |
560 | 0 | m_cached_hash = 0; |
561 | 0 | } |
562 | | |
563 | | bool UnsignedBigInteger::operator==(UnsignedBigInteger const& other) const |
564 | 3.98k | { |
565 | 3.98k | if (is_invalid() != other.is_invalid()) |
566 | 0 | return false; |
567 | | |
568 | 3.98k | auto length = trimmed_length(); |
569 | | |
570 | 3.98k | if (length != other.trimmed_length()) |
571 | 1.83k | return false; |
572 | | |
573 | 2.15k | return !__builtin_memcmp(m_words.data(), other.words().data(), length * (BITS_IN_WORD / 8)); |
574 | 3.98k | } |
575 | | |
576 | | bool UnsignedBigInteger::operator!=(UnsignedBigInteger const& other) const |
577 | 1.42k | { |
578 | 1.42k | return !(*this == other); |
579 | 1.42k | } |
580 | | |
581 | | bool UnsignedBigInteger::operator<(UnsignedBigInteger const& other) const |
582 | 1.36k | { |
583 | 1.36k | auto length = trimmed_length(); |
584 | 1.36k | auto other_length = other.trimmed_length(); |
585 | | |
586 | 1.36k | if (length < other_length) { |
587 | 467 | return true; |
588 | 467 | } |
589 | | |
590 | 899 | if (length > other_length) { |
591 | 34 | return false; |
592 | 34 | } |
593 | | |
594 | 865 | if (length == 0) { |
595 | 0 | return false; |
596 | 0 | } |
597 | 865 | for (int i = length - 1; i >= 0; --i) { |
598 | 865 | if (m_words[i] == other.m_words[i]) |
599 | 0 | continue; |
600 | 865 | return m_words[i] < other.m_words[i]; |
601 | 865 | } |
602 | 0 | return false; |
603 | 865 | } |
604 | | |
605 | | bool UnsignedBigInteger::operator>(UnsignedBigInteger const& other) const |
606 | 1.42k | { |
607 | 1.42k | return *this != other && !(*this < other); |
608 | 1.42k | } |
609 | | |
610 | | bool UnsignedBigInteger::operator>=(UnsignedBigInteger const& other) const |
611 | 0 | { |
612 | 0 | return *this > other || *this == other; |
613 | 0 | } |
614 | | |
615 | | UnsignedBigInteger::CompareResult UnsignedBigInteger::compare_to_double(double value) const |
616 | 0 | { |
617 | 0 | VERIFY(!isnan(value)); |
618 | | |
619 | 0 | if (isinf(value)) { |
620 | 0 | bool is_positive_infinity = __builtin_isinf_sign(value) > 0; |
621 | 0 | return is_positive_infinity ? CompareResult::DoubleGreaterThanBigInt : CompareResult::DoubleLessThanBigInt; |
622 | 0 | } |
623 | | |
624 | 0 | bool value_is_negative = value < 0; |
625 | |
|
626 | 0 | if (value_is_negative) |
627 | 0 | return CompareResult::DoubleLessThanBigInt; |
628 | | |
629 | | // Value is zero. |
630 | 0 | if (value == 0.0) { |
631 | 0 | VERIFY(!value_is_negative); |
632 | | // Either we are also zero or value is certainly less than us. |
633 | 0 | return is_zero() ? CompareResult::DoubleEqualsBigInt : CompareResult::DoubleLessThanBigInt; |
634 | 0 | } |
635 | | |
636 | | // If value is not zero but we are, value must be greater. |
637 | 0 | if (is_zero()) |
638 | 0 | return CompareResult::DoubleGreaterThanBigInt; |
639 | | |
640 | 0 | auto extractor = FloatExtractor<double>::from_float(value); |
641 | | |
642 | | // Value cannot be negative at this point. |
643 | 0 | VERIFY(extractor.sign == 0); |
644 | | // Exponent cannot be all set, as then we must be NaN or infinity. |
645 | 0 | VERIFY(extractor.exponent != (1 << extractor.exponent_bits) - 1); |
646 | | |
647 | 0 | i32 real_exponent = extractor.exponent - extractor.exponent_bias; |
648 | 0 | if (real_exponent < 0) { |
649 | | // value is less than 1, and we cannot be zero so value must be less. |
650 | 0 | return CompareResult::DoubleLessThanBigInt; |
651 | 0 | } |
652 | | |
653 | 0 | u64 bigint_bits_needed = one_based_index_of_highest_set_bit(); |
654 | 0 | VERIFY(bigint_bits_needed > 0); |
655 | | |
656 | | // Double value is `-1^sign (1.mantissa) * 2^(exponent - bias)` so we need |
657 | | // `exponent - bias + 1` bit to represent doubles value, |
658 | | // for example `exponent - bias` = 3, sign = 0 and mantissa = 0 we get |
659 | | // `-1^0 * 2^3 * 1 = 8` which needs 4 bits to store 8 (0b1000). |
660 | 0 | u32 double_bits_needed = real_exponent + 1; |
661 | | |
662 | | // If we need more bits to represent us, we must be of greater value. |
663 | 0 | if (bigint_bits_needed > double_bits_needed) |
664 | 0 | return CompareResult::DoubleLessThanBigInt; |
665 | | // If we need less bits to represent us, we must be of less value. |
666 | 0 | if (bigint_bits_needed < double_bits_needed) |
667 | 0 | return CompareResult::DoubleGreaterThanBigInt; |
668 | | |
669 | 0 | u64 mantissa_bits = extractor.mantissa; |
670 | | |
671 | | // We add the bit which represents the 1. of the double value calculation. |
672 | 0 | constexpr u64 mantissa_extended_bit = 1ull << extractor.mantissa_bits; |
673 | |
|
674 | 0 | mantissa_bits |= mantissa_extended_bit; |
675 | | |
676 | | // Now we shift value to the left virtually, with `exponent - bias` steps |
677 | | // we then pretend both it and the big int are extended with virtual zeros. |
678 | 0 | auto next_bigint_word = (BITS_IN_WORD - 1 + bigint_bits_needed) / BITS_IN_WORD; |
679 | |
|
680 | 0 | VERIFY(next_bigint_word == trimmed_length()); |
681 | | |
682 | 0 | auto msb_in_top_word_index = (bigint_bits_needed - 1) % BITS_IN_WORD; |
683 | 0 | VERIFY(msb_in_top_word_index == (BITS_IN_WORD - count_leading_zeroes(words()[next_bigint_word - 1]) - 1)); |
684 | | |
685 | | // We will keep the bits which are still valid in the mantissa at the top of mantissa bits. |
686 | 0 | mantissa_bits <<= 64 - (extractor.mantissa_bits + 1); |
687 | |
|
688 | 0 | auto bits_left_in_mantissa = static_cast<size_t>(extractor.mantissa_bits) + 1; |
689 | |
|
690 | 0 | auto get_next_value_bits = [&](size_t num_bits) -> Word { |
691 | 0 | VERIFY(num_bits < 63); |
692 | 0 | VERIFY(bits_left_in_mantissa > 0); |
693 | 0 | if (num_bits > bits_left_in_mantissa) |
694 | 0 | num_bits = bits_left_in_mantissa; |
695 | |
|
696 | 0 | bits_left_in_mantissa -= num_bits; |
697 | |
|
698 | 0 | u64 extracted_bits = mantissa_bits & (((1ull << num_bits) - 1) << (64 - num_bits)); |
699 | | // Now shift the bits down to put the most significant bit on the num_bits position |
700 | | // this means the rest will be "virtual" zeros. |
701 | 0 | extracted_bits >>= 32; |
702 | | |
703 | | // Now shift away the used bits and fit the result into a Word. |
704 | 0 | mantissa_bits <<= num_bits; |
705 | |
|
706 | 0 | VERIFY(extracted_bits <= NumericLimits<Word>::max()); |
707 | 0 | return static_cast<Word>(extracted_bits); |
708 | 0 | }; |
709 | |
|
710 | 0 | auto bits_in_next_bigint_word = msb_in_top_word_index + 1; |
711 | |
|
712 | 0 | while (next_bigint_word > 0 && bits_left_in_mantissa > 0) { |
713 | 0 | Word bigint_word = words()[next_bigint_word - 1]; |
714 | 0 | Word double_word = get_next_value_bits(bits_in_next_bigint_word); |
715 | | |
716 | | // For the first bit we have to align it with the top bit of bigint |
717 | | // and for all the other cases bits_in_next_bigint_word is 32 so this does nothing. |
718 | 0 | double_word >>= 32 - bits_in_next_bigint_word; |
719 | |
|
720 | 0 | if (bigint_word < double_word) |
721 | 0 | return CompareResult::DoubleGreaterThanBigInt; |
722 | | |
723 | 0 | if (bigint_word > double_word) |
724 | 0 | return CompareResult::DoubleLessThanBigInt; |
725 | | |
726 | 0 | --next_bigint_word; |
727 | 0 | bits_in_next_bigint_word = BITS_IN_WORD; |
728 | 0 | } |
729 | | |
730 | | // If there are still bits left in bigint than any non zero bit means it has greater value. |
731 | 0 | if (next_bigint_word > 0) { |
732 | 0 | VERIFY(bits_left_in_mantissa == 0); |
733 | 0 | while (next_bigint_word > 0) { |
734 | 0 | if (words()[next_bigint_word - 1] != 0) |
735 | 0 | return CompareResult::DoubleLessThanBigInt; |
736 | 0 | --next_bigint_word; |
737 | 0 | } |
738 | 0 | } else if (bits_left_in_mantissa > 0) { |
739 | 0 | VERIFY(next_bigint_word == 0); |
740 | | // Similarly if there are still any bits set in the mantissa it has greater value. |
741 | 0 | if (mantissa_bits != 0) |
742 | 0 | return CompareResult::DoubleGreaterThanBigInt; |
743 | 0 | } |
744 | | |
745 | | // Otherwise if both don't have bits left or the rest of the bits are zero they are equal. |
746 | 0 | return CompareResult::DoubleEqualsBigInt; |
747 | 0 | } |
748 | | |
749 | | } |
750 | | |
751 | | ErrorOr<void> AK::Formatter<Crypto::UnsignedBigInteger>::format(FormatBuilder& fmtbuilder, Crypto::UnsignedBigInteger const& value) |
752 | 0 | { |
753 | 0 | if (value.is_invalid()) |
754 | 0 | return fmtbuilder.put_string("invalid"sv); |
755 | | |
756 | 0 | StringBuilder builder; |
757 | 0 | for (int i = value.length() - 1; i >= 0; --i) |
758 | 0 | TRY(builder.try_appendff("{}|", value.words()[i])); |
759 | |
|
760 | 0 | return Formatter<StringView>::format(fmtbuilder, builder.string_view()); |
761 | 0 | } |