summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorDan Klishch <danilklishch@gmail.com>2022-10-28 12:02:03 -0400
committerAndrew Kaster <andrewdkaster@gmail.com>2022-11-03 20:17:09 -0600
commit17c9a3e8d951420bd85f7445c829bc6fbde4ade2 (patch)
tree7aa8e32fa84009b03b000d9b2529468f52fa5e2e /Userland
parent2d75229192f780fa4df845add4dcee37f6caa0ce (diff)
downloadserenity-17c9a3e8d951420bd85f7445c829bc6fbde4ade2.zip
AK+LibC+LibCrypto: Move FloatExtractor to AK/FloatingPoint.h
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibC/math.cpp52
-rw-r--r--Userland/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp75
2 files changed, 28 insertions, 99 deletions
diff --git a/Userland/Libraries/LibC/math.cpp b/Userland/Libraries/LibC/math.cpp
index db83bc508c..520a27cc16 100644
--- a/Userland/Libraries/LibC/math.cpp
+++ b/Userland/Libraries/LibC/math.cpp
@@ -9,6 +9,7 @@
#include <AK/BuiltinWrappers.h>
#include <AK/ExtraMathConstants.h>
+#include <AK/FloatingPoint.h>
#ifndef AK_ARCH_AARCH64
# include <AK/FPControl.h>
#endif
@@ -61,57 +62,6 @@ enum class RoundingMode {
ToEven = FE_TONEAREST
};
-template<typename T>
-union FloatExtractor;
-
-#if ARCH(I386) || ARCH(X86_64) || ARCH(AARCH64)
-// This assumes long double is 80 bits, which is true with GCC on Intel platforms
-template<>
-union FloatExtractor<long double> {
- static constexpr int mantissa_bits = 64;
- static constexpr unsigned long long mantissa_max = ~0u;
- static constexpr int exponent_bias = 16383;
- static constexpr int exponent_bits = 15;
- static constexpr unsigned exponent_max = 32767;
- struct {
- unsigned long long mantissa;
- unsigned exponent : 15;
- unsigned sign : 1;
- };
- long double d;
-};
-#endif
-
-template<>
-union FloatExtractor<double> {
- static constexpr int mantissa_bits = 52;
- static constexpr unsigned long long mantissa_max = (1ull << 52) - 1;
- static constexpr int exponent_bias = 1023;
- static constexpr int exponent_bits = 11;
- static constexpr unsigned exponent_max = 2047;
- struct {
- unsigned long long mantissa : 52;
- unsigned exponent : 11;
- unsigned sign : 1;
- };
- double d;
-};
-
-template<>
-union FloatExtractor<float> {
- static constexpr int mantissa_bits = 23;
- static constexpr unsigned mantissa_max = (1 << 23) - 1;
- static constexpr int exponent_bias = 127;
- static constexpr int exponent_bits = 8;
- static constexpr unsigned exponent_max = 255;
- struct {
- unsigned long long mantissa : 23;
- unsigned exponent : 8;
- unsigned sign : 1;
- };
- float d;
-};
-
// This is much branchier than it really needs to be
template<typename FloatType>
static FloatType internal_to_integer(FloatType x, RoundingMode rounding_mode)
diff --git a/Userland/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp b/Userland/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp
index 6c8e7a4e69..88f311cbf1 100644
--- a/Userland/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp
+++ b/Userland/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp
@@ -8,6 +8,7 @@
#include "UnsignedBigInteger.h"
#include <AK/BuiltinWrappers.h>
#include <AK/CharacterTypes.h>
+#include <AK/FloatingPoint.h>
#include <AK/StringBuilder.h>
#include <AK/StringHash.h>
#include <LibCrypto/BigInt/Algorithms/UnsignedBigIntegerAlgorithms.h>
@@ -34,19 +35,6 @@ UnsignedBigInteger::UnsignedBigInteger(u8 const* ptr, size_t length)
}
}
-static constexpr u64 mantissa_size = 52;
-static constexpr u64 exponent_size = 11;
-static constexpr auto exponent_bias = (1 << (exponent_size - 1)) - 1;
-
-union DoubleExtractor {
- struct {
- unsigned long long mantissa : mantissa_size;
- unsigned exponent : exponent_size;
- unsigned sign : 1;
- };
- double double_value = 0;
-};
-
UnsignedBigInteger::UnsignedBigInteger(double value)
{
// Because this is currently only used for LibJS we VERIFY some preconditions
@@ -61,11 +49,11 @@ UnsignedBigInteger::UnsignedBigInteger(double value)
return;
}
- DoubleExtractor extractor;
- extractor.double_value = value;
+ FloatExtractor<double> extractor;
+ extractor.d = value;
VERIFY(!extractor.sign);
- i32 real_exponent = extractor.exponent - exponent_bias;
+ i32 real_exponent = extractor.exponent - extractor.exponent_bias;
VERIFY(real_exponent > 0);
// Ensure we have enough space, we will need 2^exponent bits, so round up in words
@@ -73,10 +61,10 @@ UnsignedBigInteger::UnsignedBigInteger(double value)
m_words.resize_and_keep_capacity(word_index);
// Now we just need to put the mantissa with explicit 1 bit at the top at the proper location
- u64 raw_mantissa = extractor.mantissa | (1ull << mantissa_size);
+ u64 raw_mantissa = extractor.mantissa | (1ull << extractor.mantissa_bits);
VERIFY((raw_mantissa & 0xfff0000000000000) == 0x0010000000000000);
// Shift it so the bits we need are at the top
- raw_mantissa <<= 64 - mantissa_size - 1;
+ raw_mantissa <<= 64 - extractor.mantissa_bits - 1;
// The initial bit needs to be exactly aligned with exponent, this is 1-indexed
auto top_word_bit_offset = real_exponent % BITS_IN_WORD + 1;
@@ -88,7 +76,7 @@ UnsignedBigInteger::UnsignedBigInteger(double value)
--word_index;
// Shift used bits away
raw_mantissa <<= top_word_bit_offset;
- i32 bits_in_mantissa = mantissa_size + 1 - top_word_bit_offset;
+ i32 bits_in_mantissa = extractor.mantissa_bits + 1 - top_word_bit_offset;
// Now just put everything at the top of the next words
constexpr auto to_word_shift = 64 - BITS_IN_WORD;
@@ -198,12 +186,14 @@ double UnsignedBigInteger::to_double(UnsignedBigInteger::RoundingMode rounding_m
return 0;
--highest_bit;
+ using Extractor = FloatExtractor<double>;
+
// Simple case if less than 2^53 since those number are all exactly representable in doubles
- if (highest_bit < mantissa_size + 1)
+ if (highest_bit < Extractor::mantissa_bits + 1)
return static_cast<double>(to_u64());
// If it uses too many bit to represent in a double return infinity
- if (highest_bit > exponent_bias)
+ if (highest_bit > Extractor::exponent_bias)
return __builtin_huge_val();
// Otherwise we have to take the top 53 bits, use those as the mantissa,
@@ -211,11 +201,11 @@ double UnsignedBigInteger::to_double(UnsignedBigInteger::RoundingMode rounding_m
// so we have to ignore the very top bit.
// Since we extract at most 53 bits it will take at most 3 words
- static_assert(BITS_IN_WORD * 3 >= (mantissa_size + 1));
+ static_assert(BITS_IN_WORD * 3 >= (Extractor::mantissa_bits + 1));
constexpr auto bits_in_u64 = 64;
- static_assert(bits_in_u64 > mantissa_size + 1);
+ static_assert(bits_in_u64 > Extractor::mantissa_bits + 1);
- auto bits_to_read = min(mantissa_size, highest_bit);
+ auto bits_to_read = min(static_cast<size_t>(Extractor::mantissa_bits), highest_bit);
auto last_word_index = trimmed_length();
VERIFY(last_word_index > 0);
@@ -267,7 +257,7 @@ double UnsignedBigInteger::to_double(UnsignedBigInteger::RoundingMode rounding_m
}
// Now the mantissa should be complete so shift it down
- mantissa >>= bits_in_u64 - mantissa_size;
+ mantissa >>= bits_in_u64 - Extractor::mantissa_bits;
if (rounding_mode == RoundingMode::IEEERoundAndTiesToEvenMantissa) {
bool round_up = false;
@@ -327,13 +317,13 @@ double UnsignedBigInteger::to_double(UnsignedBigInteger::RoundingMode rounding_m
if (round_up) {
++mantissa;
- if ((mantissa & (1ull << mantissa_size)) != 0) {
+ if ((mantissa & (1ull << Extractor::mantissa_bits)) != 0) {
// we overflowed the mantissa
mantissa = 0;
highest_bit++;
// In which case it is possible we have to round to infinity
- if (highest_bit > exponent_bias)
+ if (highest_bit > Extractor::exponent_bias)
return __builtin_huge_val();
}
}
@@ -341,14 +331,13 @@ double UnsignedBigInteger::to_double(UnsignedBigInteger::RoundingMode rounding_m
VERIFY(rounding_mode == RoundingMode::RoundTowardZero);
}
- DoubleExtractor extractor;
-
- extractor.exponent = highest_bit + exponent_bias;
+ Extractor extractor;
+ extractor.exponent = highest_bit + extractor.exponent_bias;
VERIFY((mantissa & 0xfff0000000000000) == 0);
extractor.mantissa = mantissa;
- return extractor.double_value;
+ return extractor.d;
}
void UnsignedBigInteger::set_to_0()
@@ -627,25 +616,15 @@ UnsignedBigInteger::CompareResult UnsignedBigInteger::compare_to_double(double v
if (is_zero())
return CompareResult::DoubleGreaterThanBigInt;
- constexpr u64 mantissa_size = 52;
- constexpr u64 exponent_size = 11;
- constexpr auto exponent_bias = (1 << (exponent_size - 1)) - 1;
- union FloatExtractor {
- struct {
- unsigned long long mantissa : mantissa_size;
- unsigned exponent : exponent_size;
- unsigned sign : 1;
- };
- double d;
- } extractor;
-
+ FloatExtractor<double> extractor;
extractor.d = value;
+
// Value cannot be negative at this point.
VERIFY(extractor.sign == 0);
// Exponent cannot be all set, as then we must be NaN or infinity.
- VERIFY(extractor.exponent != (1 << exponent_size) - 1);
+ VERIFY(extractor.exponent != (1 << extractor.exponent_bits) - 1);
- i32 real_exponent = extractor.exponent - exponent_bias;
+ i32 real_exponent = extractor.exponent - extractor.exponent_bias;
if (real_exponent < 0) {
// value is less than 1, and we cannot be zero so value must be less.
return CompareResult::DoubleLessThanBigInt;
@@ -670,7 +649,7 @@ UnsignedBigInteger::CompareResult UnsignedBigInteger::compare_to_double(double v
u64 mantissa_bits = extractor.mantissa;
// We add the bit which represents the 1. of the double value calculation.
- constexpr u64 mantissa_extended_bit = 1ull << mantissa_size;
+ constexpr u64 mantissa_extended_bit = 1ull << extractor.mantissa_bits;
mantissa_bits |= mantissa_extended_bit;
@@ -684,9 +663,9 @@ UnsignedBigInteger::CompareResult UnsignedBigInteger::compare_to_double(double v
VERIFY(msb_in_top_word_index == (BITS_IN_WORD - count_leading_zeroes(words()[next_bigint_word - 1]) - 1));
// We will keep the bits which are still valid in the mantissa at the top of mantissa bits.
- mantissa_bits <<= 64 - (mantissa_size + 1);
+ mantissa_bits <<= 64 - (extractor.mantissa_bits + 1);
- auto bits_left_in_mantissa = mantissa_size + 1;
+ auto bits_left_in_mantissa = static_cast<size_t>(extractor.mantissa_bits) + 1;
auto get_next_value_bits = [&](size_t num_bits) -> Word {
VERIFY(num_bits < 63);