16 changes: 8 additions & 8 deletions libc/src/__support/FPUtil/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,21 @@ namespace fputil {

// All dummy functions silently succeed.

static inline int clearExcept(int) { return 0; }
static inline int clear_except(int) { return 0; }

static inline int testExcept(int) { return 0; }
static inline int test_except(int) { return 0; }

static inline int setExcept(int) { return 0; }
static inline int set_except(int) { return 0; }

static inline int raiseExcept(int) { return 0; }
static inline int raise_except(int) { return 0; }

static inline int getRound() { return FE_TONEAREST; }
static inline int get_round() { return FE_TONEAREST; }

static inline int setRound(int) { return 0; }
static inline int set_round(int) { return 0; }

static inline int getEnv(fenv_t *) { return 0; }
static inline int get_env(fenv_t *) { return 0; }

static inline int setEnv(const fenv_t *) { return 0; }
static inline int set_env(const fenv_t *) { return 0; }

} // namespace fputil
} // namespace __llvm_libc
Expand Down
82 changes: 42 additions & 40 deletions libc/src/__support/FPUtil/FPBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ namespace __llvm_libc {
namespace fputil {

template <typename T> struct MantissaWidth {
static constexpr unsigned value = FloatProperties<T>::mantissaWidth;
static constexpr unsigned VALUE = FloatProperties<T>::MANTISSA_WIDTH;
};

template <typename T> struct ExponentWidth {
static constexpr unsigned value = FloatProperties<T>::exponentWidth;
static constexpr unsigned VALUE = FloatProperties<T>::EXPONENT_WIDTH;
};

// A generic class to represent single precision, double precision, and quad
Expand All @@ -48,49 +48,49 @@ template <typename T> union FPBits {

UIntType bits;

void setMantissa(UIntType mantVal) {
mantVal &= (FloatProp::mantissaMask);
bits &= ~(FloatProp::mantissaMask);
void set_mantissa(UIntType mantVal) {
mantVal &= (FloatProp::MANTISSA_MASK);
bits &= ~(FloatProp::MANTISSA_MASK);
bits |= mantVal;
}

UIntType getMantissa() const { return bits & FloatProp::mantissaMask; }
UIntType get_mantissa() const { return bits & FloatProp::MANTISSA_MASK; }

void setUnbiasedExponent(UIntType expVal) {
expVal = (expVal << (FloatProp::mantissaWidth)) & FloatProp::exponentMask;
bits &= ~(FloatProp::exponentMask);
void set_unbiased_exponent(UIntType expVal) {
expVal = (expVal << (FloatProp::MANTISSA_WIDTH)) & FloatProp::EXPONENT_MASK;
bits &= ~(FloatProp::EXPONENT_MASK);
bits |= expVal;
}

uint16_t getUnbiasedExponent() const {
return uint16_t((bits & FloatProp::exponentMask) >>
(FloatProp::mantissaWidth));
uint16_t get_unbiased_exponent() const {
return uint16_t((bits & FloatProp::EXPONENT_MASK) >>
(FloatProp::MANTISSA_WIDTH));
}

void setSign(bool signVal) {
bits &= ~(FloatProp::signMask);
UIntType sign = UIntType(signVal) << (FloatProp::bitWidth - 1);
void set_sign(bool signVal) {
bits &= ~(FloatProp::SIGN_MASK);
UIntType sign = UIntType(signVal) << (FloatProp::BIT_WIDTH - 1);
bits |= sign;
}

bool getSign() const {
return ((bits & FloatProp::signMask) >> (FloatProp::bitWidth - 1));
bool get_sign() const {
return ((bits & FloatProp::SIGN_MASK) >> (FloatProp::BIT_WIDTH - 1));
}
T val;

static_assert(sizeof(T) == sizeof(UIntType),
"Data type and integral representation have different sizes.");

static constexpr int exponentBias = (1 << (ExponentWidth<T>::value - 1)) - 1;
static constexpr int maxExponent = (1 << ExponentWidth<T>::value) - 1;
static constexpr int EXPONENT_BIAS = (1 << (ExponentWidth<T>::VALUE - 1)) - 1;
static constexpr int MAX_EXPONENT = (1 << ExponentWidth<T>::VALUE) - 1;

static constexpr UIntType minSubnormal = UIntType(1);
static constexpr UIntType maxSubnormal =
(UIntType(1) << MantissaWidth<T>::value) - 1;
static constexpr UIntType minNormal =
(UIntType(1) << MantissaWidth<T>::value);
static constexpr UIntType maxNormal =
((UIntType(maxExponent) - 1) << MantissaWidth<T>::value) | maxSubnormal;
static constexpr UIntType MIN_SUBNORMAL = UIntType(1);
static constexpr UIntType MAX_SUBNORMAL =
(UIntType(1) << MantissaWidth<T>::VALUE) - 1;
static constexpr UIntType MIN_NORMAL =
(UIntType(1) << MantissaWidth<T>::VALUE);
static constexpr UIntType MAX_NORMAL =
((UIntType(MAX_EXPONENT) - 1) << MantissaWidth<T>::VALUE) | MAX_SUBNORMAL;

// We don't want accidental type promotions/conversions so we require exact
// type match.
Expand All @@ -108,43 +108,45 @@ template <typename T> union FPBits {

UIntType uintval() const { return bits; }

int getExponent() const { return int(getUnbiasedExponent()) - exponentBias; }
int get_exponent() const {
return int(get_unbiased_exponent()) - EXPONENT_BIAS;
}

bool isZero() const {
return getMantissa() == 0 && getUnbiasedExponent() == 0;
bool is_zero() const {
return get_mantissa() == 0 && get_unbiased_exponent() == 0;
}

bool isInf() const {
return getMantissa() == 0 && getUnbiasedExponent() == maxExponent;
bool is_inf() const {
return get_mantissa() == 0 && get_unbiased_exponent() == MAX_EXPONENT;
}

bool isNaN() const {
return getUnbiasedExponent() == maxExponent && getMantissa() != 0;
bool is_nan() const {
return get_unbiased_exponent() == MAX_EXPONENT && get_mantissa() != 0;
}

bool isInfOrNaN() const { return getUnbiasedExponent() == maxExponent; }
bool is_inf_or_nan() const { return get_unbiased_exponent() == MAX_EXPONENT; }

static FPBits<T> zero() { return FPBits(); }

static FPBits<T> negZero() {
static FPBits<T> neg_zero() {
return FPBits(UIntType(1) << (sizeof(UIntType) * 8 - 1));
}

static FPBits<T> inf() {
FPBits<T> bits;
bits.setUnbiasedExponent(maxExponent);
bits.set_unbiased_exponent(MAX_EXPONENT);
return bits;
}

static FPBits<T> negInf() {
static FPBits<T> neg_inf() {
FPBits<T> bits = inf();
bits.setSign(1);
bits.set_sign(1);
return bits;
}

static T buildNaN(UIntType v) {
static T build_nan(UIntType v) {
FPBits<T> bits = inf();
bits.setMantissa(v);
bits.set_mantissa(v);
return T(bits);
}
};
Expand Down
104 changes: 53 additions & 51 deletions libc/src/__support/FPUtil/FloatProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,41 +22,41 @@ template <> struct FloatProperties<float> {
static_assert(sizeof(BitsType) == sizeof(float),
"Unexpected size of 'float' type.");

static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;

static constexpr uint32_t mantissaWidth = 23;
static constexpr uint32_t exponentWidth = 8;
static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1;
static constexpr BitsType signMask = BitsType(1)
<< (exponentWidth + mantissaWidth);
static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentBias = 127;
static constexpr uint32_t MANTISSA_WIDTH = 23;
static constexpr uint32_t EXPONENT_WIDTH = 8;
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
static constexpr BitsType SIGN_MASK = BitsType(1)
<< (EXPONENT_WIDTH + MANTISSA_WIDTH);
static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
static constexpr uint32_t EXPONENT_BIAS = 127;

// If a number x is a NAN, then it is a quiet NAN if:
// QuietNaNMask & bits(x) != 0
// Else, it is a signalling NAN.
static constexpr BitsType quietNaNMask = 0x00400000U;
static constexpr BitsType QUIET_NAN_MASK = 0x00400000U;
};

template <> struct FloatProperties<double> {
typedef uint64_t BitsType;
static_assert(sizeof(BitsType) == sizeof(double),
"Unexpected size of 'double' type.");

static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;

static constexpr uint32_t mantissaWidth = 52;
static constexpr uint32_t exponentWidth = 11;
static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1;
static constexpr BitsType signMask = BitsType(1)
<< (exponentWidth + mantissaWidth);
static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentBias = 1023;
static constexpr uint32_t MANTISSA_WIDTH = 52;
static constexpr uint32_t EXPONENT_WIDTH = 11;
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
static constexpr BitsType SIGN_MASK = BitsType(1)
<< (EXPONENT_WIDTH + MANTISSA_WIDTH);
static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
static constexpr uint32_t EXPONENT_BIAS = 1023;

// If a number x is a NAN, then it is a quiet NAN if:
// QuietNaNMask & bits(x) != 0
// Else, it is a signalling NAN.
static constexpr BitsType quietNaNMask = 0x0008000000000000ULL;
static constexpr BitsType QUIET_NAN_MASK = 0x0008000000000000ULL;
};

#if defined(LONG_DOUBLE_IS_DOUBLE)
Expand All @@ -67,25 +67,25 @@ template <> struct FloatProperties<long double> {
static_assert(sizeof(BitsType) == sizeof(double),
"Unexpected size of 'double' type.");

static constexpr uint32_t bitWidth = FloatProperties<double>::bitWidth;
static constexpr uint32_t BIT_WIDTH = FloatProperties<double>::BIT_WIDTH;

static constexpr uint32_t mantissaWidth =
FloatProperties<double>::mantissaWidth;
static constexpr uint32_t exponentWidth =
FloatProperties<double>::exponentWidth;
static constexpr BitsType mantissaMask =
FloatProperties<double>::mantissaMask;
static constexpr BitsType signMask = FloatProperties<double>::signMask;
static constexpr BitsType exponentMask =
FloatProperties<double>::exponentMask;
static constexpr uint32_t exponentBias =
FloatProperties<double>::exponentBias;
static constexpr uint32_t MANTISSA_WIDTH =
FloatProperties<double>::MANTISSA_WIDTH;
static constexpr uint32_t EXPONENT_WIDTH =
FloatProperties<double>::EXPONENT_WIDTH;
static constexpr BitsType MANTISSA_MASK =
FloatProperties<double>::MANTISSA_MASK;
static constexpr BitsType SIGN_MASK = FloatProperties<double>::SIGN_MASK;
static constexpr BitsType EXPONENT_MASK =
FloatProperties<double>::EXPONENT_MASK;
static constexpr uint32_t EXPONENT_BIAS =
FloatProperties<double>::EXPONENT_BIAS;

// If a number x is a NAN, then it is a quiet NAN if:
// QuietNaNMask & bits(x) != 0
// Else, it is a signalling NAN.
static constexpr BitsType quietNaNMask =
FloatProperties<double>::quietNaNMask;
static constexpr BitsType QUIET_NAN_MASK =
FloatProperties<double>::QUIET_NAN_MASK;
};
#elif defined(SPECIAL_X86_LONG_DOUBLE)
// Properties for numbers represented in 80 bits long double on non-Windows x86
Expand All @@ -95,21 +95,22 @@ template <> struct FloatProperties<long double> {
static_assert(sizeof(BitsType) == sizeof(long double),
"Unexpected size of 'long double' type.");

static constexpr uint32_t bitWidth = (sizeof(BitsType) << 3) - 48;
static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) << 3) - 48;

static constexpr uint32_t mantissaWidth = 63;
static constexpr uint32_t exponentWidth = 15;
static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1;
static constexpr BitsType signMask = BitsType(1)
<< (exponentWidth + mantissaWidth + 1);
static constexpr BitsType exponentMask = ((BitsType(1) << exponentWidth) - 1)
<< (mantissaWidth + 1);
static constexpr uint32_t exponentBias = 16383;
static constexpr uint32_t MANTISSA_WIDTH = 63;
static constexpr uint32_t EXPONENT_WIDTH = 15;
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
static constexpr BitsType SIGN_MASK =
BitsType(1) << (EXPONENT_WIDTH + MANTISSA_WIDTH + 1);
static constexpr BitsType EXPONENT_MASK =
((BitsType(1) << EXPONENT_WIDTH) - 1) << (MANTISSA_WIDTH + 1);
static constexpr uint32_t EXPONENT_BIAS = 16383;

// If a number x is a NAN, then it is a quiet NAN if:
// QuietNaNMask & bits(x) != 0
// Else, it is a signalling NAN.
static constexpr BitsType quietNaNMask = BitsType(1) << (mantissaWidth - 1);
static constexpr BitsType QUIET_NAN_MASK = BitsType(1)
<< (MANTISSA_WIDTH - 1);
};
#else
// Properties for numbers represented in 128 bits long double on non x86
Expand All @@ -119,20 +120,21 @@ template <> struct FloatProperties<long double> {
static_assert(sizeof(BitsType) == sizeof(long double),
"Unexpected size of 'long double' type.");

static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;

static constexpr uint32_t mantissaWidth = 112;
static constexpr uint32_t exponentWidth = 15;
static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1;
static constexpr BitsType signMask = BitsType(1)
<< (exponentWidth + mantissaWidth);
static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentBias = 16383;
static constexpr uint32_t MANTISSA_WIDTH = 112;
static constexpr uint32_t EXPONENT_WIDTH = 15;
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
static constexpr BitsType SIGN_MASK = BitsType(1)
<< (EXPONENT_WIDTH + MANTISSA_WIDTH);
static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
static constexpr uint32_t EXPONENT_BIAS = 16383;

// If a number x is a NAN, then it is a quiet NAN if:
// QuietNaNMask & bits(x) != 0
// Else, it is a signalling NAN.
static constexpr BitsType quietNaNMask = BitsType(1) << (mantissaWidth - 1);
static constexpr BitsType QUIET_NAN_MASK = BitsType(1)
<< (MANTISSA_WIDTH - 1);
};
#endif

Expand Down
123 changes: 62 additions & 61 deletions libc/src/__support/FPUtil/Hypot.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,35 @@ namespace fputil {

namespace internal {

template <typename T> static inline T findLeadingOne(T mant, int &shift_length);
template <typename T>
static inline T find_leading_one(T mant, int &shift_length);

template <>
inline uint32_t findLeadingOne<uint32_t>(uint32_t mant, int &shift_length) {
inline uint32_t find_leading_one<uint32_t>(uint32_t mant, int &shift_length) {
shift_length = 0;
constexpr int nsteps = 5;
constexpr uint32_t bounds[nsteps] = {1 << 16, 1 << 8, 1 << 4, 1 << 2, 1 << 1};
constexpr int shifts[nsteps] = {16, 8, 4, 2, 1};
for (int i = 0; i < nsteps; ++i) {
if (mant >= bounds[i]) {
shift_length += shifts[i];
mant >>= shifts[i];
constexpr int NSTEPS = 5;
constexpr uint32_t BOUNDS[NSTEPS] = {1 << 16, 1 << 8, 1 << 4, 1 << 2, 1 << 1};
constexpr int SHIFTS[NSTEPS] = {16, 8, 4, 2, 1};
for (int i = 0; i < NSTEPS; ++i) {
if (mant >= BOUNDS[i]) {
shift_length += SHIFTS[i];
mant >>= SHIFTS[i];
}
}
return 1U << shift_length;
}

template <>
inline uint64_t findLeadingOne<uint64_t>(uint64_t mant, int &shift_length) {
inline uint64_t find_leading_one<uint64_t>(uint64_t mant, int &shift_length) {
shift_length = 0;
constexpr int nsteps = 6;
constexpr uint64_t bounds[nsteps] = {1ULL << 32, 1ULL << 16, 1ULL << 8,
constexpr int NSTEPS = 6;
constexpr uint64_t BOUNDS[NSTEPS] = {1ULL << 32, 1ULL << 16, 1ULL << 8,
1ULL << 4, 1ULL << 2, 1ULL << 1};
constexpr int shifts[nsteps] = {32, 16, 8, 4, 2, 1};
for (int i = 0; i < nsteps; ++i) {
if (mant >= bounds[i]) {
shift_length += shifts[i];
mant >>= shifts[i];
constexpr int SHIFTS[NSTEPS] = {32, 16, 8, 4, 2, 1};
for (int i = 0; i < NSTEPS; ++i) {
if (mant >= BOUNDS[i]) {
shift_length += SHIFTS[i];
mant >>= SHIFTS[i];
}
}
return 1ULL << shift_length;
Expand Down Expand Up @@ -124,13 +125,13 @@ static inline T hypot(T x, T y) {

FPBits_t x_bits(x), y_bits(y);

if (x_bits.isInf() || y_bits.isInf()) {
if (x_bits.is_inf() || y_bits.is_inf()) {
return T(FPBits_t::inf());
}
if (x_bits.isNaN()) {
if (x_bits.is_nan()) {
return x;
}
if (y_bits.isNaN()) {
if (y_bits.is_nan()) {
return y;
}

Expand All @@ -139,50 +140,50 @@ static inline T hypot(T x, T y) {
DUIntType a_mant_sq, b_mant_sq;
bool sticky_bits;

if ((x_bits.getUnbiasedExponent() >=
y_bits.getUnbiasedExponent() + MantissaWidth<T>::value + 2) ||
if ((x_bits.get_unbiased_exponent() >=
y_bits.get_unbiased_exponent() + MantissaWidth<T>::VALUE + 2) ||
(y == 0)) {
return abs(x);
} else if ((y_bits.getUnbiasedExponent() >=
x_bits.getUnbiasedExponent() + MantissaWidth<T>::value + 2) ||
} else if ((y_bits.get_unbiased_exponent() >=
x_bits.get_unbiased_exponent() + MantissaWidth<T>::VALUE + 2) ||
(x == 0)) {
y_bits.setSign(0);
y_bits.set_sign(0);
return abs(y);
}

if (abs(x) >= abs(y)) {
a_exp = x_bits.getUnbiasedExponent();
a_mant = x_bits.getMantissa();
b_exp = y_bits.getUnbiasedExponent();
b_mant = y_bits.getMantissa();
a_exp = x_bits.get_unbiased_exponent();
a_mant = x_bits.get_mantissa();
b_exp = y_bits.get_unbiased_exponent();
b_mant = y_bits.get_mantissa();
} else {
a_exp = y_bits.getUnbiasedExponent();
a_mant = y_bits.getMantissa();
b_exp = x_bits.getUnbiasedExponent();
b_mant = x_bits.getMantissa();
a_exp = y_bits.get_unbiased_exponent();
a_mant = y_bits.get_mantissa();
b_exp = x_bits.get_unbiased_exponent();
b_mant = x_bits.get_mantissa();
}

out_exp = a_exp;

// Add an extra bit to simplify the final rounding bit computation.
constexpr UIntType one = UIntType(1) << (MantissaWidth<T>::value + 1);
constexpr UIntType ONE = UIntType(1) << (MantissaWidth<T>::VALUE + 1);

a_mant <<= 1;
b_mant <<= 1;

UIntType leading_one;
int y_mant_width;
if (a_exp != 0) {
leading_one = one;
a_mant |= one;
y_mant_width = MantissaWidth<T>::value + 1;
leading_one = ONE;
a_mant |= ONE;
y_mant_width = MantissaWidth<T>::VALUE + 1;
} else {
leading_one = internal::findLeadingOne(a_mant, y_mant_width);
leading_one = internal::find_leading_one(a_mant, y_mant_width);
a_exp = 1;
}

if (b_exp != 0) {
b_mant |= one;
b_mant |= ONE;
} else {
b_exp = 1;
}
Expand All @@ -204,13 +205,13 @@ static inline T hypot(T x, T y) {
DUIntType sum = a_mant_sq + b_mant_sq;
if (sum >= (DUIntType(1) << (2 * y_mant_width + 2))) {
// a^2 + b^2 >= 4* leading_one^2, so we will need an extra bit to the left.
if (leading_one == one) {
if (leading_one == ONE) {
// For normal result, we discard the last 2 bits of the sum and increase
// the exponent.
sticky_bits = sticky_bits || ((sum & 0x3U) != 0);
sum >>= 2;
++out_exp;
if (out_exp >= FPBits_t::maxExponent) {
if (out_exp >= FPBits_t::MAX_EXPONENT) {
return T(FPBits_t::inf());
}
} else {
Expand All @@ -221,48 +222,48 @@ static inline T hypot(T x, T y) {
}
}

UIntType Y = leading_one;
UIntType R = static_cast<UIntType>(sum >> y_mant_width) - leading_one;
UIntType tailBits = static_cast<UIntType>(sum) & (leading_one - 1);
UIntType y_new = leading_one;
UIntType r = static_cast<UIntType>(sum >> y_mant_width) - leading_one;
UIntType tail_bits = static_cast<UIntType>(sum) & (leading_one - 1);

for (UIntType current_bit = leading_one >> 1; current_bit;
current_bit >>= 1) {
R = (R << 1) + ((tailBits & current_bit) ? 1 : 0);
UIntType tmp = (Y << 1) + current_bit; // 2*y(n - 1) + 2^(-n)
if (R >= tmp) {
R -= tmp;
Y += current_bit;
r = (r << 1) + ((tail_bits & current_bit) ? 1 : 0);
UIntType tmp = (y_new << 1) + current_bit; // 2*y_new(n - 1) + 2^(-n)
if (r >= tmp) {
r -= tmp;
y_new += current_bit;
}
}

bool round_bit = Y & UIntType(1);
bool lsb = Y & UIntType(2);
bool round_bit = y_new & UIntType(1);
bool lsb = y_new & UIntType(2);

if (Y >= one) {
Y -= one;
if (y_new >= ONE) {
y_new -= ONE;

if (out_exp == 0) {
out_exp = 1;
}
}

Y >>= 1;
y_new >>= 1;

// Round to the nearest, tie to even.
if (round_bit && (lsb || sticky_bits || (R != 0))) {
++Y;
if (round_bit && (lsb || sticky_bits || (r != 0))) {
++y_new;
}

if (Y >= (one >> 1)) {
Y -= one >> 1;
if (y_new >= (ONE >> 1)) {
y_new -= ONE >> 1;
++out_exp;
if (out_exp >= FPBits_t::maxExponent) {
if (out_exp >= FPBits_t::MAX_EXPONENT) {
return T(FPBits_t::inf());
}
}

Y |= static_cast<UIntType>(out_exp) << MantissaWidth<T>::value;
return *reinterpret_cast<T *>(&Y);
y_new |= static_cast<UIntType>(out_exp) << MantissaWidth<T>::VALUE;
return *reinterpret_cast<T *>(&y_new);
}

} // namespace fputil
Expand Down
60 changes: 30 additions & 30 deletions libc/src/__support/FPUtil/ManipulationFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T frexp(T x, int &exp) {
FPBits<T> bits(x);
if (bits.isInfOrNaN())
if (bits.is_inf_or_nan())
return x;
if (bits.isZero()) {
if (bits.is_zero()) {
exp = 0;
return x;
}
Expand All @@ -43,18 +43,18 @@ template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T modf(T x, T &iptr) {
FPBits<T> bits(x);
if (bits.isZero() || bits.isNaN()) {
if (bits.is_zero() || bits.is_nan()) {
iptr = x;
return x;
} else if (bits.isInf()) {
} else if (bits.is_inf()) {
iptr = x;
return bits.getSign() ? T(FPBits<T>::negZero()) : T(FPBits<T>::zero());
return bits.get_sign() ? T(FPBits<T>::neg_zero()) : T(FPBits<T>::zero());
} else {
iptr = trunc(x);
if (x == iptr) {
// If x is already an integer value, then return zero with the right
// sign.
return bits.getSign() ? T(FPBits<T>::negZero()) : T(FPBits<T>::zero());
return bits.get_sign() ? T(FPBits<T>::neg_zero()) : T(FPBits<T>::zero());
} else {
return x - iptr;
}
Expand All @@ -65,7 +65,7 @@ template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T copysign(T x, T y) {
FPBits<T> xbits(x);
xbits.setSign(FPBits<T>(y).getSign());
xbits.set_sign(FPBits<T>(y).get_sign());
return T(xbits);
}

Expand All @@ -75,11 +75,11 @@ static inline int ilogb(T x) {
// TODO: Raise appropriate floating point exceptions and set errno to the
// an appropriate error value wherever relevant.
FPBits<T> bits(x);
if (bits.isZero()) {
if (bits.is_zero()) {
return FP_ILOGB0;
} else if (bits.isNaN()) {
} else if (bits.is_nan()) {
return FP_ILOGBNAN;
} else if (bits.isInf()) {
} else if (bits.is_inf()) {
return INT_MAX;
}

Expand All @@ -102,13 +102,13 @@ template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T logb(T x) {
FPBits<T> bits(x);
if (bits.isZero()) {
if (bits.is_zero()) {
// TODO(Floating point exception): Raise div-by-zero exception.
// TODO(errno): POSIX requires setting errno to ERANGE.
return T(FPBits<T>::negInf());
} else if (bits.isNaN()) {
return T(FPBits<T>::neg_inf());
} else if (bits.is_nan()) {
return x;
} else if (bits.isInf()) {
} else if (bits.is_inf()) {
// Return positive infinity.
return T(FPBits<T>::inf());
}
Expand All @@ -121,7 +121,7 @@ template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T ldexp(T x, int exp) {
FPBits<T> bits(x);
if (bits.isZero() || bits.isInfOrNaN() || exp == 0)
if (bits.is_zero() || bits.is_inf_or_nan() || exp == 0)
return x;

// NormalFloat uses int32_t to store the true exponent value. We should ensure
Expand All @@ -130,13 +130,13 @@ static inline T ldexp(T x, int exp) {
// early. Because the result of the ldexp operation can be a subnormal number,
// we need to accommodate the (mantissaWidht + 1) worth of shift in
// calculating the limit.
int expLimit = FPBits<T>::maxExponent + MantissaWidth<T>::value + 1;
if (exp > expLimit)
return bits.getSign() ? T(FPBits<T>::negInf()) : T(FPBits<T>::inf());
int exp_limit = FPBits<T>::MAX_EXPONENT + MantissaWidth<T>::VALUE + 1;
if (exp > exp_limit)
return bits.get_sign() ? T(FPBits<T>::neg_inf()) : T(FPBits<T>::inf());

// Similarly on the negative side we return zero early if |exp| is too small.
if (exp < -expLimit)
return bits.getSign() ? T(FPBits<T>::negZero()) : T(FPBits<T>::zero());
if (exp < -exp_limit)
return bits.get_sign() ? T(FPBits<T>::neg_zero()) : T(FPBits<T>::zero());

// For all other values, NormalFloat to T conversion handles it the right way.
NormalFloat<T> normal(bits);
Expand All @@ -147,31 +147,31 @@ static inline T ldexp(T x, int exp) {
template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T nextafter(T from, T to) {
FPBits<T> fromBits(from);
if (fromBits.isNaN())
FPBits<T> from_bits(from);
if (from_bits.is_nan())
return from;

FPBits<T> toBits(to);
if (toBits.isNaN())
FPBits<T> to_bits(to);
if (to_bits.is_nan())
return to;

if (from == to)
return to;

using UIntType = typename FPBits<T>::UIntType;
UIntType intVal = fromBits.uintval();
UIntType signMask = (UIntType(1) << (sizeof(T) * 8 - 1));
UIntType int_val = from_bits.uintval();
UIntType sign_mask = (UIntType(1) << (sizeof(T) * 8 - 1));
if (from != T(0.0)) {
if ((from < to) == (from > T(0.0))) {
++intVal;
++int_val;
} else {
--intVal;
--int_val;
}
} else {
intVal = (toBits.uintval() & signMask) + UIntType(1);
int_val = (to_bits.uintval() & sign_mask) + UIntType(1);
}

return *reinterpret_cast<T *>(&intVal);
return *reinterpret_cast<T *>(&int_val);
// TODO: Raise floating point exceptions as required by the standard.
}

Expand Down
176 changes: 88 additions & 88 deletions libc/src/__support/FPUtil/NearestIntegerOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,26 @@ static inline T trunc(T x) {
// If it is zero also we should return it as is, but the logic
// later in this function takes care of it. But not doing a zero
// check, we improve the run time of non-zero values.
if (bits.isInfOrNaN())
if (bits.is_inf_or_nan())
return x;

int exponent = bits.getExponent();
int exponent = bits.get_exponent();

// If the exponent is greater than the most negative mantissa
// exponent, then x is already an integer.
if (exponent >= static_cast<int>(MantissaWidth<T>::value))
if (exponent >= static_cast<int>(MantissaWidth<T>::VALUE))
return x;

// If the exponent is such that abs(x) is less than 1, then return 0.
if (exponent <= -1) {
if (bits.getSign())
if (bits.get_sign())
return T(-0.0);
else
return T(0.0);
}

int trimSize = MantissaWidth<T>::value - exponent;
bits.setMantissa((bits.getMantissa() >> trimSize) << trimSize);
int trim_size = MantissaWidth<T>::VALUE - exponent;
bits.set_mantissa((bits.get_mantissa() >> trim_size) << trim_size);
return T(bits);
}

Expand All @@ -60,44 +60,44 @@ static inline T ceil(T x) {
FPBits<T> bits(x);

// If x is infinity NaN or zero, return it.
if (bits.isInfOrNaN() || bits.isZero())
if (bits.is_inf_or_nan() || bits.is_zero())
return x;

bool isNeg = bits.getSign();
int exponent = bits.getExponent();
bool is_neg = bits.get_sign();
int exponent = bits.get_exponent();

// If the exponent is greater than the most negative mantissa
// exponent, then x is already an integer.
if (exponent >= static_cast<int>(MantissaWidth<T>::value))
if (exponent >= static_cast<int>(MantissaWidth<T>::VALUE))
return x;

if (exponent <= -1) {
if (isNeg)
if (is_neg)
return T(-0.0);
else
return T(1.0);
}

uint32_t trimSize = MantissaWidth<T>::value - exponent;
bits.setMantissa((bits.getMantissa() >> trimSize) << trimSize);
T truncValue = T(bits);
uint32_t trim_size = MantissaWidth<T>::VALUE - exponent;
bits.set_mantissa((bits.get_mantissa() >> trim_size) << trim_size);
T trunc_value = T(bits);

// If x is already an integer, return it.
if (truncValue == x)
if (trunc_value == x)
return x;

// If x is negative, the ceil operation is equivalent to the trunc operation.
if (isNeg)
return truncValue;
if (is_neg)
return trunc_value;

return truncValue + T(1.0);
return trunc_value + T(1.0);
}

template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T floor(T x) {
FPBits<T> bits(x);
if (bits.getSign()) {
if (bits.get_sign()) {
return -ceil(-x);
} else {
return trunc(x);
Expand All @@ -111,123 +111,123 @@ static inline T round(T x) {
FPBits<T> bits(x);

// If x is infinity NaN or zero, return it.
if (bits.isInfOrNaN() || bits.isZero())
if (bits.is_inf_or_nan() || bits.is_zero())
return x;

bool isNeg = bits.getSign();
int exponent = bits.getExponent();
bool is_neg = bits.get_sign();
int exponent = bits.get_exponent();

// If the exponent is greater than the most negative mantissa
// exponent, then x is already an integer.
if (exponent >= static_cast<int>(MantissaWidth<T>::value))
if (exponent >= static_cast<int>(MantissaWidth<T>::VALUE))
return x;

if (exponent == -1) {
// Absolute value of x is greater than equal to 0.5 but less than 1.
if (isNeg)
if (is_neg)
return T(-1.0);
else
return T(1.0);
}

if (exponent <= -2) {
// Absolute value of x is less than 0.5.
if (isNeg)
if (is_neg)
return T(-0.0);
else
return T(0.0);
}

uint32_t trimSize = MantissaWidth<T>::value - exponent;
bool halfBitSet = bits.getMantissa() & (UIntType(1) << (trimSize - 1));
bits.setMantissa((bits.getMantissa() >> trimSize) << trimSize);
T truncValue = T(bits);
uint32_t trim_size = MantissaWidth<T>::VALUE - exponent;
bool half_bit_set = bits.get_mantissa() & (UIntType(1) << (trim_size - 1));
bits.set_mantissa((bits.get_mantissa() >> trim_size) << trim_size);
T trunc_value = T(bits);

// If x is already an integer, return it.
if (truncValue == x)
if (trunc_value == x)
return x;

if (!halfBitSet) {
if (!half_bit_set) {
// Franctional part is less than 0.5 so round value is the
// same as the trunc value.
return truncValue;
return trunc_value;
} else {
return isNeg ? truncValue - T(1.0) : truncValue + T(1.0);
return is_neg ? trunc_value - T(1.0) : trunc_value + T(1.0);
}
}

template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T roundUsingCurrentRoundingMode(T x) {
static inline T round_using_current_rounding_mode(T x) {
using UIntType = typename FPBits<T>::UIntType;
FPBits<T> bits(x);

// If x is infinity NaN or zero, return it.
if (bits.isInfOrNaN() || bits.isZero())
if (bits.is_inf_or_nan() || bits.is_zero())
return x;

bool isNeg = bits.getSign();
int exponent = bits.getExponent();
int roundingMode = getRound();
bool is_neg = bits.get_sign();
int exponent = bits.get_exponent();
int rounding_mode = get_round();

// If the exponent is greater than the most negative mantissa
// exponent, then x is already an integer.
if (exponent >= static_cast<int>(MantissaWidth<T>::value))
if (exponent >= static_cast<int>(MantissaWidth<T>::VALUE))
return x;

if (exponent <= -1) {
switch (roundingMode) {
switch (rounding_mode) {
case FE_DOWNWARD:
return isNeg ? T(-1.0) : T(0.0);
return is_neg ? T(-1.0) : T(0.0);
case FE_UPWARD:
return isNeg ? T(-0.0) : T(1.0);
return is_neg ? T(-0.0) : T(1.0);
case FE_TOWARDZERO:
return isNeg ? T(-0.0) : T(0.0);
return is_neg ? T(-0.0) : T(0.0);
case FE_TONEAREST:
if (exponent <= -2 || bits.getMantissa() == 0)
return isNeg ? T(-0.0) : T(0.0); // abs(x) <= 0.5
if (exponent <= -2 || bits.get_mantissa() == 0)
return is_neg ? T(-0.0) : T(0.0); // abs(x) <= 0.5
else
return isNeg ? T(-1.0) : T(1.0); // abs(x) > 0.5
return is_neg ? T(-1.0) : T(1.0); // abs(x) > 0.5
default:
__builtin_unreachable();
}
}

uint32_t trimSize = MantissaWidth<T>::value - exponent;
FPBits<T> newBits = bits;
newBits.setMantissa((bits.getMantissa() >> trimSize) << trimSize);
T truncValue = T(newBits);
uint32_t trim_size = MantissaWidth<T>::VALUE - exponent;
FPBits<T> new_bits = bits;
new_bits.set_mantissa((bits.get_mantissa() >> trim_size) << trim_size);
T trunc_value = T(new_bits);

// If x is already an integer, return it.
if (truncValue == x)
if (trunc_value == x)
return x;

UIntType trimValue = bits.getMantissa() & ((UIntType(1) << trimSize) - 1);
UIntType halfValue = (UIntType(1) << (trimSize - 1));
UIntType trim_value = bits.get_mantissa() & ((UIntType(1) << trim_size) - 1);
UIntType half_value = (UIntType(1) << (trim_size - 1));
// If exponent is 0, trimSize will be equal to the mantissa width, and
// truncIsOdd` will not be correct. So, we handle it as a special case
// below.
UIntType truncIsOdd = newBits.getMantissa() & (UIntType(1) << trimSize);
UIntType trunc_is_odd = new_bits.get_mantissa() & (UIntType(1) << trim_size);

switch (roundingMode) {
switch (rounding_mode) {
case FE_DOWNWARD:
return isNeg ? truncValue - T(1.0) : truncValue;
return is_neg ? trunc_value - T(1.0) : trunc_value;
case FE_UPWARD:
return isNeg ? truncValue : truncValue + T(1.0);
return is_neg ? trunc_value : trunc_value + T(1.0);
case FE_TOWARDZERO:
return truncValue;
return trunc_value;
case FE_TONEAREST:
if (trimValue > halfValue) {
return isNeg ? truncValue - T(1.0) : truncValue + T(1.0);
} else if (trimValue == halfValue) {
if (trim_value > half_value) {
return is_neg ? trunc_value - T(1.0) : trunc_value + T(1.0);
} else if (trim_value == half_value) {
if (exponent == 0)
return isNeg ? T(-2.0) : T(2.0);
if (truncIsOdd)
return isNeg ? truncValue - T(1.0) : truncValue + T(1.0);
return is_neg ? T(-2.0) : T(2.0);
if (trunc_is_odd)
return is_neg ? trunc_value - T(1.0) : trunc_value + T(1.0);
else
return truncValue;
return trunc_value;
} else {
return truncValue;
return trunc_value;
}
default:
__builtin_unreachable();
Expand All @@ -240,33 +240,33 @@ template <typename F, typename I,
cpp::EnableIfType<cpp::IsFloatingPointType<F>::Value &&
cpp::IsIntegral<I>::Value,
int> = 0>
static inline I roundedFloatToSignedInteger(F x) {
constexpr I IntegerMin = (I(1) << (sizeof(I) * 8 - 1));
constexpr I IntegerMax = -(IntegerMin + 1);
static inline I rounded_float_to_signed_integer(F x) {
constexpr I INTEGER_MIN = (I(1) << (sizeof(I) * 8 - 1));
constexpr I INTEGER_MAX = -(INTEGER_MIN + 1);
FPBits<F> bits(x);
auto setDomainErrorAndRaiseInvalid = []() {
auto set_domain_error_and_raise_invalid = []() {
#if math_errhandling & MATH_ERRNO
errno = EDOM;
#endif
#if math_errhandling & MATH_ERREXCEPT
raiseExcept(FE_INVALID);
raise_except(FE_INVALID);
#endif
};

if (bits.isInfOrNaN()) {
setDomainErrorAndRaiseInvalid();
return bits.getSign() ? IntegerMin : IntegerMax;
if (bits.is_inf_or_nan()) {
set_domain_error_and_raise_invalid();
return bits.get_sign() ? INTEGER_MIN : INTEGER_MAX;
}

int exponent = bits.getExponent();
constexpr int exponentLimit = sizeof(I) * 8 - 1;
if (exponent > exponentLimit) {
setDomainErrorAndRaiseInvalid();
return bits.getSign() ? IntegerMin : IntegerMax;
} else if (exponent == exponentLimit) {
if (bits.getSign() == 0 || bits.getMantissa() != 0) {
setDomainErrorAndRaiseInvalid();
return bits.getSign() ? IntegerMin : IntegerMax;
int exponent = bits.get_exponent();
constexpr int EXPONENT_LIMIT = sizeof(I) * 8 - 1;
if (exponent > EXPONENT_LIMIT) {
set_domain_error_and_raise_invalid();
return bits.get_sign() ? INTEGER_MIN : INTEGER_MAX;
} else if (exponent == EXPONENT_LIMIT) {
if (bits.get_sign() == 0 || bits.get_mantissa() != 0) {
set_domain_error_and_raise_invalid();
return bits.get_sign() ? INTEGER_MIN : INTEGER_MAX;
}
// If the control reaches here, then it means that the rounded
// value is the most negative number for the signed integer type I.
Expand All @@ -284,17 +284,17 @@ template <typename F, typename I,
cpp::EnableIfType<cpp::IsFloatingPointType<F>::Value &&
cpp::IsIntegral<I>::Value,
int> = 0>
static inline I roundToSignedInteger(F x) {
return internal::roundedFloatToSignedInteger<F, I>(round(x));
static inline I round_to_signed_integer(F x) {
return internal::rounded_float_to_signed_integer<F, I>(round(x));
}

template <typename F, typename I,
cpp::EnableIfType<cpp::IsFloatingPointType<F>::Value &&
cpp::IsIntegral<I>::Value,
int> = 0>
static inline I roundToSignedIntegerUsingCurrentRoundingMode(F x) {
return internal::roundedFloatToSignedInteger<F, I>(
roundUsingCurrentRoundingMode(x));
static inline I round_to_signed_integer_using_current_rounding_mode(F x) {
return internal::rounded_float_to_signed_integer<F, I>(
round_using_current_rounding_mode(x));
}

} // namespace fputil
Expand Down
170 changes: 86 additions & 84 deletions libc/src/__support/FPUtil/NormalFloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,32 @@ template <typename T> struct NormalFloat {
"NormalFloat template parameter has to be a floating point type.");

using UIntType = typename FPBits<T>::UIntType;
static constexpr UIntType one = (UIntType(1) << MantissaWidth<T>::value);
static constexpr UIntType ONE = (UIntType(1) << MantissaWidth<T>::VALUE);

// Unbiased exponent value.
int32_t exponent;

UIntType mantissa;
// We want |UIntType| to have atleast one bit more than the actual mantissa
// bit width to accommodate the implicit 1 value.
static_assert(sizeof(UIntType) * 8 >= MantissaWidth<T>::value + 1,
static_assert(sizeof(UIntType) * 8 >= MantissaWidth<T>::VALUE + 1,
"Bad type for mantissa in NormalFloat.");

bool sign;

NormalFloat(int32_t e, UIntType m, bool s)
: exponent(e), mantissa(m), sign(s) {
if (mantissa >= one)
if (mantissa >= ONE)
return;

unsigned normalizationShift = evaluateNormalizationShift(mantissa);
mantissa = mantissa << normalizationShift;
exponent -= normalizationShift;
unsigned normalization_shift = evaluate_normalization_shift(mantissa);
mantissa = mantissa << normalization_shift;
exponent -= normalization_shift;
}

explicit NormalFloat(T x) { initFromBits(FPBits<T>(x)); }
explicit NormalFloat(T x) { init_from_bits(FPBits<T>(x)); }

explicit NormalFloat(FPBits<T> bits) { initFromBits(bits); }
explicit NormalFloat(FPBits<T> bits) { init_from_bits(bits); }

// Compares this normalized number with another normalized number.
// Returns -1 is this number is less than |other|, 0 if this number is equal
Expand Down Expand Up @@ -89,59 +89,59 @@ template <typename T> struct NormalFloat {
}

operator T() const {
int biasedExponent = exponent + FPBits<T>::exponentBias;
int biased_exponent = exponent + FPBits<T>::EXPONENT_BIAS;
// Max exponent is of the form 0xFF...E. That is why -2 and not -1.
constexpr int maxExponentValue = (1 << ExponentWidth<T>::value) - 2;
if (biasedExponent > maxExponentValue) {
return sign ? T(FPBits<T>::negInf()) : T(FPBits<T>::inf());
constexpr int MAX_EXPONENT_VALUE = (1 << ExponentWidth<T>::VALUE) - 2;
if (biased_exponent > MAX_EXPONENT_VALUE) {
return sign ? T(FPBits<T>::neg_inf()) : T(FPBits<T>::inf());
}

FPBits<T> result(T(0.0));
result.setSign(sign);
result.set_sign(sign);

constexpr int subnormalExponent = -FPBits<T>::exponentBias + 1;
if (exponent < subnormalExponent) {
unsigned shift = subnormalExponent - exponent;
constexpr int SUBNORMAL_EXPONENT = -FPBits<T>::EXPONENT_BIAS + 1;
if (exponent < SUBNORMAL_EXPONENT) {
unsigned shift = SUBNORMAL_EXPONENT - exponent;
// Since exponent > subnormalExponent, shift is strictly greater than
// zero.
if (shift <= MantissaWidth<T>::value + 1) {
if (shift <= MantissaWidth<T>::VALUE + 1) {
// Generate a subnormal number. Might lead to loss of precision.
// We round to nearest and round halfway cases to even.
const UIntType shiftOutMask = (UIntType(1) << shift) - 1;
const UIntType shiftOutValue = mantissa & shiftOutMask;
const UIntType halfwayValue = UIntType(1) << (shift - 1);
result.setUnbiasedExponent(0);
result.setMantissa(mantissa >> shift);
UIntType newMantissa = result.getMantissa();
if (shiftOutValue > halfwayValue) {
newMantissa += 1;
} else if (shiftOutValue == halfwayValue) {
const UIntType shift_out_mask = (UIntType(1) << shift) - 1;
const UIntType shift_out_value = mantissa & shift_out_mask;
const UIntType halfway_value = UIntType(1) << (shift - 1);
result.set_unbiased_exponent(0);
result.set_mantissa(mantissa >> shift);
UIntType new_mantissa = result.get_mantissa();
if (shift_out_value > halfway_value) {
new_mantissa += 1;
} else if (shift_out_value == halfway_value) {
// Round to even.
if (result.getMantissa() & 0x1)
newMantissa += 1;
if (result.get_mantissa() & 0x1)
new_mantissa += 1;
}
result.setMantissa(newMantissa);
result.set_mantissa(new_mantissa);
// Adding 1 to mantissa can lead to overflow. This can only happen if
// mantissa was all ones (0b111..11). For such a case, we will carry
// the overflow into the exponent.
if (newMantissa == one)
result.setUnbiasedExponent(1);
if (new_mantissa == ONE)
result.set_unbiased_exponent(1);
return T(result);
} else {
return T(result);
}
}

result.setUnbiasedExponent(exponent + FPBits<T>::exponentBias);
result.setMantissa(mantissa);
result.set_unbiased_exponent(exponent + FPBits<T>::EXPONENT_BIAS);
result.set_mantissa(mantissa);
return T(result);
}

private:
void initFromBits(FPBits<T> bits) {
sign = bits.getSign();
void init_from_bits(FPBits<T> bits) {
sign = bits.get_sign();

if (bits.isInfOrNaN() || bits.isZero()) {
if (bits.is_inf_or_nan() || bits.is_zero()) {
// Ignore special bit patterns. Implementations deal with them separately
// anyway so this should not be a problem.
exponent = 0;
Expand All @@ -150,19 +150,19 @@ template <typename T> struct NormalFloat {
}

// Normalize subnormal numbers.
if (bits.getUnbiasedExponent() == 0) {
unsigned shift = evaluateNormalizationShift(bits.getMantissa());
mantissa = UIntType(bits.getMantissa()) << shift;
exponent = 1 - FPBits<T>::exponentBias - shift;
if (bits.get_unbiased_exponent() == 0) {
unsigned shift = evaluate_normalization_shift(bits.get_mantissa());
mantissa = UIntType(bits.get_mantissa()) << shift;
exponent = 1 - FPBits<T>::EXPONENT_BIAS - shift;
} else {
exponent = bits.getUnbiasedExponent() - FPBits<T>::exponentBias;
mantissa = one | bits.getMantissa();
exponent = bits.get_unbiased_exponent() - FPBits<T>::EXPONENT_BIAS;
mantissa = ONE | bits.get_mantissa();
}
}

unsigned evaluateNormalizationShift(UIntType m) {
unsigned evaluate_normalization_shift(UIntType m) {
unsigned shift = 0;
for (; (one & m) == 0 && (shift < MantissaWidth<T>::value);
for (; (ONE & m) == 0 && (shift < MantissaWidth<T>::VALUE);
m <<= 1, ++shift)
;
return shift;
Expand All @@ -171,88 +171,90 @@ template <typename T> struct NormalFloat {

#ifdef SPECIAL_X86_LONG_DOUBLE
template <>
inline void NormalFloat<long double>::initFromBits(FPBits<long double> bits) {
sign = bits.getSign();
inline void NormalFloat<long double>::init_from_bits(FPBits<long double> bits) {
sign = bits.get_sign();

if (bits.isInfOrNaN() || bits.isZero()) {
if (bits.is_inf_or_nan() || bits.is_zero()) {
// Ignore special bit patterns. Implementations deal with them separately
// anyway so this should not be a problem.
exponent = 0;
mantissa = 0;
return;
}

if (bits.getUnbiasedExponent() == 0) {
if (bits.getImplicitBit() == 0) {
if (bits.get_unbiased_exponent() == 0) {
if (bits.get_implicit_bit() == 0) {
// Since we ignore zero value, the mantissa in this case is non-zero.
int normalizationShift = evaluateNormalizationShift(bits.getMantissa());
exponent = -16382 - normalizationShift;
mantissa = (bits.getMantissa() << normalizationShift);
int normalization_shift =
evaluate_normalization_shift(bits.get_mantissa());
exponent = -16382 - normalization_shift;
mantissa = (bits.get_mantissa() << normalization_shift);
} else {
exponent = -16382;
mantissa = one | bits.getMantissa();
mantissa = ONE | bits.get_mantissa();
}
} else {
if (bits.getImplicitBit() == 0) {
if (bits.get_implicit_bit() == 0) {
// Invalid number so just store 0 similar to a NaN.
exponent = 0;
mantissa = 0;
} else {
exponent = bits.getUnbiasedExponent() - 16383;
mantissa = one | bits.getMantissa();
exponent = bits.get_unbiased_exponent() - 16383;
mantissa = ONE | bits.get_mantissa();
}
}
}

template <> inline NormalFloat<long double>::operator long double() const {
int biasedExponent = exponent + FPBits<long double>::exponentBias;
int biased_exponent = exponent + FPBits<long double>::EXPONENT_BIAS;
// Max exponent is of the form 0xFF...E. That is why -2 and not -1.
constexpr int maxExponentValue = (1 << ExponentWidth<long double>::value) - 2;
if (biasedExponent > maxExponentValue) {
return sign ? FPBits<long double>::negInf() : FPBits<long double>::inf();
constexpr int MAX_EXPONENT_VALUE =
(1 << ExponentWidth<long double>::VALUE) - 2;
if (biased_exponent > MAX_EXPONENT_VALUE) {
return sign ? FPBits<long double>::neg_inf() : FPBits<long double>::inf();
}

FPBits<long double> result(0.0l);
result.setSign(sign);
result.set_sign(sign);

constexpr int subnormalExponent = -FPBits<long double>::exponentBias + 1;
if (exponent < subnormalExponent) {
unsigned shift = subnormalExponent - exponent;
if (shift <= MantissaWidth<long double>::value + 1) {
constexpr int SUBNORMAL_EXPONENT = -FPBits<long double>::EXPONENT_BIAS + 1;
if (exponent < SUBNORMAL_EXPONENT) {
unsigned shift = SUBNORMAL_EXPONENT - exponent;
if (shift <= MantissaWidth<long double>::VALUE + 1) {
// Generate a subnormal number. Might lead to loss of precision.
// We round to nearest and round halfway cases to even.
const UIntType shiftOutMask = (UIntType(1) << shift) - 1;
const UIntType shiftOutValue = mantissa & shiftOutMask;
const UIntType halfwayValue = UIntType(1) << (shift - 1);
result.setUnbiasedExponent(0);
result.setMantissa(mantissa >> shift);
UIntType newMantissa = result.getMantissa();
if (shiftOutValue > halfwayValue) {
newMantissa += 1;
} else if (shiftOutValue == halfwayValue) {
const UIntType shift_out_mask = (UIntType(1) << shift) - 1;
const UIntType shift_out_value = mantissa & shift_out_mask;
const UIntType halfway_value = UIntType(1) << (shift - 1);
result.set_unbiased_exponent(0);
result.set_mantissa(mantissa >> shift);
UIntType new_mantissa = result.get_mantissa();
if (shift_out_value > halfway_value) {
new_mantissa += 1;
} else if (shift_out_value == halfway_value) {
// Round to even.
if (result.getMantissa() & 0x1)
newMantissa += 1;
if (result.get_mantissa() & 0x1)
new_mantissa += 1;
}
result.setMantissa(newMantissa);
result.set_mantissa(new_mantissa);
// Adding 1 to mantissa can lead to overflow. This can only happen if
// mantissa was all ones (0b111..11). For such a case, we will carry
// the overflow into the exponent and set the implicit bit to 1.
if (newMantissa == one) {
result.setUnbiasedExponent(1);
result.setImplicitBit(1);
if (new_mantissa == ONE) {
result.set_unbiased_exponent(1);
result.set_implicit_bit(1);
} else {
result.setImplicitBit(0);
result.set_implicit_bit(0);
}
return static_cast<long double>(result);
} else {
return static_cast<long double>(result);
}
}

result.setUnbiasedExponent(biasedExponent);
result.setMantissa(mantissa);
result.setImplicitBit(1);
result.set_unbiased_exponent(biased_exponent);
result.set_mantissa(mantissa);
result.set_implicit_bit(1);
return static_cast<long double>(result);
}
#endif // SPECIAL_X86_LONG_DOUBLE
Expand Down
24 changes: 12 additions & 12 deletions libc/src/__support/FPUtil/Sqrt.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,32 +97,32 @@ template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T sqrt(T x) {
using UIntType = typename FPBits<T>::UIntType;
constexpr UIntType One = UIntType(1) << MantissaWidth<T>::value;
constexpr UIntType One = UIntType(1) << MantissaWidth<T>::VALUE;

FPBits<T> bits(x);

if (bits.isInfOrNaN()) {
if (bits.getSign() && (bits.getMantissa() == 0)) {
if (bits.is_inf_or_nan()) {
if (bits.get_sign() && (bits.get_mantissa() == 0)) {
// sqrt(-Inf) = NaN
return FPBits<T>::buildNaN(One >> 1);
return FPBits<T>::build_nan(One >> 1);
} else {
// sqrt(NaN) = NaN
// sqrt(+Inf) = +Inf
return x;
}
} else if (bits.isZero()) {
} else if (bits.is_zero()) {
// sqrt(+0) = +0
// sqrt(-0) = -0
return x;
} else if (bits.getSign()) {
} else if (bits.get_sign()) {
// sqrt( negative numbers ) = NaN
return FPBits<T>::buildNaN(One >> 1);
return FPBits<T>::build_nan(One >> 1);
} else {
int xExp = bits.getExponent();
UIntType xMant = bits.getMantissa();
int xExp = bits.get_exponent();
UIntType xMant = bits.get_mantissa();

// Step 1a: Normalize denormal input and append hidden bit to the mantissa
if (bits.getUnbiasedExponent() == 0) {
if (bits.get_unbiased_exponent() == 0) {
++xExp; // let xExp be the correct exponent of One bit.
internal::normalize<T>(xExp, xMant);
} else {
Expand Down Expand Up @@ -170,9 +170,9 @@ static inline T sqrt(T x) {
}

// Remove hidden bit and append the exponent field.
xExp = ((xExp >> 1) + FPBits<T>::exponentBias);
xExp = ((xExp >> 1) + FPBits<T>::EXPONENT_BIAS);

y = (y - One) | (static_cast<UIntType>(xExp) << MantissaWidth<T>::value);
y = (y - One) | (static_cast<UIntType>(xExp) << MantissaWidth<T>::VALUE);
// Round to nearest, ties to even
if (rb && (lsb || (r != 0))) {
++y;
Expand Down
26 changes: 13 additions & 13 deletions libc/src/__support/FPUtil/aarch64/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct FEnv {
static void writeStatusWord(uint32_t fpsr) { __arm_wsr("fpsr", fpsr); }
};

static inline int enableExcept(int excepts) {
static inline int enable_except(int excepts) {
uint32_t newExcepts = FEnv::getStatusValueForExcept(excepts);
uint32_t controlWord = FEnv::getControlWord();
int oldExcepts =
Expand All @@ -85,7 +85,7 @@ static inline int enableExcept(int excepts) {
return FEnv::exceptionStatusToMacro(oldExcepts);
}

static inline int disableExcept(int excepts) {
static inline int disable_except(int excepts) {
uint32_t disabledExcepts = FEnv::getStatusValueForExcept(excepts);
uint32_t controlWord = FEnv::getControlWord();
int oldExcepts =
Expand All @@ -95,41 +95,41 @@ static inline int disableExcept(int excepts) {
return FEnv::exceptionStatusToMacro(oldExcepts);
}

static inline int getExcept() {
static inline int get_except() {
uint32_t controlWord = FEnv::getControlWord();
int enabledExcepts =
(controlWord >> FEnv::ExceptionControlFlagsBitPosition) & 0x1F;
return FEnv::exceptionStatusToMacro(enabledExcepts);
}

static inline int clearExcept(int excepts) {
static inline int clear_except(int excepts) {
uint32_t statusWord = FEnv::getStatusWord();
uint32_t toClear = FEnv::getStatusValueForExcept(excepts);
statusWord &= ~(toClear << FEnv::ExceptionStatusFlagsBitPosition);
FEnv::writeStatusWord(statusWord);
return 0;
}

static inline int testExcept(int excepts) {
static inline int test_except(int excepts) {
uint32_t toTest = FEnv::getStatusValueForExcept(excepts);
uint32_t statusWord = FEnv::getStatusWord();
return FEnv::exceptionStatusToMacro(
(statusWord >> FEnv::ExceptionStatusFlagsBitPosition) & toTest);
}

static inline int setExcept(int excepts) {
static inline int set_except(int excepts) {
uint32_t statusWord = FEnv::getControlWord();
uint32_t statusValue = FEnv::getStatusValueForExcept(excepts);
statusWord |= (statusValue << FEnv::ExceptionStatusFlagsBitPosition);
FEnv::writeStatusWord(statusWord);
return 0;
}

static inline int raiseExcept(int excepts) {
static inline int raise_except(int excepts) {
float zero = 0.0f;
float one = 1.0f;
float largeValue = float(FPBits<float>(FPBits<float>::maxNormal));
float smallValue = float(FPBits<float>(FPBits<float>::minNormal));
float largeValue = float(FPBits<float>(FPBits<float>::MAX_NORMAL));
float smallValue = float(FPBits<float>(FPBits<float>::MIN_NORMAL));
auto divfunc = [](float a, float b) {
__asm__ __volatile__("ldr s0, %0\n\t"
"ldr s1, %1\n\t"
Expand Down Expand Up @@ -184,7 +184,7 @@ static inline int raiseExcept(int excepts) {
return 0;
}

static inline int getRound() {
static inline int get_round() {
uint32_t roundingMode =
(FEnv::getControlWord() >> FEnv::RoundingControlBitPosition) & 0x3;
switch (roundingMode) {
Expand All @@ -201,7 +201,7 @@ static inline int getRound() {
}
}

static inline int setRound(int mode) {
static inline int set_round(int mode) {
uint16_t bitValue;
switch (mode) {
case FE_TONEAREST:
Expand All @@ -228,14 +228,14 @@ static inline int setRound(int mode) {
return 0;
}

static inline int getEnv(fenv_t *envp) {
static inline int get_env(fenv_t *envp) {
FEnv::FPState *state = reinterpret_cast<FEnv::FPState *>(envp);
state->ControlWord = FEnv::getControlWord();
state->StatusWord = FEnv::getStatusWord();
return 0;
}

static inline int setEnv(const fenv_t *envp) {
static inline int set_env(const fenv_t *envp) {
if (envp == FE_DFL_ENV) {
// Default status and control words bits are all zeros so we just
// write zeros.
Expand Down
14 changes: 7 additions & 7 deletions libc/src/__support/FPUtil/generic/FMA.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ static inline cpp::EnableIfType<cpp::IsSame<T, float>::Value, T> fma(T x, T y,
double sum = prod + z_d;
fputil::FPBits<double> bit_prod(prod), bitz(z_d), bit_sum(sum);

if (!(bit_sum.isInfOrNaN() || bit_sum.isZero())) {
if (!(bit_sum.is_inf_or_nan() || bit_sum.is_zero())) {
// Since the sum is computed in double precision, rounding might happen
// (for instance, when bitz.exponent > bit_prod.exponent + 5, or
// bit_prod.exponent > bitz.exponent + 40). In that case, when we round
Expand All @@ -47,17 +47,17 @@ static inline cpp::EnableIfType<cpp::IsSame<T, float>::Value, T> fma(T x, T y,
// bit of sum, so that the sticky bits used when rounding sum to float are
// correct (when it matters).
fputil::FPBits<double> t(
(bit_prod.getUnbiasedExponent() >= bitz.getUnbiasedExponent())
(bit_prod.get_unbiased_exponent() >= bitz.get_unbiased_exponent())
? ((double(bit_sum) - double(bit_prod)) - double(bitz))
: ((double(bit_sum) - double(bitz)) - double(bit_prod)));

// Update sticky bits if t != 0.0 and the least (52 - 23 - 1 = 28) bits are
// zero.
if (!t.isZero() && ((bit_sum.getMantissa() & 0xfff'ffffULL) == 0)) {
if (bit_sum.getSign() != t.getSign()) {
bit_sum.setMantissa(bit_sum.getMantissa() + 1);
} else if (bit_sum.getMantissa()) {
bit_sum.setMantissa(bit_sum.getMantissa() - 1);
if (!t.is_zero() && ((bit_sum.get_mantissa() & 0xfff'ffffULL) == 0)) {
if (bit_sum.get_sign() != t.get_sign()) {
bit_sum.set_mantissa(bit_sum.get_mantissa() + 1);
} else if (bit_sum.get_mantissa()) {
bit_sum.set_mantissa(bit_sum.get_mantissa() - 1);
}
}
}
Expand Down
306 changes: 154 additions & 152 deletions libc/src/__support/FPUtil/x86_64/FEnvImpl.h

Large diffs are not rendered by default.

136 changes: 69 additions & 67 deletions libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,68 +25,70 @@ namespace fputil {
template <unsigned Width> struct Padding;

// i386 padding.
template <> struct Padding<4> { static constexpr unsigned value = 16; };
template <> struct Padding<4> { static constexpr unsigned VALUE = 16; };

// x86_64 padding.
template <> struct Padding<8> { static constexpr unsigned value = 48; };
template <> struct Padding<8> { static constexpr unsigned VALUE = 48; };

template <> union FPBits<long double> {
using UIntType = __uint128_t;

static constexpr int exponentBias = 0x3FFF;
static constexpr int maxExponent = 0x7FFF;
static constexpr UIntType minSubnormal = UIntType(1);
static constexpr int EXPONENT_BIAS = 0x3FFF;
static constexpr int MAX_EXPONENT = 0x7FFF;
static constexpr UIntType MIN_SUBNORMAL = UIntType(1);
// Subnormal numbers include the implicit bit in x86 long double formats.
static constexpr UIntType maxSubnormal =
(UIntType(1) << (MantissaWidth<long double>::value)) - 1;
static constexpr UIntType minNormal =
(UIntType(3) << MantissaWidth<long double>::value);
static constexpr UIntType maxNormal =
((UIntType(maxExponent) - 1) << (MantissaWidth<long double>::value + 1)) |
(UIntType(1) << MantissaWidth<long double>::value) | maxSubnormal;
static constexpr UIntType MAX_SUBNORMAL =
(UIntType(1) << (MantissaWidth<long double>::VALUE)) - 1;
static constexpr UIntType MIN_NORMAL =
(UIntType(3) << MantissaWidth<long double>::VALUE);
static constexpr UIntType MAX_NORMAL =
((UIntType(MAX_EXPONENT) - 1)
<< (MantissaWidth<long double>::VALUE + 1)) |
(UIntType(1) << MantissaWidth<long double>::VALUE) | MAX_SUBNORMAL;

using FloatProp = FloatProperties<long double>;

UIntType bits;

void setMantissa(UIntType mantVal) {
mantVal &= (FloatProp::mantissaMask);
bits &= ~(FloatProp::mantissaMask);
void set_mantissa(UIntType mantVal) {
mantVal &= (FloatProp::MANTISSA_MASK);
bits &= ~(FloatProp::MANTISSA_MASK);
bits |= mantVal;
}

UIntType getMantissa() const { return bits & FloatProp::mantissaMask; }
UIntType get_mantissa() const { return bits & FloatProp::MANTISSA_MASK; }

void setUnbiasedExponent(UIntType expVal) {
expVal = (expVal << (FloatProp::bitWidth - 1 - FloatProp::exponentWidth)) &
FloatProp::exponentMask;
bits &= ~(FloatProp::exponentMask);
void set_unbiased_exponent(UIntType expVal) {
expVal =
(expVal << (FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH)) &
FloatProp::EXPONENT_MASK;
bits &= ~(FloatProp::EXPONENT_MASK);
bits |= expVal;
}

uint16_t getUnbiasedExponent() const {
return uint16_t((bits & FloatProp::exponentMask) >>
(FloatProp::bitWidth - 1 - FloatProp::exponentWidth));
uint16_t get_unbiased_exponent() const {
return uint16_t((bits & FloatProp::EXPONENT_MASK) >>
(FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH));
}

void setImplicitBit(bool implicitVal) {
bits &= ~(UIntType(1) << FloatProp::mantissaWidth);
bits |= (UIntType(implicitVal) << FloatProp::mantissaWidth);
void set_implicit_bit(bool implicitVal) {
bits &= ~(UIntType(1) << FloatProp::MANTISSA_WIDTH);
bits |= (UIntType(implicitVal) << FloatProp::MANTISSA_WIDTH);
}

bool getImplicitBit() const {
return ((bits & (UIntType(1) << FloatProp::mantissaWidth)) >>
FloatProp::mantissaWidth);
bool get_implicit_bit() const {
return ((bits & (UIntType(1) << FloatProp::MANTISSA_WIDTH)) >>
FloatProp::MANTISSA_WIDTH);
}

void setSign(bool signVal) {
bits &= ~(FloatProp::signMask);
UIntType sign1 = UIntType(signVal) << (FloatProp::bitWidth - 1);
void set_sign(bool signVal) {
bits &= ~(FloatProp::SIGN_MASK);
UIntType sign1 = UIntType(signVal) << (FloatProp::BIT_WIDTH - 1);
bits |= sign1;
}

bool getSign() const {
return ((bits & FloatProp::signMask) >> (FloatProp::bitWidth - 1));
bool get_sign() const {
return ((bits & FloatProp::SIGN_MASK) >> (FloatProp::BIT_WIDTH - 1));
}

long double val;
Expand All @@ -109,73 +111,73 @@ template <> union FPBits<long double> {

UIntType uintval() {
// We zero the padding bits as they can contain garbage.
static constexpr UIntType mask =
static constexpr UIntType MASK =
(UIntType(1) << (sizeof(long double) * 8 -
Padding<sizeof(uintptr_t)>::value)) -
Padding<sizeof(uintptr_t)>::VALUE)) -
1;
return bits & mask;
return bits & MASK;
}

int getExponent() const {
if (getUnbiasedExponent() == 0)
return int(1) - exponentBias;
return int(getUnbiasedExponent()) - exponentBias;
int get_exponent() const {
if (get_unbiased_exponent() == 0)
return int(1) - EXPONENT_BIAS;
return int(get_unbiased_exponent()) - EXPONENT_BIAS;
}

bool isZero() const {
return getUnbiasedExponent() == 0 && getMantissa() == 0 &&
getImplicitBit() == 0;
bool is_zero() const {
return get_unbiased_exponent() == 0 && get_mantissa() == 0 &&
get_implicit_bit() == 0;
}

bool isInf() const {
return getUnbiasedExponent() == maxExponent && getMantissa() == 0 &&
getImplicitBit() == 1;
bool is_inf() const {
return get_unbiased_exponent() == MAX_EXPONENT && get_mantissa() == 0 &&
get_implicit_bit() == 1;
}

bool isNaN() const {
if (getUnbiasedExponent() == maxExponent) {
return (getImplicitBit() == 0) || getMantissa() != 0;
} else if (getUnbiasedExponent() != 0) {
return getImplicitBit() == 0;
bool is_nan() const {
if (get_unbiased_exponent() == MAX_EXPONENT) {
return (get_implicit_bit() == 0) || get_mantissa() != 0;
} else if (get_unbiased_exponent() != 0) {
return get_implicit_bit() == 0;
}
return false;
}

bool isInfOrNaN() const {
return (getUnbiasedExponent() == maxExponent) ||
(getUnbiasedExponent() != 0 && getImplicitBit() == 0);
bool is_inf_or_nan() const {
return (get_unbiased_exponent() == MAX_EXPONENT) ||
(get_unbiased_exponent() != 0 && get_implicit_bit() == 0);
}

// Methods below this are used by tests.

static FPBits<long double> zero() { return FPBits<long double>(0.0l); }

static FPBits<long double> negZero() {
static FPBits<long double> neg_zero() {
FPBits<long double> bits(0.0l);
bits.setSign(1);
bits.set_sign(1);
return bits;
}

static FPBits<long double> inf() {
FPBits<long double> bits(0.0l);
bits.setUnbiasedExponent(maxExponent);
bits.setImplicitBit(1);
bits.set_unbiased_exponent(MAX_EXPONENT);
bits.set_implicit_bit(1);
return bits;
}

static FPBits<long double> negInf() {
static FPBits<long double> neg_inf() {
FPBits<long double> bits(0.0l);
bits.setUnbiasedExponent(maxExponent);
bits.setImplicitBit(1);
bits.setSign(1);
bits.set_unbiased_exponent(MAX_EXPONENT);
bits.set_implicit_bit(1);
bits.set_sign(1);
return bits;
}

static long double buildNaN(UIntType v) {
static long double build_nan(UIntType v) {
FPBits<long double> bits(0.0l);
bits.setUnbiasedExponent(maxExponent);
bits.setImplicitBit(1);
bits.setMantissa(v);
bits.set_unbiased_exponent(MAX_EXPONENT);
bits.set_implicit_bit(1);
bits.set_mantissa(v);
return bits;
}
};
Expand Down
83 changes: 42 additions & 41 deletions libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,93 +24,94 @@ namespace fputil {

static inline long double nextafter(long double from, long double to) {
using FPBits = FPBits<long double>;
FPBits fromBits(from);
if (fromBits.isNaN())
FPBits from_bits(from);
if (from_bits.is_nan())
return from;

FPBits toBits(to);
if (toBits.isNaN())
FPBits to_bits(to);
if (to_bits.is_nan())
return to;

if (from == to)
return to;

// Convert pseudo subnormal number to normal number.
if (fromBits.getImplicitBit() == 1 && fromBits.getUnbiasedExponent() == 0) {
fromBits.setUnbiasedExponent(1);
if (from_bits.get_implicit_bit() == 1 &&
from_bits.get_unbiased_exponent() == 0) {
from_bits.set_unbiased_exponent(1);
}

using UIntType = FPBits::UIntType;
constexpr UIntType signVal = (UIntType(1) << 79);
constexpr UIntType mantissaMask =
(UIntType(1) << MantissaWidth<long double>::value) - 1;
UIntType intVal = fromBits.uintval();
constexpr UIntType SIGN_VAL = (UIntType(1) << 79);
constexpr UIntType MANTISSA_MASK =
(UIntType(1) << MantissaWidth<long double>::VALUE) - 1;
UIntType int_val = from_bits.uintval();
if (from < 0.0l) {
if (from > to) {
if (intVal == (signVal + FPBits::maxSubnormal)) {
if (int_val == (SIGN_VAL + FPBits::MAX_SUBNORMAL)) {
// We deal with normal/subnormal boundary separately to avoid
// dealing with the implicit bit.
intVal = signVal + FPBits::minNormal;
} else if ((intVal & mantissaMask) == mantissaMask) {
fromBits.setMantissa(0);
int_val = SIGN_VAL + FPBits::MIN_NORMAL;
} else if ((int_val & MANTISSA_MASK) == MANTISSA_MASK) {
from_bits.set_mantissa(0);
// Incrementing exponent might overflow the value to infinity,
// which is what is expected. Since NaNs are handling separately,
// it will never overflow "beyond" infinity.
fromBits.setUnbiasedExponent(fromBits.getUnbiasedExponent() + 1);
return fromBits;
from_bits.set_unbiased_exponent(from_bits.get_unbiased_exponent() + 1);
return from_bits;
} else {
++intVal;
++int_val;
}
} else {
if (intVal == (signVal + FPBits::minNormal)) {
if (int_val == (SIGN_VAL + FPBits::MIN_NORMAL)) {
// We deal with normal/subnormal boundary separately to avoid
// dealing with the implicit bit.
intVal = signVal + FPBits::maxSubnormal;
} else if ((intVal & mantissaMask) == 0) {
fromBits.setMantissa(mantissaMask);
int_val = SIGN_VAL + FPBits::MAX_SUBNORMAL;
} else if ((int_val & MANTISSA_MASK) == 0) {
from_bits.set_mantissa(MANTISSA_MASK);
// from == 0 is handled separately so decrementing the exponent will not
// lead to underflow.
fromBits.setUnbiasedExponent(fromBits.getUnbiasedExponent() - 1);
return fromBits;
from_bits.set_unbiased_exponent(from_bits.get_unbiased_exponent() - 1);
return from_bits;
} else {
--intVal;
--int_val;
}
}
} else if (from == 0.0l) {
if (from > to)
intVal = signVal + 1;
int_val = SIGN_VAL + 1;
else
intVal = 1;
int_val = 1;
} else {
if (from > to) {
if (intVal == FPBits::minNormal) {
intVal = FPBits::maxSubnormal;
} else if ((intVal & mantissaMask) == 0) {
fromBits.setMantissa(mantissaMask);
if (int_val == FPBits::MIN_NORMAL) {
int_val = FPBits::MAX_SUBNORMAL;
} else if ((int_val & MANTISSA_MASK) == 0) {
from_bits.set_mantissa(MANTISSA_MASK);
// from == 0 is handled separately so decrementing the exponent will not
// lead to underflow.
fromBits.setUnbiasedExponent(fromBits.getUnbiasedExponent() - 1);
return fromBits;
from_bits.set_unbiased_exponent(from_bits.get_unbiased_exponent() - 1);
return from_bits;
} else {
--intVal;
--int_val;
}
} else {
if (intVal == FPBits::maxSubnormal) {
intVal = FPBits::minNormal;
} else if ((intVal & mantissaMask) == mantissaMask) {
fromBits.setMantissa(0);
if (int_val == FPBits::MAX_SUBNORMAL) {
int_val = FPBits::MIN_NORMAL;
} else if ((int_val & MANTISSA_MASK) == MANTISSA_MASK) {
from_bits.set_mantissa(0);
// Incrementing exponent might overflow the value to infinity,
// which is what is expected. Since NaNs are handling separately,
// it will never overflow "beyond" infinity.
fromBits.setUnbiasedExponent(fromBits.getUnbiasedExponent() + 1);
return fromBits;
from_bits.set_unbiased_exponent(from_bits.get_unbiased_exponent() + 1);
return from_bits;
} else {
++intVal;
++int_val;
}
}
}

return *reinterpret_cast<long double *>(&intVal);
return *reinterpret_cast<long double *>(&int_val);
// TODO: Raise floating point exceptions as required by the standard.
}

Expand Down
28 changes: 14 additions & 14 deletions libc/src/__support/FPUtil/x86_64/SqrtLongDouble.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,34 +50,34 @@ inline void normalize<long double>(int &exponent, __uint128_t &mantissa) {
template <> inline long double sqrt<long double, 0>(long double x) {
using UIntType = typename FPBits<long double>::UIntType;
constexpr UIntType One = UIntType(1)
<< int(MantissaWidth<long double>::value);
<< int(MantissaWidth<long double>::VALUE);

FPBits<long double> bits(x);

if (bits.isInfOrNaN()) {
if (bits.getSign() && (bits.getMantissa() == 0)) {
if (bits.is_inf_or_nan()) {
if (bits.get_sign() && (bits.get_mantissa() == 0)) {
// sqrt(-Inf) = NaN
return FPBits<long double>::buildNaN(One >> 1);
return FPBits<long double>::build_nan(One >> 1);
} else {
// sqrt(NaN) = NaN
// sqrt(+Inf) = +Inf
return x;
}
} else if (bits.isZero()) {
} else if (bits.is_zero()) {
// sqrt(+0) = +0
// sqrt(-0) = -0
return x;
} else if (bits.getSign()) {
} else if (bits.get_sign()) {
// sqrt( negative numbers ) = NaN
return FPBits<long double>::buildNaN(One >> 1);
return FPBits<long double>::build_nan(One >> 1);
} else {
int xExp = bits.getExponent();
UIntType xMant = bits.getMantissa();
int xExp = bits.get_exponent();
UIntType xMant = bits.get_mantissa();

// Step 1a: Normalize denormal input
if (bits.getImplicitBit()) {
xMant |= One;
} else if (bits.getUnbiasedExponent() == 0) {
} else if (bits.get_unbiased_exponent() == 0) {
internal::normalize<long double>(xExp, xMant);
}

Expand Down Expand Up @@ -122,9 +122,9 @@ template <> inline long double sqrt<long double, 0>(long double x) {
}

// Append the exponent field.
xExp = ((xExp >> 1) + FPBits<long double>::exponentBias);
xExp = ((xExp >> 1) + FPBits<long double>::EXPONENT_BIAS);
y |= (static_cast<UIntType>(xExp)
<< (MantissaWidth<long double>::value + 1));
<< (MantissaWidth<long double>::VALUE + 1));

// Round to nearest, ties to even
if (rb && (lsb || (r != 0))) {
Expand All @@ -133,9 +133,9 @@ template <> inline long double sqrt<long double, 0>(long double x) {

// Extract output
FPBits<long double> out(0.0L);
out.setUnbiasedExponent(xExp);
out.set_unbiased_exponent(xExp);
out.setImplicitBit(1);
out.setMantissa((y & (One - 1)));
out.set_mantissa((y & (One - 1)));

return out;
}
Expand Down
4 changes: 2 additions & 2 deletions libc/src/__support/detailed_powers_of_ten.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ constexpr int32_t DETAILED_POWERS_OF_TEN_MIN_EXP_10 = -348;
constexpr int32_t DETAILED_POWERS_OF_TEN_MAX_EXP_10 = 347;

// This rescales the base 10 exponent by a factor of log(10)/log(2).
static inline int64_t exp10ToExp2(int64_t exp10) {
static inline int64_t exp10_to_exp2(int64_t exp10) {
return (217706 * exp10) >> 16;
}

static const uint64_t DETAILED_POWERS_OF_TEN[696][2] = {
static constexpr uint64_t DETAILED_POWERS_OF_TEN[696][2] = {
{0x1732C869CD60E453, 0xFA8FD5A0081C0288}, // 1e-348
{0x0E7FBD42205C8EB4, 0x9C99E58405118195}, // 1e-347
{0x521FAC92A873B261, 0xC3C05EE50655E1FA}, // 1e-346
Expand Down
40 changes: 20 additions & 20 deletions libc/src/__support/endian.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,108 +28,108 @@ namespace internal {
// - to prevent fallback in (unlikely) case of middle-endianness.

template <unsigned ORDER> struct Endian {
static constexpr const bool isLittle = ORDER == __ORDER_LITTLE_ENDIAN__;
static constexpr const bool isBig = ORDER == __ORDER_BIG_ENDIAN__;
template <typename T> static T ToBigEndian(T value);
template <typename T> static T ToLittleEndian(T value);
static constexpr const bool IS_LITTLE = ORDER == __ORDER_LITTLE_ENDIAN__;
static constexpr const bool IS_BIG = ORDER == __ORDER_BIG_ENDIAN__;
template <typename T> static T to_big_endian(T value);
template <typename T> static T to_little_endian(T value);
};

// Little Endian specializations
template <>
template <>
inline uint8_t
Endian<__ORDER_LITTLE_ENDIAN__>::ToBigEndian<uint8_t>(uint8_t v) {
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint8_t>(uint8_t v) {
return v;
}
template <>
template <>
inline uint8_t
Endian<__ORDER_LITTLE_ENDIAN__>::ToLittleEndian<uint8_t>(uint8_t v) {
Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint8_t>(uint8_t v) {
return v;
}
template <>
template <>
inline uint16_t
Endian<__ORDER_LITTLE_ENDIAN__>::ToBigEndian<uint16_t>(uint16_t v) {
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint16_t>(uint16_t v) {
return __builtin_bswap16(v);
}
template <>
template <>
inline uint16_t
Endian<__ORDER_LITTLE_ENDIAN__>::ToLittleEndian<uint16_t>(uint16_t v) {
Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint16_t>(uint16_t v) {
return v;
}
template <>
template <>
inline uint32_t
Endian<__ORDER_LITTLE_ENDIAN__>::ToBigEndian<uint32_t>(uint32_t v) {
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint32_t>(uint32_t v) {
return __builtin_bswap32(v);
}
template <>
template <>
inline uint32_t
Endian<__ORDER_LITTLE_ENDIAN__>::ToLittleEndian<uint32_t>(uint32_t v) {
Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint32_t>(uint32_t v) {
return v;
}
template <>
template <>
inline uint64_t
Endian<__ORDER_LITTLE_ENDIAN__>::ToBigEndian<uint64_t>(uint64_t v) {
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint64_t>(uint64_t v) {
return __builtin_bswap64(v);
}
template <>
template <>
inline uint64_t
Endian<__ORDER_LITTLE_ENDIAN__>::ToLittleEndian<uint64_t>(uint64_t v) {
Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint64_t>(uint64_t v) {
return v;
}

// Big Endian specializations
template <>
template <>
inline uint8_t Endian<__ORDER_BIG_ENDIAN__>::ToBigEndian<uint8_t>(uint8_t v) {
inline uint8_t Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint8_t>(uint8_t v) {
return v;
}
template <>
template <>
inline uint8_t
Endian<__ORDER_BIG_ENDIAN__>::ToLittleEndian<uint8_t>(uint8_t v) {
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint8_t>(uint8_t v) {
return v;
}
template <>
template <>
inline uint16_t
Endian<__ORDER_BIG_ENDIAN__>::ToBigEndian<uint16_t>(uint16_t v) {
Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint16_t>(uint16_t v) {
return v;
}
template <>
template <>
inline uint16_t
Endian<__ORDER_BIG_ENDIAN__>::ToLittleEndian<uint16_t>(uint16_t v) {
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint16_t>(uint16_t v) {
return __builtin_bswap16(v);
}
template <>
template <>
inline uint32_t
Endian<__ORDER_BIG_ENDIAN__>::ToBigEndian<uint32_t>(uint32_t v) {
Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint32_t>(uint32_t v) {
return v;
}
template <>
template <>
inline uint32_t
Endian<__ORDER_BIG_ENDIAN__>::ToLittleEndian<uint32_t>(uint32_t v) {
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint32_t>(uint32_t v) {
return __builtin_bswap32(v);
}
template <>
template <>
inline uint64_t
Endian<__ORDER_BIG_ENDIAN__>::ToBigEndian<uint64_t>(uint64_t v) {
Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint64_t>(uint64_t v) {
return v;
}
template <>
template <>
inline uint64_t
Endian<__ORDER_BIG_ENDIAN__>::ToLittleEndian<uint64_t>(uint64_t v) {
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint64_t>(uint64_t v) {
return __builtin_bswap64(v);
}

Expand Down
226 changes: 114 additions & 112 deletions libc/src/__support/high_precision_decimal.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ namespace __llvm_libc {
namespace internal {

struct LShiftTableEntry {
uint32_t newDigits;
char const *powerOfFive;
uint32_t new_digits;
char const *power_of_five;
};

// This is based on the HPD data structure described as part of the Simple
Expand Down Expand Up @@ -105,20 +105,20 @@ class HighPrecisionDecimal {
// large enough for any practical number.
static constexpr uint32_t MAX_NUM_DIGITS = 800;

uint32_t numDigits = 0;
int32_t decimalPoint = 0;
uint32_t num_digits = 0;
int32_t decimal_point = 0;
bool truncated = false;
uint8_t digits[MAX_NUM_DIGITS];

private:
bool shouldRoundUp(uint32_t roundToDigit) {
if (roundToDigit < 0 || roundToDigit >= this->numDigits) {
bool should_round_up(uint32_t roundToDigit) {
if (roundToDigit < 0 || roundToDigit >= this->num_digits) {
return false;
}

// If we're right in the middle and there are no extra digits
if (this->digits[roundToDigit] == 5 &&
roundToDigit + 1 == this->numDigits) {
roundToDigit + 1 == this->num_digits) {

// Round up if we've truncated (since that means the result is slightly
// higher than what's represented.)
Expand All @@ -136,99 +136,101 @@ class HighPrecisionDecimal {

// Takes an amount to left shift and returns the number of new digits needed
// to store the result based on LEFT_SHIFT_DIGIT_TABLE.
uint32_t getNumNewDigits(uint32_t lShiftAmount) {
const char *powerOfFive = LEFT_SHIFT_DIGIT_TABLE[lShiftAmount].powerOfFive;
uint32_t newDigits = LEFT_SHIFT_DIGIT_TABLE[lShiftAmount].newDigits;
uint32_t digitIndex = 0;
while (powerOfFive[digitIndex] != 0) {
if (digitIndex >= this->numDigits) {
return newDigits - 1;
uint32_t get_num_new_digits(uint32_t lShiftAmount) {
const char *power_of_five =
LEFT_SHIFT_DIGIT_TABLE[lShiftAmount].power_of_five;
uint32_t new_digits = LEFT_SHIFT_DIGIT_TABLE[lShiftAmount].new_digits;
uint32_t digit_index = 0;
while (power_of_five[digit_index] != 0) {
if (digit_index >= this->num_digits) {
return new_digits - 1;
}
if (this->digits[digitIndex] != powerOfFive[digitIndex] - '0') {
return newDigits -
((this->digits[digitIndex] < powerOfFive[digitIndex] - '0') ? 1
: 0);
if (this->digits[digit_index] != power_of_five[digit_index] - '0') {
return new_digits -
((this->digits[digit_index] < power_of_five[digit_index] - '0')
? 1
: 0);
}
++digitIndex;
++digit_index;
}
return newDigits;
return new_digits;
}

// Trim all trailing 0s
void trimTrailingZeroes() {
while (this->numDigits > 0 && this->digits[this->numDigits - 1] == 0) {
--this->numDigits;
void trim_trailing_zeroes() {
while (this->num_digits > 0 && this->digits[this->num_digits - 1] == 0) {
--this->num_digits;
}
if (this->numDigits == 0) {
this->decimalPoint = 0;
if (this->num_digits == 0) {
this->decimal_point = 0;
}
}

// Perform a digitwise binary non-rounding right shift on this value by
// shiftAmount. The shiftAmount can't be more than MAX_SHIFT_AMOUNT to prevent
// overflow.
void rightShift(uint32_t shiftAmount) {
uint32_t readIndex = 0;
uint32_t writeIndex = 0;
void right_shift(uint32_t shiftAmount) {
uint32_t read_index = 0;
uint32_t write_index = 0;

uint64_t accumulator = 0;

const uint64_t shiftMask = (uint64_t(1) << shiftAmount) - 1;
const uint64_t shift_mask = (uint64_t(1) << shiftAmount) - 1;

// Warm Up phase: we don't have enough digits to start writing, so just
// read them into the accumulator.
while (accumulator >> shiftAmount == 0) {
uint64_t readDigit = 0;
uint64_t read_digit = 0;
// If there are still digits to read, read the next one, else the digit is
// assumed to be 0.
if (readIndex < this->numDigits) {
readDigit = this->digits[readIndex];
if (read_index < this->num_digits) {
read_digit = this->digits[read_index];
}
accumulator = accumulator * 10 + readDigit;
++readIndex;
accumulator = accumulator * 10 + read_digit;
++read_index;
}

// Shift the decimal point by the number of digits it took to fill the
// accumulator.
this->decimalPoint -= readIndex - 1;
this->decimal_point -= read_index - 1;

// Middle phase: we have enough digits to write, as well as more digits to
// read. Keep reading until we run out of digits.
while (readIndex < this->numDigits) {
uint64_t readDigit = this->digits[readIndex];
uint64_t writeDigit = accumulator >> shiftAmount;
accumulator &= shiftMask;
this->digits[writeIndex] = static_cast<uint8_t>(writeDigit);
accumulator = accumulator * 10 + readDigit;
++readIndex;
++writeIndex;
while (read_index < this->num_digits) {
uint64_t read_digit = this->digits[read_index];
uint64_t write_digit = accumulator >> shiftAmount;
accumulator &= shift_mask;
this->digits[write_index] = static_cast<uint8_t>(write_digit);
accumulator = accumulator * 10 + read_digit;
++read_index;
++write_index;
}

// Cool Down phase: All of the readable digits have been read, so just write
// the remainder, while treating any more digits as 0.
while (accumulator > 0) {
uint64_t writeDigit = accumulator >> shiftAmount;
accumulator &= shiftMask;
if (writeIndex < MAX_NUM_DIGITS) {
this->digits[writeIndex] = static_cast<uint8_t>(writeDigit);
++writeIndex;
} else if (writeDigit > 0) {
uint64_t write_digit = accumulator >> shiftAmount;
accumulator &= shift_mask;
if (write_index < MAX_NUM_DIGITS) {
this->digits[write_index] = static_cast<uint8_t>(write_digit);
++write_index;
} else if (write_digit > 0) {
this->truncated = true;
}
accumulator = accumulator * 10;
}
this->numDigits = writeIndex;
this->trimTrailingZeroes();
this->num_digits = write_index;
this->trim_trailing_zeroes();
}

// Perform a digitwise binary non-rounding left shift on this value by
// shiftAmount. The shiftAmount can't be more than MAX_SHIFT_AMOUNT to prevent
// overflow.
void leftShift(uint32_t shiftAmount) {
uint32_t newDigits = this->getNumNewDigits(shiftAmount);
void left_shift(uint32_t shiftAmount) {
uint32_t new_digits = this->get_num_new_digits(shiftAmount);

int32_t readIndex = this->numDigits - 1;
uint32_t writeIndex = this->numDigits + newDigits;
int32_t read_index = this->num_digits - 1;
uint32_t write_index = this->num_digits + new_digits;

uint64_t accumulator = 0;

Expand All @@ -237,89 +239,89 @@ class HighPrecisionDecimal {

// Middle phase: while we have more digits to read, keep reading as well as
// writing.
while (readIndex >= 0) {
accumulator += static_cast<uint64_t>(this->digits[readIndex])
while (read_index >= 0) {
accumulator += static_cast<uint64_t>(this->digits[read_index])
<< shiftAmount;
uint64_t nextAccumulator = accumulator / 10;
uint64_t writeDigit = accumulator - (10 * nextAccumulator);
--writeIndex;
if (writeIndex < MAX_NUM_DIGITS) {
this->digits[writeIndex] = static_cast<uint8_t>(writeDigit);
} else if (writeDigit != 0) {
uint64_t next_accumulator = accumulator / 10;
uint64_t write_digit = accumulator - (10 * next_accumulator);
--write_index;
if (write_index < MAX_NUM_DIGITS) {
this->digits[write_index] = static_cast<uint8_t>(write_digit);
} else if (write_digit != 0) {
this->truncated = true;
}
accumulator = nextAccumulator;
--readIndex;
accumulator = next_accumulator;
--read_index;
}

// Cool Down phase: there are no more digits to read, so just write the
// remaining digits in the accumulator.
while (accumulator > 0) {
uint64_t nextAccumulator = accumulator / 10;
uint64_t writeDigit = accumulator - (10 * nextAccumulator);
--writeIndex;
if (writeIndex < MAX_NUM_DIGITS) {
this->digits[writeIndex] = static_cast<uint8_t>(writeDigit);
} else if (writeDigit != 0) {
uint64_t next_accumulator = accumulator / 10;
uint64_t write_digit = accumulator - (10 * next_accumulator);
--write_index;
if (write_index < MAX_NUM_DIGITS) {
this->digits[write_index] = static_cast<uint8_t>(write_digit);
} else if (write_digit != 0) {
this->truncated = true;
}
accumulator = nextAccumulator;
accumulator = next_accumulator;
}

this->numDigits += newDigits;
if (this->numDigits > MAX_NUM_DIGITS) {
this->numDigits = MAX_NUM_DIGITS;
this->num_digits += new_digits;
if (this->num_digits > MAX_NUM_DIGITS) {
this->num_digits = MAX_NUM_DIGITS;
}
this->decimalPoint += newDigits;
this->trimTrailingZeroes();
this->decimal_point += new_digits;
this->trim_trailing_zeroes();
}

public:
// numString is assumed to be a string of numeric characters. It doesn't
// handle leading spaces.
HighPrecisionDecimal(const char *__restrict numString) {
bool sawDot = false;
bool saw_dot = false;
while (isdigit(*numString) || *numString == '.') {
if (*numString == '.') {
if (sawDot) {
if (saw_dot) {
break;
}
this->decimalPoint = this->numDigits;
sawDot = true;
this->decimal_point = this->num_digits;
saw_dot = true;
} else {
if (*numString == '0' && this->numDigits == 0) {
--this->decimalPoint;
if (*numString == '0' && this->num_digits == 0) {
--this->decimal_point;
++numString;
continue;
}
if (this->numDigits < MAX_NUM_DIGITS) {
this->digits[this->numDigits] = *numString - '0';
++this->numDigits;
if (this->num_digits < MAX_NUM_DIGITS) {
this->digits[this->num_digits] = *numString - '0';
++this->num_digits;
} else if (*numString != '0') {
this->truncated = true;
}
}
++numString;
}

if (!sawDot) {
this->decimalPoint = this->numDigits;
if (!saw_dot) {
this->decimal_point = this->num_digits;
}

if ((*numString | 32) == 'e') {
++numString;
if (isdigit(*numString) || *numString == '+' || *numString == '-') {
int32_t addToExp = strtointeger<int32_t>(numString, nullptr, 10);
if (addToExp > 100000) {
addToExp = 100000;
} else if (addToExp < -100000) {
addToExp = -100000;
int32_t add_to_exp = strtointeger<int32_t>(numString, nullptr, 10);
if (add_to_exp > 100000) {
add_to_exp = 100000;
} else if (add_to_exp < -100000) {
add_to_exp = -100000;
}
this->decimalPoint += addToExp;
this->decimal_point += add_to_exp;
}
}

this->trimTrailingZeroes();
this->trim_trailing_zeroes();
}

// Binary shift left (shiftAmount > 0) or right (shiftAmount < 0)
Expand All @@ -330,50 +332,50 @@ class HighPrecisionDecimal {
// Left
else if (shiftAmount > 0) {
while (static_cast<uint32_t>(shiftAmount) > MAX_SHIFT_AMOUNT) {
this->leftShift(MAX_SHIFT_AMOUNT);
this->left_shift(MAX_SHIFT_AMOUNT);
shiftAmount -= MAX_SHIFT_AMOUNT;
}
this->leftShift(shiftAmount);
this->left_shift(shiftAmount);
}
// Right
else {
while (static_cast<uint32_t>(shiftAmount) < -MAX_SHIFT_AMOUNT) {
this->rightShift(MAX_SHIFT_AMOUNT);
this->right_shift(MAX_SHIFT_AMOUNT);
shiftAmount += MAX_SHIFT_AMOUNT;
}
this->rightShift(-shiftAmount);
this->right_shift(-shiftAmount);
}
}

// Round the number represented to the closest value of unsigned int type T.
// This is done ignoring overflow.
template <class T> T roundToIntegerType() {
template <class T> T round_to_integer_type() {
T result = 0;
uint32_t curDigit = 0;
uint32_t cur_digit = 0;

while (static_cast<int32_t>(curDigit) < this->decimalPoint &&
curDigit < this->numDigits) {
result = result * 10 + (this->digits[curDigit]);
++curDigit;
while (static_cast<int32_t>(cur_digit) < this->decimal_point &&
cur_digit < this->num_digits) {
result = result * 10 + (this->digits[cur_digit]);
++cur_digit;
}

// If there are implicit 0s at the end of the number, include those.
while (static_cast<int32_t>(curDigit) < this->decimalPoint) {
while (static_cast<int32_t>(cur_digit) < this->decimal_point) {
result *= 10;
++curDigit;
++cur_digit;
}
if (this->shouldRoundUp(this->decimalPoint)) {
if (this->should_round_up(this->decimal_point)) {
++result;
}
return result;
}

// Extra functions for testing.

uint8_t *getDigits() { return this->digits; }
uint32_t getNumDigits() { return this->numDigits; }
int32_t getDecimalPoint() { return this->decimalPoint; }
void setTruncated(bool trunc) { this->truncated = trunc; }
uint8_t *get_digits() { return this->digits; }
uint32_t get_num_digits() { return this->num_digits; }
int32_t get_decimal_point() { return this->decimal_point; }
void set_truncated(bool trunc) { this->truncated = trunc; }
};

} // namespace internal
Expand Down
4 changes: 2 additions & 2 deletions libc/src/__support/integer_operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ namespace __llvm_libc {

template <typename T>
static constexpr cpp::EnableIfType<cpp::IsIntegral<T>::Value, T>
integerAbs(T n) {
integer_abs(T n) {
return (n < 0) ? -n : n;
}

template <typename T>
static constexpr cpp::EnableIfType<cpp::IsIntegral<T>::Value, void>
integerRemQuo(T x, T y, T &quot, T &rem) {
integer_rem_quo(T x, T y, T &quot, T &rem) {
quot = x / y;
rem = x % y;
}
Expand Down
Loading