mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-27 06:35:37 +00:00
Parameterized fp on significand type
This commit is contained in:
parent
cf940ae82e
commit
4fcacea354
@ -223,18 +223,20 @@ template <typename Float> constexpr int num_significand_bits() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A floating-point number f * pow(2, e).
|
// A floating-point number f * pow(2, e).
|
||||||
struct fp {
|
template <typename F> struct basic_fp {
|
||||||
uint64_t f;
|
F f;
|
||||||
int e;
|
int e;
|
||||||
|
|
||||||
static constexpr const int num_significand_bits = bits<decltype(f)>::value;
|
static constexpr const int num_significand_bits = bits<F>::value;
|
||||||
|
|
||||||
constexpr fp() : f(0), e(0) {}
|
constexpr basic_fp() : f(0), e(0) {}
|
||||||
constexpr fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
|
constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
|
||||||
|
|
||||||
// Constructs fp from an IEEE754 floating-point number. It is a template to
|
// Constructs fp from an IEEE754 floating-point number. It is a template to
|
||||||
// prevent compile errors on systems where n is not IEEE754.
|
// prevent compile errors on systems where n is not IEEE754.
|
||||||
template <typename Float> explicit FMT_CONSTEXPR fp(Float n) { assign(n); }
|
template <typename Float> explicit FMT_CONSTEXPR basic_fp(Float n) {
|
||||||
|
assign(n);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Float>
|
template <typename Float>
|
||||||
using is_supported = bool_constant<std::numeric_limits<Float>::digits <= 64>;
|
using is_supported = bool_constant<std::numeric_limits<Float>::digits <= 64>;
|
||||||
@ -272,8 +274,11 @@ struct fp {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using fp = basic_fp<unsigned long long>;
|
||||||
|
|
||||||
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
|
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
|
||||||
template <int SHIFT = 0> FMT_CONSTEXPR fp normalize(fp value) {
|
template <int SHIFT = 0, typename F>
|
||||||
|
FMT_CONSTEXPR basic_fp<F> normalize(basic_fp<F> value) {
|
||||||
// Handle subnormals.
|
// Handle subnormals.
|
||||||
const uint64_t implicit_bit = 1ULL << num_significand_bits<double>();
|
const uint64_t implicit_bit = 1ULL << num_significand_bits<double>();
|
||||||
const auto shifted_implicit_bit = implicit_bit << SHIFT;
|
const auto shifted_implicit_bit = implicit_bit << SHIFT;
|
||||||
@ -289,7 +294,9 @@ template <int SHIFT = 0> FMT_CONSTEXPR fp normalize(fp value) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(fp x, fp y) { return x.f == y.f && x.e == y.e; }
|
template <typename F> inline bool operator==(basic_fp<F> x, basic_fp<F> y) {
|
||||||
|
return x.f == y.f && x.e == y.e;
|
||||||
|
}
|
||||||
|
|
||||||
// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
|
// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
|
||||||
FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
|
FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
|
||||||
|
@ -190,14 +190,14 @@ TEST(fp_test, get_cached_power) {
|
|||||||
using limits = std::numeric_limits<double>;
|
using limits = std::numeric_limits<double>;
|
||||||
for (auto exp = limits::min_exponent; exp <= limits::max_exponent; ++exp) {
|
for (auto exp = limits::min_exponent; exp <= limits::max_exponent; ++exp) {
|
||||||
int dec_exp = 0;
|
int dec_exp = 0;
|
||||||
auto fp = fmt::detail::get_cached_power(exp, dec_exp);
|
auto power = fmt::detail::get_cached_power(exp, dec_exp);
|
||||||
bigint exact, cache(fp.f);
|
bigint exact, cache(power.f);
|
||||||
if (dec_exp >= 0) {
|
if (dec_exp >= 0) {
|
||||||
exact.assign_pow10(dec_exp);
|
exact.assign_pow10(dec_exp);
|
||||||
if (fp.e <= 0)
|
if (power.e <= 0)
|
||||||
exact <<= -fp.e;
|
exact <<= -power.e;
|
||||||
else
|
else
|
||||||
cache <<= fp.e;
|
cache <<= power.e;
|
||||||
exact.align(cache);
|
exact.align(cache);
|
||||||
cache.align(exact);
|
cache.align(exact);
|
||||||
auto exact_str = fmt::format("{}", exact);
|
auto exact_str = fmt::format("{}", exact);
|
||||||
@ -211,9 +211,9 @@ TEST(fp_test, get_cached_power) {
|
|||||||
EXPECT_EQ(diff, 0);
|
EXPECT_EQ(diff, 0);
|
||||||
} else {
|
} else {
|
||||||
cache.assign_pow10(-dec_exp);
|
cache.assign_pow10(-dec_exp);
|
||||||
cache *= fp.f + 1; // Inexact check.
|
cache *= power.f + 1; // Inexact check.
|
||||||
exact.assign(1);
|
exact.assign(1);
|
||||||
exact <<= -fp.e;
|
exact <<= -power.e;
|
||||||
exact.align(cache);
|
exact.align(cache);
|
||||||
auto exact_str = fmt::format("{}", exact);
|
auto exact_str = fmt::format("{}", exact);
|
||||||
auto cache_str = fmt::format("{}", cache);
|
auto cache_str = fmt::format("{}", cache);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user