Skip to content

Commit b05ba23

Browse files
authored
[libc] Add next_toward_inf fo FPBits (#80654)
It is needed to provide correct rounding when building FPRep from greater precision representations.
1 parent 95403b4 commit b05ba23

File tree

4 files changed

+59
-0
lines changed

4 files changed

+59
-0
lines changed

libc/src/__support/FPUtil/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ add_header_library(
3131
libc.src.__support.common
3232
libc.src.__support.CPP.bit
3333
libc.src.__support.CPP.type_traits
34+
libc.src.__support.libc_assert
3435
libc.src.__support.macros.attributes
3536
libc.src.__support.macros.properties.float
3637
libc.src.__support.math_extras

libc/src/__support/FPUtil/FPBits.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "src/__support/CPP/type_traits.h"
1414
#include "src/__support/UInt128.h"
1515
#include "src/__support/common.h"
16+
#include "src/__support/libc_assert.h" // LIBC_ASSERT
1617
#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
1718
#include "src/__support/macros/properties/float.h" // LIBC_COMPILER_HAS_FLOAT128
1819
#include "src/__support/math_extras.h" // mask_trailing_ones
@@ -266,6 +267,18 @@ template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
266267
LIBC_INLINE constexpr operator Exponent() const {
267268
return Exponent(UP::value - EXP_BIAS);
268269
}
270+
271+
LIBC_INLINE constexpr BiasedExponent &operator++() {
272+
LIBC_ASSERT(*this != BiasedExponent(Exponent::INF()));
273+
++UP::value;
274+
return *this;
275+
}
276+
277+
LIBC_INLINE constexpr BiasedExponent &operator--() {
278+
LIBC_ASSERT(*this != BiasedExponent(Exponent::SUBNORMAL()));
279+
--UP::value;
280+
return *this;
281+
}
269282
};
270283

271284
// An opaque type to store a floating point significand.
@@ -370,6 +383,7 @@ struct FPRepSem : public FPStorage<fp_type> {
370383
protected:
371384
using typename UP::Exponent;
372385
using typename UP::Significand;
386+
using UP::bits;
373387
using UP::encode;
374388
using UP::exp_bits;
375389
using UP::exp_sig_bits;
@@ -435,6 +449,12 @@ struct FPRepSem : public FPStorage<fp_type> {
435449
LIBC_INLINE constexpr bool is_normal() const {
436450
return is_finite() && !is_subnormal();
437451
}
452+
LIBC_INLINE constexpr RetT next_toward_inf() const {
453+
if (is_finite())
454+
return RetT(bits + StorageType(1));
455+
return RetT(bits);
456+
}
457+
438458
// Returns the mantissa with the implicit bit set iff the current
439459
// value is a valid normal number.
440460
LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
@@ -551,6 +571,21 @@ struct FPRepSem<FPType::X86_Binary80, RetT>
551571
return false;
552572
return get_implicit_bit();
553573
}
574+
LIBC_INLINE constexpr RetT next_toward_inf() const {
575+
if (is_finite()) {
576+
if (exp_sig_bits() == max_normal().uintval()) {
577+
return inf(sign());
578+
} else if (exp_sig_bits() == max_subnormal().uintval()) {
579+
return min_normal(sign());
580+
} else if (sig_bits() == SIG_MASK) {
581+
return RetT(encode(sign(), ++biased_exponent(), Significand::ZERO()));
582+
} else {
583+
return RetT(bits + StorageType(1));
584+
}
585+
}
586+
return RetT(bits);
587+
}
588+
554589
LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
555590
return sig_bits();
556591
}
@@ -653,6 +688,7 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
653688
using UP::is_signaling_nan;
654689
using UP::is_subnormal;
655690
using UP::is_zero;
691+
using UP::next_toward_inf;
656692
using UP::sign;
657693
LIBC_INLINE constexpr bool is_inf_or_nan() const { return !is_finite(); }
658694
LIBC_INLINE constexpr bool is_neg() const { return sign().is_neg(); }

libc/test/src/__support/FPUtil/fpbits_test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,27 @@ TYPED_TEST(LlvmLibcFPBitsTest, Properties, FPTypes) {
306306
}
307307
}
308308

309+
#define ASSERT_SAME_REP(A, B) ASSERT_EQ(A.uintval(), B.uintval());
310+
311+
TYPED_TEST(LlvmLibcFPBitsTest, NextTowardInf, FPTypes) {
312+
struct {
313+
FP before, after;
314+
} TEST_CASES[] = {
315+
{FP::ZERO, FP::MIN_SUBNORMAL}, //
316+
{FP::MAX_SUBNORMAL, FP::MIN_NORMAL}, //
317+
{FP::MAX_NORMAL, FP::INF}, //
318+
{FP::INF, FP::INF}, //
319+
{FP::QUIET_NAN, FP::QUIET_NAN}, //
320+
{FP::SIGNALING_NAN, FP::SIGNALING_NAN}, //
321+
};
322+
for (Sign sign : all_signs) {
323+
for (auto tc : TEST_CASES) {
324+
T val = make<T>(sign, tc.before);
325+
ASSERT_SAME_REP(val.next_toward_inf(), make<T>(sign, tc.after));
326+
}
327+
}
328+
}
329+
309330
TEST(LlvmLibcFPBitsTest, FloatType) {
310331
using FloatBits = FPBits<float>;
311332

utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,7 @@ libc_support_library(
666666
":__support_common",
667667
":__support_cpp_bit",
668668
":__support_cpp_type_traits",
669+
":__support_libc_assert",
669670
":__support_macros_attributes",
670671
":__support_macros_properties_float",
671672
":__support_math_extras",

0 commit comments

Comments
 (0)