1919#include " double-conversion/double-conversion.h"
2020#include " grisu_exact.h"
2121#include " dragon4.h"
22+ #include " schubfach_32.h"
2223#include " schubfach_64.h"
24+
2325#if __has_include("errol.h")
2426#include " errol.h"
25- #define ERROL_SUPPORTED 1
26- #else
27- #define ERROL_SUPPORTED 0
27+ #define ERROL_SUPPORTED
2828#endif
2929
3030#define IEEE_8087
3939#include " random_generators.h"
4040#include " ieeeToString.h"
4141
42- #include < charconv>
42+ #include < fmt/format.h>
43+
4344#include < climits>
4445#include < cmath>
4546#include < cstdio>
46- #include < cstdlib>
47- #include < cstring>
48- #include < float.h>
49- #include < fmt/format.h>
5047#include < fstream>
5148#include < iostream>
52- #include < limits.h>
53- #include < stdio.h>
5449#include < string>
5550#include < vector>
5651
57- #if FROM_CHARS_DOUBLE_SUPPORTED
52+ #if FROM_CHARS_SUPPORTED
5853#include < charconv>
5954#endif
6055
6156template <typename T>
6257void process (const std::vector<T> &lines) {
63- pretty_print (lines, " dragon4" , [](const std::vector<T> &lines) -> T {
64- T volume = 0 ;
58+ static_assert (std::is_same_v<T, float > || std::is_same_v<T, double >,
59+ " The function currently only supports float or double" );
60+ using MantissaType = std::conditional_t <std::is_same_v<T, float >,
61+ uint32_t , uint64_t >;
62+ using IEEE754Type = std::conditional_t <std::is_same_v<T, float >,
63+ IEEE754f, IEEE754d>;
64+
65+ // No dragon4 implementation optimized for float instead of double ?
66+ pretty_print (lines, " dragon4" , [](const std::vector<T> &lines) -> int {
67+ int volume = 0 ;
6568 for (const auto d : lines) {
66- uint64_t dmantissa;
69+ MantissaType dmantissa;
6770 int dexp;
68- const IEEE754d fields = decode_ieee754 (d);
71+ const IEEE754Type fields = decode_ieee754 (d);
6972 dragon4::Dragon4 (dmantissa, dexp, fields.mantissa , fields.exponent ,
7073 true , true );
7174 char buffer[100 ];
7275 volume += to_chars (dmantissa, dexp, fields.sign , buffer);
7376 }
7477 return volume;
75- });
78+ }, 10 );
7679
77- #if ERROL_SUPPORTED
78- pretty_print (lines, " errol3" , [](const std::vector<double > &lines) {
79- double volume = 0 ;
80+ #ifdef ERROL_SUPPORTED
81+ // No errol3 implementation optimized for float instead of double ?
82+ pretty_print (lines, " errol3" , [](const std::vector<T> &lines) -> int {
83+ int volume = 0 ;
8084 char buffer[100 ];
8185 for (const auto d : lines) {
82- errol3_dtoa (d, buffer); // returns the exponent?
86+ errol3_dtoa (d, buffer); // returns the exponent
8387 volume += std::strlen (buffer);
8488 }
8589 return volume;
8690 });
8791#else
8892 std::cout << " # errol not supported" << std::endl;
89- #endif // ERROL_SUPPORTED
93+ #endif
9094
91- pretty_print (lines, " std::to_string" , [](const std::vector<T> &lines) -> T {
92- T volume = 0 ;
95+ pretty_print (lines, " std::to_string" , [](const std::vector<T> &lines) -> int {
96+ int volume = 0 ;
9397 for (const auto d : lines) {
9498 const std::string s = std::to_string (d);
9599 volume += s.size ();
96100 }
97101 return volume;
98102 });
99103
100- pretty_print (lines, " fmt::format" , [](const std::vector<T> &lines) -> T {
101- T volume = 0 ;
104+ pretty_print (lines, " fmt::format" , [](const std::vector<T> &lines) -> int {
105+ int volume = 0 ;
102106 for (const auto d : lines) {
103107 const std::string s = fmt::format (" {}" , d);
104108 volume += s.size ();
@@ -107,8 +111,9 @@ void process(const std::vector<T> &lines) {
107111 });
108112
109113#if NETLIB_SUPPORTED
110- pretty_print (lines, " netlib" , [](const std::vector<T> &lines) -> T {
111- T volume = 0 ;
114+ // There's no "ftoa", only "dtoa", so not optimized for float.
115+ pretty_print (lines, " netlib" , [](const std::vector<T> &lines) -> int {
116+ int volume = 0 ;
112117 char *result;
113118 int decpt, sign;
114119 char *rve;
@@ -128,17 +133,19 @@ void process(const std::vector<T> &lines) {
128133 std::cout << " # netlib not supported" << std::endl;
129134#endif
130135
131- pretty_print (lines, " sprintf" , [](const std::vector<T> &lines) -> T {
132- T volume = 0 ;
136+ pretty_print (lines, " sprintf" , [](const std::vector<T> &lines) -> int {
137+ int volume = 0 ;
133138 char buffer[100 ];
134139 for (const auto d : lines) {
135140 volume += snprintf (buffer, sizeof (buffer), " %g" , d);
136141 }
137142 return volume;
138143 });
139144
140- pretty_print (lines, " grisu2" , [](const std::vector<T> &lines) -> T {
141- T volume = 0 ;
145+ // grisu2::dtoa_impl::grisu2 can take a template type
146+ // However, grisu2::to_chars is hardcoded for double.
147+ pretty_print (lines, " grisu2" , [](const std::vector<T> &lines) -> int {
148+ int volume = 0 ;
142149 char buffer[100 ];
143150 for (const auto d : lines) {
144151 const char *newp = grisu2::to_chars (buffer, nullptr , d);
@@ -147,8 +154,8 @@ void process(const std::vector<T> &lines) {
147154 return volume;
148155 });
149156
150- pretty_print (lines, " grisu_exact" , [](const std::vector<T> &lines) -> T {
151- T volume = 0 ;
157+ pretty_print (lines, " grisu_exact" , [](const std::vector<T> &lines) -> int {
158+ int volume = 0 ;
152159 char buffer[100 ];
153160 for (const auto d : lines) {
154161 auto v = jkj::grisu_exact (d);
@@ -157,54 +164,20 @@ void process(const std::vector<T> &lines) {
157164 return volume;
158165 });
159166
160- #if FROM_CHARS_DOUBLE_SUPPORTED
161- pretty_print (lines, " std::to_chars" , [](const std::vector<double > &lines) {
162- double volume = 0 ;
167+ pretty_print (lines, " schubfach" , [](const std::vector<T> &lines) -> int {
168+ int volume = 0 ;
163169 char buffer[100 ];
164170 for (const auto d : lines) {
165- const auto [p, ec] = std::to_chars (buffer, buffer + sizeof (buffer), d);
166- if (ec != std::errc ()) {
167- std::cerr << " problem with " << d << std::endl;
168- std::abort ();
169- }
170- volume += p - buffer;
171- }
172- return volume;
173- });
174- #else
175- std::cout << " # std::to_chars not supported" << std::endl;
176- #endif
177-
178- #if FROM_CHARS_DOUBLE_SUPPORTED
179- pretty_print (lines, " std::to_chars" , [](const std::vector<T> &lines) -> T {
180- T volume = 0 ;
181- char buffer[100 ];
182- for (const auto d : lines) {
183- const auto [p, ec] = std::to_chars (buffer, buffer + sizeof (buffer), d);
184- if (ec != std::errc ()) {
185- std::cerr << " problem with " << d << std::endl;
186- std::abort ();
187- }
188- volume += p - buffer;
189- }
190- return volume;
191- });
192- #else
193- std::cout << " # std::to_chars not supported" << std::endl;
194- #endif
195-
196- pretty_print (lines, " schubfach" , [](const std::vector<T> &lines) -> T {
197- T volume = 0 ;
198- char buffer[100 ];
199- for (const auto d : lines) {
200- const char *end_ptr = schubfach::Dtoa (buffer, d);
171+ const char * end_ptr = std::is_same_v<T, float >
172+ ? schubfach::Ftoa (buffer, d)
173+ : schubfach::Dtoa (buffer, d);
201174 volume += end_ptr - &buffer[0 ];
202175 }
203176 return volume;
204177 });
205178
206- pretty_print (lines, " dragonbox" , [](const std::vector<T> &lines) -> T {
207- T volume = 0 ;
179+ pretty_print (lines, " dragonbox" , [](const std::vector<T> &lines) -> int {
180+ int volume = 0 ;
208181 char buffer[100 ];
209182 for (const auto d : lines) {
210183 const char *end_ptr = jkj::dragonbox::to_chars (d, buffer);
@@ -213,38 +186,42 @@ void process(const std::vector<T> &lines) {
213186 return volume;
214187 });
215188
216- pretty_print (lines, " ryu" , [](const std::vector<T> &lines) -> T {
217- T volume = 0 ;
189+ pretty_print (lines, " ryu" , [](const std::vector<T> &lines) -> int {
190+ int volume = 0 ;
218191 char buffer[100 ];
219192 for (const auto d : lines) {
220- volume += d2s_buffered_n (d, buffer);
193+ volume += std::is_same_v<T, float > ? f2s_buffered_n (d, buffer)
194+ : d2s_buffered_n (d, buffer);
221195 }
222196 return volume;
223197 });
224198
225- pretty_print (lines, " teju_jagua" , [](const std::vector<T> &lines) -> T {
226- T volume = 0 ;
199+ pretty_print (lines, " teju_jagua" , [](const std::vector<T> &lines) -> int {
200+ int volume = 0 ;
227201 char buffer[100 ];
228202 for (const auto d : lines) {
229- const auto fields = teju::traits_t <double >::teju (d);
230- const bool sign = (* reinterpret_cast < const uint64_t *>(&d) >> 63 ) & 1 ;
203+ const auto fields = teju::traits_t <T >::teju (d);
204+ const bool sign = std::signbit (d) ;
231205 volume += to_chars (fields.mantissa , fields.exponent , sign, buffer);
232206 }
233207 return volume;
234208 });
235209
236- pretty_print (lines, " double_conversion" , [](const std::vector<T> &lines) -> T {
237- T volume = 0 ;
210+ pretty_print (lines, " double_conversion" , [](const std::vector<T> &lines) -> int {
211+ int volume = 0 ;
212+ constexpr int kBufferSize = 100 ;
213+ char buffer[kBufferSize ];
238214 const double_conversion::DoubleToStringConverter converter (
239215 double_conversion::DoubleToStringConverter::NO_FLAGS, " inf" , " nan" , ' e' ,
240216 -4 , 6 , 0 , 0 );
241- const int kBufferSize = 100 ;
242- char buffer[kBufferSize ];
243217 double_conversion::StringBuilder builder (buffer, kBufferSize );
244218
245219 for (const auto d : lines) {
246220 builder.Reset ();
247- if (!converter.ToShortest (d, &builder)) {
221+ const bool valid = std::is_same_v<T, float >
222+ ? converter.ToShortestSingle (d, &builder)
223+ : converter.ToShortest (d, &builder);
224+ if (!valid) {
248225 std::cerr << " problem with " << d << std::endl;
249226 std::abort ();
250227 }
@@ -253,8 +230,8 @@ void process(const std::vector<T> &lines) {
253230 return volume;
254231 });
255232
256- pretty_print (lines, " abseil" , [](const std::vector<T> &lines) -> T {
257- T volume = 0 ;
233+ pretty_print (lines, " abseil" , [](const std::vector<T> &lines) -> int {
234+ int volume = 0 ;
258235 std::string buffer;
259236 for (const auto d : lines) {
260237 buffer.clear ();
@@ -264,10 +241,9 @@ void process(const std::vector<T> &lines) {
264241 return volume;
265242 });
266243
267-
268- #if FROM_CHARS_DOUBLE_SUPPORTED
269- pretty_print (lines, " std::to_chars" , [](const std::vector<double > &lines) {
270- double volume = 0 ;
244+ #if FROM_CHARS_SUPPORTED
245+ pretty_print (lines, " std::to_chars" , [](const std::vector<T> &lines) -> int {
246+ int volume = 0 ;
271247 char buffer[100 ];
272248 for (const auto d : lines) {
273249 const auto [p, ec] = std::to_chars (buffer, buffer + sizeof (buffer), d);
@@ -282,7 +258,6 @@ void process(const std::vector<T> &lines) {
282258#else
283259 std::cout << " # std::to_chars not supported" << std::endl;
284260#endif
285-
286261}
287262
288263void fileload (const char *filename) {
0 commit comments