Commit 50b18a3c authored by Victor Zverovich's avatar Victor Zverovich

Integrate Grisu

parent 69929752
...@@ -68,13 +68,13 @@ include(CheckCXXCompilerFlag) ...@@ -68,13 +68,13 @@ include(CheckCXXCompilerFlag)
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(PEDANTIC_COMPILE_FLAGS -pedantic-errors -Wall -Wextra -pedantic set(PEDANTIC_COMPILE_FLAGS -pedantic-errors -Wall -Wextra -pedantic
-Wold-style-cast -Wfloat-equal -Wlogical-op -Wundef -Wold-style-cast -Wlogical-op -Wundef
-Wredundant-decls -Wshadow -Wwrite-strings -Wpointer-arith -Wredundant-decls -Wshadow -Wwrite-strings -Wpointer-arith
-Wcast-qual -Wformat=2 -Wmissing-include-dirs -Wcast-qual -Wformat=2 -Wmissing-include-dirs
-Wcast-align -Wnon-virtual-dtor -Wcast-align -Wnon-virtual-dtor
-Wctor-dtor-privacy -Wdisabled-optimization -Wctor-dtor-privacy -Wdisabled-optimization
-Winvalid-pch -Woverloaded-virtual -Winvalid-pch -Woverloaded-virtual
-Wno-ctor-dtor-privacy -Wno-dangling-else -Wno-float-equal -Wno-ctor-dtor-privacy -Wno-dangling-else
-Wno-format-nonliteral -Wno-sign-conversion -Wno-shadow) -Wno-format-nonliteral -Wno-sign-conversion -Wno-shadow)
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnoexcept) set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnoexcept)
...@@ -93,7 +93,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") ...@@ -93,7 +93,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
endif () endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(PEDANTIC_COMPILE_FLAGS -Weverything -Wpedantic set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -Wpedantic
-Wno-weak-vtables -Wno-padded -Wno-gnu-statement-expression -Wno-weak-vtables -Wno-padded -Wno-gnu-statement-expression
-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-reserved-id-macro -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-reserved-id-macro
-Wno-global-constructors -Wno-disabled-macro-expansion -Wno-global-constructors -Wno-disabled-macro-expansion
......
This diff is collapsed.
...@@ -289,15 +289,20 @@ inline bool use_grisu() { ...@@ -289,15 +289,20 @@ inline bool use_grisu() {
return FMT_USE_GRISU && std::numeric_limits<double>::is_iec559; return FMT_USE_GRISU && std::numeric_limits<double>::is_iec559;
} }
struct grisu2_specs {
int precision;
char type;
uint_least8_t flags;
};
// Formats value using Grisu2 algorithm: // Formats value using Grisu2 algorithm:
// https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf
template <typename Double> template <typename Double>
FMT_API typename std::enable_if<sizeof(Double) == sizeof(uint64_t)>::type FMT_API typename std::enable_if<sizeof(Double) == sizeof(uint64_t), bool>::type
grisu2_format(Double value, char *buffer, size_t &size, char type, grisu2_format(Double value, char *buffer, size_t &size, grisu2_specs);
int precision, bool write_decimal_point);
template <typename Double> template <typename Double>
inline typename std::enable_if<sizeof(Double) != sizeof(uint64_t)>::type inline typename std::enable_if<sizeof(Double) != sizeof(uint64_t), bool>::type
grisu2_format(Double, char *, size_t &, char, int, bool) {} grisu2_format(Double, char *, size_t &, grisu2_specs) { return false; }
template <typename Allocator> template <typename Allocator>
typename Allocator::value_type *allocate(Allocator& alloc, std::size_t n) { typename Allocator::value_type *allocate(Allocator& alloc, std::size_t n) {
...@@ -1203,13 +1208,13 @@ struct align_spec : empty_spec { ...@@ -1203,13 +1208,13 @@ struct align_spec : empty_spec {
template <typename Char> template <typename Char>
class basic_format_specs : public align_spec { class basic_format_specs : public align_spec {
public: public:
unsigned flags_;
int precision_; int precision_;
uint_least8_t flags_;
char type_; char type_;
FMT_CONSTEXPR basic_format_specs( FMT_CONSTEXPR basic_format_specs(
unsigned width = 0, char type = 0, wchar_t fill = ' ') unsigned width = 0, char type = 0, wchar_t fill = ' ')
: align_spec(width, fill), flags_(0), precision_(-1), type_(type) {} : align_spec(width, fill), precision_(-1), flags_(0), type_(type) {}
FMT_CONSTEXPR bool flag(unsigned f) const { return (flags_ & f) != 0; } FMT_CONSTEXPR bool flag(unsigned f) const { return (flags_ & f) != 0; }
FMT_CONSTEXPR int precision() const { return precision_; } FMT_CONSTEXPR int precision() const { return precision_; }
...@@ -2881,16 +2886,23 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) { ...@@ -2881,16 +2886,23 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
memory_buffer buffer; memory_buffer buffer;
char type = static_cast<char>(spec.type()); char type = static_cast<char>(spec.type());
if (internal::const_check( bool use_grisu = internal::use_grisu() && sizeof(T) <= sizeof(double) &&
internal::use_grisu() && sizeof(T) <= sizeof(double)) && type != 'a' && type != 'A';
type != 'a' && type != 'A') { if (use_grisu) {
char buf[100]; // TODO: correct buffer size char buf[100]; // TODO: correct buffer size
size_t size = 0; size_t size = 0;
internal::grisu2_format(static_cast<double>(value), buf, size, type, auto gs = internal::grisu2_specs();
spec.precision(), spec.flag(HASH_FLAG)); gs.type = type;
FMT_ASSERT(size <= 100, "buffer overflow"); gs.precision = spec.precision();
buffer.append(buf, buf + size); // TODO: avoid extra copy gs.flags = spec.flags_;
} else { use_grisu = internal::grisu2_format(
static_cast<double>(value), buf, size, gs);
if (use_grisu) {
FMT_ASSERT(size <= 100, "buffer overflow");
buffer.append(buf, buf + size); // TODO: avoid extra copy
}
}
if (!use_grisu) {
format_specs normalized_spec(spec); format_specs normalized_spec(spec);
normalized_spec.type_ = handler.type; normalized_spec.type_ = handler.type;
write_double_sprintf(value, normalized_spec, buffer); write_double_sprintf(value, normalized_spec, buffer);
......
...@@ -104,7 +104,7 @@ TEST(FPTest, GetCachedPower) { ...@@ -104,7 +104,7 @@ TEST(FPTest, GetCachedPower) {
TEST(FPTest, Grisu2FormatCompilesWithNonIEEEDouble) { TEST(FPTest, Grisu2FormatCompilesWithNonIEEEDouble) {
size_t size = 0; size_t size = 0;
fmt::internal::grisu2_format(4.2f, FMT_NULL, size, 0, 0, false); grisu2_format(4.2f, FMT_NULL, size, fmt::internal::grisu2_specs());
} }
template <typename T> template <typename T>
......
...@@ -180,13 +180,8 @@ TEST(PrintfTest, HashFlag) { ...@@ -180,13 +180,8 @@ TEST(PrintfTest, HashFlag) {
safe_sprintf(buffer, "%#E", -42.0); safe_sprintf(buffer, "%#E", -42.0);
EXPECT_PRINTF(buffer, "%#E", -42.0); EXPECT_PRINTF(buffer, "%#E", -42.0);
if (fmt::internal::use_grisu()) { EXPECT_PRINTF("-42.0000", "%#g", -42.0);
EXPECT_PRINTF("-42.0", "%#g", -42.0); EXPECT_PRINTF("-42.0000", "%#G", -42.0);
EXPECT_PRINTF("-42.0", "%#G", -42.0);
} else {
EXPECT_PRINTF("-42.0000", "%#g", -42.0);
EXPECT_PRINTF("-42.0000", "%#G", -42.0);
}
safe_sprintf(buffer, "%#a", 16.0); safe_sprintf(buffer, "%#a", 16.0);
EXPECT_PRINTF(buffer, "%#a", 16.0); EXPECT_PRINTF(buffer, "%#a", 16.0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment