Make constexpr ceil

Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>
This commit is contained in:
Vladislav Shchapov 2023-05-24 00:27:40 +05:00 committed by Victor Zverovich
parent c684a06d51
commit 19b17618a9
2 changed files with 55 additions and 2 deletions

View File

@ -3317,6 +3317,26 @@ FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision,
format_hexfloat(static_cast<double>(value), precision, specs, buf); format_hexfloat(static_cast<double>(value), precision, specs, buf);
} }
template <typename Float> FMT_CONSTEXPR auto iceil(Float value) -> int {
auto min = (std::numeric_limits<int>::min)();
auto max = (std::numeric_limits<int>::max)();
ignore_unused(min, max);
FMT_ASSERT(value >= min && value <= max, "value not in int range");
if (is_constant_evaluated()) {
do {
auto mid = min + static_cast<int>((static_cast<unsigned>(max) -
static_cast<unsigned>(min)) /
2);
if (mid < value)
min = mid;
else
max = mid;
} while (min + 1 != max);
return max;
}
return static_cast<int>(std::ceil(value));
}
template <typename Float> template <typename Float>
FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs,
buffer<char>& buf) -> int { buffer<char>& buf) -> int {
@ -3347,8 +3367,7 @@ FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs,
// 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1). // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1).
// This is based on log10(value) == log2(value) / log2(10) and approximation // This is based on log10(value) == log2(value) / log2(10) and approximation
// of log2(value) by e + num_fraction_bits idea from double-conversion. // of log2(value) by e + num_fraction_bits idea from double-conversion.
exp = static_cast<int>( exp = iceil((f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10);
std::ceil((f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10));
dragon_flags = dragon::fixup; dragon_flags = dragon::fixup;
} else if (precision < 0) { } else if (precision < 0) {
// Use Dragonbox for the shortest format. // Use Dragonbox for the shortest format.

View File

@ -523,3 +523,37 @@ TEST(format_impl_test, to_utf8) {
EXPECT_EQ(s, u.str()); EXPECT_EQ(s, u.str());
EXPECT_EQ(s.size(), u.size()); EXPECT_EQ(s.size(), u.size());
} }
FMT_CONSTEXPR20 bool constexpr_iceil() {
for (double v : std::initializer_list<double>{
((std::numeric_limits<int>::min)() + 0.5),
-1.2,
-0.2,
0.0,
0.2,
1.2,
4.0,
((std::numeric_limits<int>::max)() - 0.5),
}) {
auto r = fmt::detail::iceil(v);
fmt::detail::ignore_unused(r);
}
return true;
}
TEST(format_impl_test, iceil) {
for (double v : std::initializer_list<double>{
((std::numeric_limits<int>::min)() + 0.5),
-1.2,
-0.2,
0.0,
0.2,
1.2,
4.0,
((std::numeric_limits<int>::max)() - 0.5),
}) {
EXPECT_EQ(fmt::detail::iceil(v), static_cast<int>(std::ceil(v)));
}
FMT_CONSTEXPR20 auto result = constexpr_iceil();
EXPECT_TRUE(result);
}