Enable grisu for general format

This commit is contained in:
Victor Zverovich 2019-03-16 12:17:35 -07:00
parent c21c6b8c4b
commit 76d326a2a2
4 changed files with 18 additions and 14 deletions

View File

@ -645,7 +645,7 @@ FMT_FUNC bool grisu2_format(Double value, buffer& buf, int precision,
bool fixed, int& exp) { bool fixed, int& exp) {
FMT_ASSERT(value >= 0, "value is negative"); FMT_ASSERT(value >= 0, "value is negative");
if (value <= 0) { // <= instead of == to silence a warning. if (value <= 0) { // <= instead of == to silence a warning.
if (precision < 0) { if (precision < 0 || !fixed) {
exp = 0; exp = 0;
buf.push_back('0'); buf.push_back('0');
} else { } else {

View File

@ -1161,7 +1161,7 @@ template <typename Char, typename It> It write_exponent(int exp, It it) {
*it++ = static_cast<Char>(d[1]); *it++ = static_cast<Char>(d[1]);
} else { } else {
const char* d = data::DIGITS + exp * 2; const char* d = data::DIGITS + exp * 2;
if (d[0] != '0') *it++ = static_cast<Char>(d[0]); *it++ = static_cast<Char>(d[0]);
*it++ = static_cast<Char>(d[1]); *it++ = static_cast<Char>(d[1]);
} }
return it; return it;
@ -1198,12 +1198,14 @@ It grisu2_prettify(const char* digits, int size, int exp, It it,
// 1234e-2 -> 12.34[0+] // 1234e-2 -> 12.34[0+]
it = copy_str<Char>(digits, digits + full_exp, it); it = copy_str<Char>(digits, digits + full_exp, it);
*it++ = static_cast<Char>('.'); *it++ = static_cast<Char>('.');
it = copy_str<Char>(digits + full_exp, digits + size, it);
if (!params.trailing_zeros) { if (!params.trailing_zeros) {
// Remove trailing zeros. // Remove trailing zeros.
// TODO while (size > full_exp && digits[size - 1] == '0')
// handler.remove_trailing('0'); --size;
} else if (params.num_digits > size) { return copy_str<Char>(digits + full_exp, digits + size, it);
}
it = copy_str<Char>(digits + full_exp, digits + size, it);
if (params.num_digits > size) {
// Add trailing zeros. // Add trailing zeros.
int num_zeros = params.num_digits - size; int num_zeros = params.num_digits - size;
it = std::fill_n(it, num_zeros, static_cast<Char>('0')); it = std::fill_n(it, num_zeros, static_cast<Char>('0'));
@ -2668,8 +2670,9 @@ template <typename Range> class basic_writer {
const internal::gen_digits_params& params) const internal::gen_digits_params& params)
: digits_(digits), sign_(sign), exp_(exp), params_(params) { : digits_(digits), sign_(sign), exp_(exp), params_(params) {
int num_digits = static_cast<int>(digits.size()); int num_digits = static_cast<int>(digits.size());
int full_exp = num_digits + exp; int full_exp = num_digits + exp - 1;
params_.fixed |= (full_exp - 1) >= -4 && (full_exp - 1) <= 10; int precision = params.num_digits > 0 ? params.num_digits : 11;
params_.fixed |= full_exp >= -4 && full_exp < precision;
auto it = internal::grisu2_prettify<char>( auto it = internal::grisu2_prettify<char>(
digits.data(), num_digits, exp, internal::counting_iterator<char>(), digits.data(), num_digits, exp, internal::counting_iterator<char>(),
params_); params_);
@ -2869,7 +2872,8 @@ void basic_writer<Range>::write_double(T value, const format_specs& spec) {
int exp = 0; int exp = 0;
int precision = spec.has_precision() || !spec.type ? spec.precision : 6; int precision = spec.has_precision() || !spec.type ? spec.precision : 6;
bool use_grisu = fmt::internal::use_grisu<T>() && bool use_grisu = fmt::internal::use_grisu<T>() &&
(!spec.type || handler.fixed) && (spec.type != 'a' && spec.type != 'A' &&
spec.type != 'e' && spec.type != 'E') &&
internal::grisu2_format(static_cast<double>(value), buffer, internal::grisu2_format(static_cast<double>(value), buffer,
precision, handler.fixed, exp); precision, handler.fixed, exp);
if (!use_grisu) internal::sprintf_format(value, buffer, spec); if (!use_grisu) internal::sprintf_format(value, buffer, spec);
@ -2894,7 +2898,8 @@ void basic_writer<Range>::write_double(T value, const format_specs& spec) {
auto params = internal::gen_digits_params(); auto params = internal::gen_digits_params();
params.fixed = handler.fixed; params.fixed = handler.fixed;
params.num_digits = precision; params.num_digits = precision;
if (precision != 0) params.trailing_zeros = true; params.trailing_zeros =
(precision != 0 && (handler.fixed || !spec.type)) || spec.has(HASH_FLAG);
write_padded(as, grisu_writer{sign, buffer, exp, params}); write_padded(as, grisu_writer{sign, buffer, exp, params});
} else { } else {
write_padded(as, double_writer{sign, buffer}); write_padded(as, double_writer{sign, buffer});

View File

@ -44,8 +44,8 @@ TEST(GrisuTest, Round) {
TEST(GrisuTest, Prettify) { TEST(GrisuTest, Prettify) {
EXPECT_EQ("0.0001", fmt::format("{}", 1e-4)); EXPECT_EQ("0.0001", fmt::format("{}", 1e-4));
EXPECT_EQ("1e-5", fmt::format("{}", 1e-5)); EXPECT_EQ("1e-05", fmt::format("{}", 1e-5));
EXPECT_EQ("9.999e-5", fmt::format("{}", 9.999e-5)); EXPECT_EQ("9.999e-05", fmt::format("{}", 9.999e-5));
EXPECT_EQ("10000000000.0", fmt::format("{}", 1e10)); EXPECT_EQ("10000000000.0", fmt::format("{}", 1e10));
EXPECT_EQ("1e+11", fmt::format("{}", 1e11)); EXPECT_EQ("1e+11", fmt::format("{}", 1e11));
EXPECT_EQ("12340000000.0", fmt::format("{}", 1234e7)); EXPECT_EQ("12340000000.0", fmt::format("{}", 1234e7));

View File

@ -252,8 +252,7 @@ TEST(PrintfTest, FloatPrecision) {
safe_sprintf(buffer, "%.3e", 1234.5678); safe_sprintf(buffer, "%.3e", 1234.5678);
EXPECT_PRINTF(buffer, "%.3e", 1234.5678); EXPECT_PRINTF(buffer, "%.3e", 1234.5678);
EXPECT_PRINTF("1234.568", "%.3f", 1234.5678); EXPECT_PRINTF("1234.568", "%.3f", 1234.5678);
safe_sprintf(buffer, "%.3g", 1234.5678); EXPECT_PRINTF("1.23e+03", "%.3g", 1234.5678);
EXPECT_PRINTF(buffer, "%.3g", 1234.5678);
safe_sprintf(buffer, "%.3a", 1234.5678); safe_sprintf(buffer, "%.3a", 1234.5678);
EXPECT_PRINTF(buffer, "%.3a", 1234.5678); EXPECT_PRINTF(buffer, "%.3a", 1234.5678);
} }