Skip to content

Commit 24a903c

Browse files
authored
[libc][NFC] Move functions from FPBits to FPRep, make bits member private (#79974)
1 parent 0f9ab7b commit 24a903c

File tree

9 files changed

+62
-62
lines changed

9 files changed

+62
-62
lines changed

libc/src/__support/FPUtil/FPBits.h

Lines changed: 49 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -551,10 +551,13 @@ struct FPRep : public FPRepSem<fp_type, RetT> {
551551
using UP::SIG_LEN;
552552

553553
public:
554+
// Constants.
554555
using UP::EXP_BIAS;
555556
using UP::EXP_MASK;
556557
using UP::FRACTION_MASK;
557558
using UP::SIGN_MASK;
559+
LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT =
560+
(1 << UP::EXP_LEN) - 1;
558561

559562
LIBC_INLINE constexpr FPRep() = default;
560563
LIBC_INLINE constexpr explicit FPRep(StorageType x) : UP(x) {}
@@ -652,6 +655,47 @@ struct FPRep : public FPRepSem<fp_type, RetT> {
652655
bits = merge(bits, mantVal, FRACTION_MASK);
653656
}
654657

658+
// Unsafe function to create a floating point representation.
659+
// It simply packs the sign, biased exponent and mantissa values without
660+
// checking bound nor normalization.
661+
// FIXME: Use an uint32_t for 'biased_exp'.
662+
LIBC_INLINE static constexpr RetT
663+
create_value(Sign sign, StorageType biased_exp, StorageType mantissa) {
664+
static_assert(fp_type != FPType::X86_Binary80,
665+
"This function is not tested for X86 Extended Precision");
666+
return RetT(encode(sign, BiasedExp(static_cast<uint32_t>(biased_exp)),
667+
Sig(mantissa)));
668+
}
669+
670+
// The function converts integer number and unbiased exponent to proper float
671+
// T type:
672+
// Result = number * 2^(ep+1 - exponent_bias)
673+
// Be careful!
674+
// 1) "ep" is the raw exponent value.
675+
// 2) The function adds +1 to ep for seamless normalized to denormalized
676+
// transition.
677+
// 3) The function does not check exponent high limit.
678+
// 4) "number" zero value is not processed correctly.
679+
// 5) Number is unsigned, so the result can be only positive.
680+
LIBC_INLINE static constexpr RetT make_value(StorageType number, int ep) {
681+
static_assert(fp_type != FPType::X86_Binary80,
682+
"This function is not tested for X86 Extended Precision");
683+
FPRep result;
684+
// offset: +1 for sign, but -1 for implicit first bit
685+
int lz = cpp::countl_zero(number) - UP::EXP_LEN;
686+
number <<= lz;
687+
ep -= lz;
688+
689+
if (LIBC_LIKELY(ep >= 0)) {
690+
// Implicit number bit will be removed by mask
691+
result.set_mantissa(number);
692+
result.set_biased_exponent(ep + 1);
693+
} else {
694+
result.set_mantissa(number >> -ep);
695+
}
696+
return RetT(result.uintval());
697+
}
698+
655699
private:
656700
// Merge bits from 'a' and 'b' values according to 'mask'.
657701
// Use 'a' bits when corresponding 'mask' bits are zeroes and 'b' bits when
@@ -696,79 +740,33 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
696740
static_assert(cpp::always_false<UnqualT>, "Unsupported type");
697741
}
698742

699-
// A generic class to manipulate floating point formats.
743+
// A generic class to manipulate C++ floating point formats.
700744
// It derives most of its functionality to FPRep above.
701745
template <typename T>
702746
struct FPBits final : public internal::FPRep<get_fp_type<T>(), FPBits<T>> {
703747
static_assert(cpp::is_floating_point_v<T>,
704748
"FPBits instantiated with invalid type.");
705749
using UP = internal::FPRep<get_fp_type<T>(), FPBits<T>>;
706-
using Rep = UP;
707750
using StorageType = typename UP::StorageType;
708751

709-
using UP::bits;
710-
711-
// Constants.
712-
LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT =
713-
(1 << UP::EXP_LEN) - 1;
714-
715752
// Constructors.
716753
LIBC_INLINE constexpr FPBits() = default;
717754

718755
template <typename XType> LIBC_INLINE constexpr explicit FPBits(XType x) {
719756
using Unqual = typename cpp::remove_cv_t<XType>;
720757
if constexpr (cpp::is_same_v<Unqual, T>) {
721-
bits = cpp::bit_cast<StorageType>(x);
758+
UP::bits = cpp::bit_cast<StorageType>(x);
722759
} else if constexpr (cpp::is_same_v<Unqual, StorageType>) {
723-
bits = x;
760+
UP::bits = x;
724761
} else {
725762
// We don't want accidental type promotions/conversions, so we require
726763
// exact type match.
727764
static_assert(cpp::always_false<XType>);
728765
}
729766
}
730-
// Floating-point conversions.
731-
LIBC_INLINE constexpr T get_val() const { return cpp::bit_cast<T>(bits); }
732-
733-
// TODO: Use an uint32_t for 'biased_exp'.
734-
LIBC_INLINE static constexpr FPBits<T>
735-
create_value(Sign sign, StorageType biased_exp, StorageType mantissa) {
736-
static_assert(get_fp_type<T>() != FPType::X86_Binary80,
737-
"This function is not tested for X86 Extended Precision");
738-
return FPBits(UP::encode(
739-
sign, typename UP::BiasedExponent(static_cast<uint32_t>(biased_exp)),
740-
typename UP::Significand(mantissa)));
741-
}
742-
743-
// The function convert integer number and unbiased exponent to proper float
744-
// T type:
745-
// Result = number * 2^(ep+1 - exponent_bias)
746-
// Be careful!
747-
// 1) "ep" is raw exponent value.
748-
// 2) The function add to +1 to ep for seamless normalized to denormalized
749-
// transition.
750-
// 3) The function did not check exponent high limit.
751-
// 4) "number" zero value is not processed correctly.
752-
// 5) Number is unsigned, so the result can be only positive.
753-
LIBC_INLINE static constexpr FPBits<T> make_value(StorageType number,
754-
int ep) {
755-
static_assert(get_fp_type<T>() != FPType::X86_Binary80,
756-
"This function is not tested for X86 Extended Precision");
757-
FPBits<T> result;
758-
// offset: +1 for sign, but -1 for implicit first bit
759-
int lz = cpp::countl_zero(number) - UP::EXP_LEN;
760-
number <<= lz;
761-
ep -= lz;
762767

763-
if (LIBC_LIKELY(ep >= 0)) {
764-
// Implicit number bit will be removed by mask
765-
result.set_mantissa(number);
766-
result.set_biased_exponent(ep + 1);
767-
} else {
768-
result.set_mantissa(number >> -ep);
769-
}
770-
return result;
771-
}
768+
// Floating-point conversions.
769+
LIBC_INLINE constexpr T get_val() const { return cpp::bit_cast<T>(UP::bits); }
772770
};
773771

774772
} // namespace fputil

