Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions libc/src/__support/CPP/string_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class string_view {

LIBC_INLINE static int compareMemory(const char *Lhs, const char *Rhs,
size_t Length) {
for (size_t I = 0; I < Length; ++I)
if (int Diff = (int)Lhs[I] - (int)Rhs[I])
for (size_t i = 0; i < Length; ++i)
if (int Diff = (int)Lhs[i] - (int)Rhs[i])
return Diff;
return 0;
}
Expand Down
6 changes: 3 additions & 3 deletions libc/src/__support/CPP/utility/in_place.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ template <class T> struct in_place_type_t {
};
template <class T> LIBC_INLINE_VAR constexpr in_place_type_t<T> in_place_type{};

template <size_t I> struct in_place_index_t {
template <size_t IDX> struct in_place_index_t {
LIBC_INLINE explicit in_place_index_t() = default;
};
template <size_t I>
LIBC_INLINE_VAR constexpr in_place_index_t<I> in_place_index{};
template <size_t IDX>
LIBC_INLINE_VAR constexpr in_place_index_t<IDX> in_place_index{};

} // namespace cpp
} // namespace LIBC_NAMESPACE_DECL
Expand Down
41 changes: 23 additions & 18 deletions libc/src/__support/FPUtil/NearestIntegerOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,13 +346,14 @@ fromfpx(T x, int rnd, unsigned int width) {

namespace internal {

template <typename F, typename I,
cpp::enable_if_t<cpp::is_floating_point_v<F> && cpp::is_integral_v<I>,
template <typename FloatType, typename IntType,
cpp::enable_if_t<cpp::is_floating_point_v<FloatType> &&
cpp::is_integral_v<IntType>,
int> = 0>
LIBC_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);
LIBC_INLINE IntType rounded_float_to_signed_integer(FloatType x) {
constexpr IntType INTEGER_MIN = (IntType(1) << (sizeof(IntType) * 8 - 1));
constexpr IntType INTEGER_MAX = -(INTEGER_MIN + 1);
FPBits<FloatType> bits(x);
auto set_domain_error_and_raise_invalid = []() {
set_errno_if_required(EDOM);
raise_except_if_required(FE_INVALID);
Expand All @@ -364,7 +365,7 @@ LIBC_INLINE I rounded_float_to_signed_integer(F x) {
}

int exponent = bits.get_exponent();
constexpr int EXPONENT_LIMIT = sizeof(I) * 8 - 1;
constexpr int EXPONENT_LIMIT = sizeof(IntType) * 8 - 1;
if (exponent > EXPONENT_LIMIT) {
set_domain_error_and_raise_invalid();
return bits.is_neg() ? INTEGER_MIN : INTEGER_MAX;
Expand All @@ -374,29 +375,33 @@ LIBC_INLINE I rounded_float_to_signed_integer(F x) {
return bits.is_neg() ? 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.
// value is the most negative number for the signed integer type IntType.
}

// For all other cases, if `x` can fit in the integer type `I`,
// For all other cases, if `x` can fit in the integer type `IntType`,
// we just return `x`. static_cast will convert the floating
// point value to the exact integer value.
return static_cast<I>(x);
return static_cast<IntType>(x);
}

} // namespace internal

template <typename F, typename I,
cpp::enable_if_t<cpp::is_floating_point_v<F> && cpp::is_integral_v<I>,
template <typename FloatType, typename IntType,
cpp::enable_if_t<cpp::is_floating_point_v<FloatType> &&
cpp::is_integral_v<IntType>,
int> = 0>
LIBC_INLINE I round_to_signed_integer(F x) {
return internal::rounded_float_to_signed_integer<F, I>(round(x));
LIBC_INLINE IntType round_to_signed_integer(FloatType x) {
return internal::rounded_float_to_signed_integer<FloatType, IntType>(
round(x));
}

template <typename F, typename I,
cpp::enable_if_t<cpp::is_floating_point_v<F> && cpp::is_integral_v<I>,
template <typename FloatType, typename IntType,
cpp::enable_if_t<cpp::is_floating_point_v<FloatType> &&
cpp::is_integral_v<IntType>,
int> = 0>
LIBC_INLINE I round_to_signed_integer_using_current_rounding_mode(F x) {
return internal::rounded_float_to_signed_integer<F, I>(
LIBC_INLINE IntType
round_to_signed_integer_using_current_rounding_mode(FloatType x) {
return internal::rounded_float_to_signed_integer<FloatType, IntType>(
round_using_current_rounding_mode(x));
}

Expand Down
83 changes: 42 additions & 41 deletions libc/test/src/math/RoundToIntegerTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ using LIBC_NAMESPACE::Sign;
static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
FE_TONEAREST};

template <typename F, typename I, bool TestModes = false>
template <typename F, typename OutType, bool TestModes = false>
class RoundToIntegerTestTemplate
: public LIBC_NAMESPACE::testing::FEnvSafeTest {
public:
typedef I (*RoundToIntegerFunc)(F);
typedef OutType (*RoundToIntegerFunc)(F);

private:
using FPBits = LIBC_NAMESPACE::fputil::FPBits<F>;
Expand All @@ -49,10 +49,11 @@ class RoundToIntegerTestTemplate
static constexpr StorageType MIN_SUBNORMAL =
FPBits::min_subnormal().uintval();

static constexpr I INTEGER_MIN = I(1) << (sizeof(I) * 8 - 1);
static constexpr I INTEGER_MAX = -(INTEGER_MIN + 1);
static constexpr OutType INTEGER_MIN = OutType(1)
<< (sizeof(OutType) * 8 - 1);
static constexpr OutType INTEGER_MAX = -(INTEGER_MIN + 1);

void test_one_input(RoundToIntegerFunc func, F input, I expected,
void test_one_input(RoundToIntegerFunc func, F input, OutType expected,
bool expectError) {
LIBC_NAMESPACE::libc_errno = 0;
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
Expand Down Expand Up @@ -120,24 +121,24 @@ class RoundToIntegerTestTemplate
}

void do_round_numbers_test(RoundToIntegerFunc func) {
test_one_input(func, zero, I(0), false);
test_one_input(func, neg_zero, I(0), false);
test_one_input(func, F(1.0), I(1), false);
test_one_input(func, F(-1.0), I(-1), false);
test_one_input(func, F(10.0), I(10), false);
test_one_input(func, F(-10.0), I(-10), false);
test_one_input(func, F(1234.0), I(1234), false);
test_one_input(func, F(-1234.0), I(-1234), false);
test_one_input(func, zero, OutType(0), false);
test_one_input(func, neg_zero, OutType(0), false);
test_one_input(func, F(1.0), OutType(1), false);
test_one_input(func, F(-1.0), OutType(-1), false);
test_one_input(func, F(10.0), OutType(10), false);
test_one_input(func, F(-10.0), OutType(-10), false);
test_one_input(func, F(1234.0), OutType(1234), false);
test_one_input(func, F(-1234.0), OutType(-1234), false);

// The rest of this function compares with an equivalent MPFR function
// which rounds floating point numbers to long values. There is no MPFR
// function to round to long long or wider integer values. So, we will
// the remaining tests only if the width of I less than equal to that of
// long.
if (sizeof(I) > sizeof(long))
// the remaining tests only if the width of OutType less than equal to that
// of long.
if (sizeof(OutType) > sizeof(long))
return;

constexpr int EXPONENT_LIMIT = sizeof(I) * 8 - 1;
constexpr int EXPONENT_LIMIT = sizeof(OutType) * 8 - 1;
constexpr int BIASED_EXPONENT_LIMIT = EXPONENT_LIMIT + FPBits::EXP_BIAS;
if (BIASED_EXPONENT_LIMIT > FPBits::MAX_BIASED_EXPONENT)
return;
Expand Down Expand Up @@ -179,7 +180,7 @@ class RoundToIntegerTestTemplate
else
erangeflag = mpfr::round_to_long(x, mpfr_long_result);
ASSERT_FALSE(erangeflag);
I mpfr_result = mpfr_long_result;
OutType mpfr_result = mpfr_long_result;
test_one_input(func, x, mpfr_result, false);
}
}
Expand All @@ -201,12 +202,12 @@ class RoundToIntegerTestTemplate
// This function compares with an equivalent MPFR function which rounds
// floating point numbers to long values. There is no MPFR function to
// round to long long or wider integer values. So, we will peform the
// comparisons in this function only if the width of I less than equal to
// that of long.
if (sizeof(I) > sizeof(long))
// comparisons in this function only if the width of OutType less than equal
// to that of long.
if (sizeof(OutType) > sizeof(long))
return;

constexpr int EXPONENT_LIMIT = sizeof(I) * 8 - 1;
constexpr int EXPONENT_LIMIT = sizeof(OutType) * 8 - 1;
constexpr int BIASED_EXPONENT_LIMIT = EXPONENT_LIMIT + FPBits::EXP_BIAS;
if (BIASED_EXPONENT_LIMIT > FPBits::MAX_BIASED_EXPONENT)
return;
Expand Down Expand Up @@ -248,22 +249,22 @@ class RoundToIntegerTestTemplate
if (TestModes) {
if (x > 0) {
LIBC_NAMESPACE::fputil::set_round(FE_UPWARD);
test_one_input(func, x, I(1), false);
test_one_input(func, x, OutType(1), false);
LIBC_NAMESPACE::fputil::set_round(FE_DOWNWARD);
test_one_input(func, x, I(0), false);
test_one_input(func, x, OutType(0), false);
LIBC_NAMESPACE::fputil::set_round(FE_TOWARDZERO);
test_one_input(func, x, I(0), false);
test_one_input(func, x, OutType(0), false);
LIBC_NAMESPACE::fputil::set_round(FE_TONEAREST);
test_one_input(func, x, I(0), false);
test_one_input(func, x, OutType(0), false);
} else {
LIBC_NAMESPACE::fputil::set_round(FE_UPWARD);
test_one_input(func, x, I(0), false);
test_one_input(func, x, OutType(0), false);
LIBC_NAMESPACE::fputil::set_round(FE_DOWNWARD);
test_one_input(func, x, I(-1), false);
test_one_input(func, x, OutType(-1), false);
LIBC_NAMESPACE::fputil::set_round(FE_TOWARDZERO);
test_one_input(func, x, I(0), false);
test_one_input(func, x, OutType(0), false);
LIBC_NAMESPACE::fputil::set_round(FE_TONEAREST);
test_one_input(func, x, I(0), false);
test_one_input(func, x, OutType(0), false);
}
} else {
test_one_input(func, x, 0L, false);
Expand All @@ -275,9 +276,9 @@ class RoundToIntegerTestTemplate
// This function compares with an equivalent MPFR function which rounds
// floating point numbers to long values. There is no MPFR function to
// round to long long or wider integer values. So, we will peform the
// comparisons in this function only if the width of I less than equal to
// that of long.
if (sizeof(I) > sizeof(long))
// comparisons in this function only if the width of OutType less than equal
// to that of long.
if (sizeof(OutType) > sizeof(long))
return;

constexpr int COUNT = 1'000'001;
Expand All @@ -297,7 +298,7 @@ class RoundToIntegerTestTemplate
long mpfr_long_result;
bool erangeflag = mpfr::round_to_long(x, to_mpfr_rounding_mode(m),
mpfr_long_result);
I mpfr_result = mpfr_long_result;
OutType mpfr_result = mpfr_long_result;
LIBC_NAMESPACE::fputil::set_round(m);
if (erangeflag)
test_one_input(func, x, x > 0 ? INTEGER_MAX : INTEGER_MIN, true);
Expand All @@ -307,7 +308,7 @@ class RoundToIntegerTestTemplate
} else {
long mpfr_long_result;
bool erangeflag = mpfr::round_to_long(x, mpfr_long_result);
I mpfr_result = mpfr_long_result;
OutType mpfr_result = mpfr_long_result;
if (erangeflag)
test_one_input(func, x, x > 0 ? INTEGER_MAX : INTEGER_MIN, true);
else
Expand All @@ -317,9 +318,9 @@ class RoundToIntegerTestTemplate
}
};

#define LIST_ROUND_TO_INTEGER_TESTS_HELPER(F, I, func, TestModes) \
#define LIST_ROUND_TO_INTEGER_TESTS_HELPER(F, OutType, func, TestModes) \
using LlvmLibcRoundToIntegerTest = \
RoundToIntegerTestTemplate<F, I, TestModes>; \
RoundToIntegerTestTemplate<F, OutType, TestModes>; \
TEST_F(LlvmLibcRoundToIntegerTest, InfinityAndNaN) { \
testInfinityAndNaN(&func); \
} \
Expand All @@ -335,10 +336,10 @@ class RoundToIntegerTestTemplate
} \
TEST_F(LlvmLibcRoundToIntegerTest, NormalRange) { testNormalRange(&func); }

#define LIST_ROUND_TO_INTEGER_TESTS(F, I, func) \
LIST_ROUND_TO_INTEGER_TESTS_HELPER(F, I, func, false)
#define LIST_ROUND_TO_INTEGER_TESTS(F, OutType, func) \
LIST_ROUND_TO_INTEGER_TESTS_HELPER(F, OutType, func, false)

#define LIST_ROUND_TO_INTEGER_TESTS_WITH_MODES(F, I, func) \
LIST_ROUND_TO_INTEGER_TESTS_HELPER(F, I, func, true)
#define LIST_ROUND_TO_INTEGER_TESTS_WITH_MODES(F, OutType, func) \
LIST_ROUND_TO_INTEGER_TESTS_HELPER(F, OutType, func, true)

#endif // LLVM_LIBC_TEST_SRC_MATH_ROUNDTOINTEGERTEST_H
Loading