mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-31 11:17:35 +02:00
Implement left shift
This commit is contained in:
@ -398,13 +398,14 @@ class fp {
|
|||||||
// 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> friend fp normalize(fp value) {
|
template <int SHIFT> friend fp normalize(fp value) {
|
||||||
// Handle subnormals.
|
// Handle subnormals.
|
||||||
const auto shifted_implicit_bit = implicit_bit << SHIFT;
|
const auto shifted_implicit_bit = fp::implicit_bit << SHIFT;
|
||||||
while ((value.f & shifted_implicit_bit) == 0) {
|
while ((value.f & shifted_implicit_bit) == 0) {
|
||||||
value.f <<= 1;
|
value.f <<= 1;
|
||||||
--value.e;
|
--value.e;
|
||||||
}
|
}
|
||||||
// Subtract 1 to account for hidden bit.
|
// Subtract 1 to account for hidden bit.
|
||||||
const auto offset = significand_size - double_significand_size - SHIFT - 1;
|
const auto offset =
|
||||||
|
fp::significand_size - fp::double_significand_size - SHIFT - 1;
|
||||||
value.f <<= offset;
|
value.f <<= offset;
|
||||||
value.e -= offset;
|
value.e -= offset;
|
||||||
return value;
|
return value;
|
||||||
@ -490,6 +491,18 @@ class bigint {
|
|||||||
|
|
||||||
bigint(const bigint&) = delete;
|
bigint(const bigint&) = delete;
|
||||||
void operator=(const bigint&) = delete;
|
void operator=(const bigint&) = delete;
|
||||||
|
|
||||||
|
bigint& operator<<=(int shift) {
|
||||||
|
assert(shift >= 0 && shift < bigit_bits);
|
||||||
|
bigit carry = 0;
|
||||||
|
for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
|
||||||
|
bigit c = shift != 0 ? bigits_[i] >> (bigit_bits - shift) : 0;
|
||||||
|
bigits_[i] = (bigits_[i] << shift) + carry;
|
||||||
|
carry = c;
|
||||||
|
}
|
||||||
|
if (carry != 0) bigits_.push_back(carry);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum round_direction { unknown, up, down };
|
enum round_direction { unknown, up, down };
|
||||||
@ -712,6 +725,10 @@ template <int GRISU_VERSION> struct grisu_shortest_handler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FMT_API void fallback_format(const fp& value) {
|
||||||
|
(void)value; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Double,
|
template <typename Double,
|
||||||
enable_if_t<(sizeof(Double) == sizeof(uint64_t)), int>>
|
enable_if_t<(sizeof(Double) == sizeof(uint64_t)), int>>
|
||||||
FMT_API bool grisu_format(Double value, buffer<char>& buf, int precision,
|
FMT_API bool grisu_format(Double value, buffer<char>& buf, int precision,
|
||||||
@ -765,13 +782,13 @@ FMT_API bool grisu_format(Double value, buffer<char>& buf, int precision,
|
|||||||
result = grisu_gen_digits(upper, upper.f - lower.f, exp, handler);
|
result = grisu_gen_digits(upper, upper.f - lower.f, exp, handler);
|
||||||
size = handler.size;
|
size = handler.size;
|
||||||
if (result == digits::error) {
|
if (result == digits::error) {
|
||||||
// TODO: use fallback
|
fallback_format(fp_value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
++lower.f; // \tilde{M}^- + 1 ulp -> M^-_{\uparrow}.
|
++lower.f; // \tilde{M}^- + 1 ulp -> M^-_{\uparrow}.
|
||||||
--upper.f; // \tilde{M}^+ - 1 ulp -> M^+_{\downarrow}.
|
--upper.f; // \tilde{M}^+ - 1 ulp -> M^+_{\downarrow}.
|
||||||
grisu_shortest_handler<2> handler{buf.data(), 0, (upper - fp_value).f};
|
grisu_shortest_handler<2> handler{buf.data(), 0, (upper - normalized).f};
|
||||||
result = grisu_gen_digits(upper, upper.f - lower.f, exp, handler);
|
result = grisu_gen_digits(upper, upper.f - lower.f, exp, handler);
|
||||||
size = handler.size;
|
size = handler.size;
|
||||||
assert(result != digits::error);
|
assert(result != digits::error);
|
||||||
|
@ -33,6 +33,16 @@ TEST(BigIntTest, Construct) {
|
|||||||
EXPECT_EQ("123456789abcedf0", fmt::format("{}", bigint(0x123456789abcedf0)));
|
EXPECT_EQ("123456789abcedf0", fmt::format("{}", bigint(0x123456789abcedf0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(BigIntTest, ShiftLeft) {
|
||||||
|
bigint n(0x42);
|
||||||
|
n <<= 0;
|
||||||
|
EXPECT_EQ("42", fmt::format("{}", n));
|
||||||
|
n <<= 1;
|
||||||
|
EXPECT_EQ("84", fmt::format("{}", n));
|
||||||
|
n <<= 25;
|
||||||
|
EXPECT_EQ("108000000", fmt::format("{}", n));
|
||||||
|
}
|
||||||
|
|
||||||
template <bool is_iec559> void test_construct_from_double() {
|
template <bool is_iec559> void test_construct_from_double() {
|
||||||
fmt::print("warning: double is not IEC559, skipping FP tests\n");
|
fmt::print("warning: double is not IEC559, skipping FP tests\n");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user