libc/src/math/generic/explogxf.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ LIBC_INLINE static double log2_eval(double x) {
283283
int p1 = (bs.get_mantissa() >> (FPB::FRACTION_LEN - LOG_P1_BITS)) &
284284
(LOG_P1_SIZE - 1);
285285

286-
bs.bits &= FPB::FRACTION_MASK >> LOG_P1_BITS;
286+
bs.set_uintval(bs.uintval() & (FPB::FRACTION_MASK >> LOG_P1_BITS));
287287
bs.set_biased_exponent(FPB::EXP_BIAS);
288288
double dx = (bs.get_val() - 1.0) * LOG_P1_1_OVER[p1];
289289

@@ -313,7 +313,7 @@ LIBC_INLINE static double log_eval(double x) {
313313
int p1 = static_cast<int>(bs.get_mantissa() >> (FPB::FRACTION_LEN - 7));
314314

315315
// Set bs to (1 + (mx - p1*2^(-7))
316-
bs.bits &= FPB::FRACTION_MASK >> 7;
316+
bs.set_uintval(bs.uintval() & (FPB::FRACTION_MASK >> 7));
317317
bs.set_biased_exponent(FPB::EXP_BIAS);
318318
// dx = (mx - p1*2^(-7)) / (1 + p1*2^(-7)).
319319
double dx = (bs.get_val() - 1.0) * ONE_OVER_F[p1];

libc/src/math/generic/hypotf.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ LLVM_LIBC_FUNCTION(float, hypotf, (float x, float y)) {
5252
uint64_t lrs = result.uintval() & mask;
5353

5454
if (lrs == 0x0000'0000'1000'0000ULL && err < diff) {
55-
result.bits |= 1ULL;
55+
result.set_uintval(result.uintval() | 1ULL);
5656
} else if (lrs == 0x0000'0000'3000'0000ULL && err > diff) {
57-
result.bits -= 1ULL;
57+
result.set_uintval(result.uintval() - 1ULL);
5858
}
5959
} else {
6060
FPBits bits_x(x), bits_y(y);

libc/src/math/generic/log1pf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ LIBC_INLINE float log(double x) {
6464
FPBits f = xbits;
6565

6666
// Clear the lowest 45 bits.
67-
f.bits &= ~0x0000'1FFF'FFFF'FFFFULL;
67+
f.set_uintval(f.uintval() & ~0x0000'1FFF'FFFF'FFFFULL);
6868

6969
double d = xbits.get_val() - f.get_val();
7070
d *= ONE_OVER_F[f_index];

libc/src/math/generic/range_reduction_fma.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ LIBC_INLINE int64_t large_range_reduction(double x, int x_exp, double &y) {
5151
// - When |x| >= 2^55, the LSB of double(x * THIRTYTWO_OVER_PI[0]) is at
5252
// least 2^6.
5353
fputil::FPBits<double> prod_hi(x * THIRTYTWO_OVER_PI[0]);
54-
prod_hi.bits &= (x_exp < 55) ? (~0xfffULL) : (~0ULL); // |x| < 2^55
54+
prod_hi.set_uintval(prod_hi.uintval() &
55+
((x_exp < 55) ? (~0xfffULL) : (~0ULL))); // |x| < 2^55
5556
double k_hi = fputil::nearest_integer(prod_hi.get_val());
5657
double truncated_prod = fputil::fma(x, THIRTYTWO_OVER_PI[0], -k_hi);
5758
double prod_lo = fputil::fma(x, THIRTYTWO_OVER_PI[1], truncated_prod);
@@ -70,7 +71,8 @@ LIBC_INLINE int64_t large_range_reduction(double x, int x_exp, double &y) {
7071
// - When |x| >= 2^110, the LSB of double(x * THIRTYTWO_OVER_PI[1]) is at
7172
// least 64.
7273
fputil::FPBits<double> prod_hi(x * THIRTYTWO_OVER_PI[1]);
73-
prod_hi.bits &= (x_exp < 110) ? (~0xfffULL) : (~0ULL); // |x| < 2^110
74+
prod_hi.set_uintval(prod_hi.uintval() &
75+
((x_exp < 110) ? (~0xfffULL) : (~0ULL))); // |x| < 2^110
7476
double k_hi = fputil::nearest_integer(prod_hi.get_val());
7577
double truncated_prod = fputil::fma(x, THIRTYTWO_OVER_PI[1], -k_hi);
7678
double prod_lo = fputil::fma(x, THIRTYTWO_OVER_PI[2], truncated_prod);

libc/test/src/math/atanhf_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) {
5050
EXPECT_MATH_ERRNO(ERANGE);
5151

5252
auto bt = FPBits(1.0f);
53-
bt.bits += 1;
53+
bt.set_uintval(bt.uintval() + 1);
5454

5555
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
5656
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(bt.get_val()));

libc/test/src/math/smoke/atanhf_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) {
4545
EXPECT_MATH_ERRNO(ERANGE);
4646

4747
auto bt = FPBits(1.0f);
48-
bt.bits += 1;
48+
bt.set_uintval(bt.uintval() + 1);
4949

5050
EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::atanhf(bt.get_val()),
5151
FE_INVALID);

libc/test/src/math/smoke/nan_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class LlvmLibcNanTest : public LIBC_NAMESPACE::testing::Test {
2020
double result = LIBC_NAMESPACE::nan(input_str);
2121
auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<double>(result);
2222
auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<double>(bits);
23-
EXPECT_EQ(actual_fp.bits, expected_fp.bits);
23+
EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval());
2424
};
2525
};
2626

libc/test/src/math/smoke/nanf_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class LlvmLibcNanfTest : public LIBC_NAMESPACE::testing::Test {
2020
float result = LIBC_NAMESPACE::nanf(input_str);
2121
auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<float>(result);
2222
auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<float>(bits);
23-
EXPECT_EQ(actual_fp.bits, expected_fp.bits);
23+
EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval());
2424
};
2525
};
2626

0 commit comments

Comments
 (0)