4747#include < fstream>
4848#include < iostream>
4949#include < string>
50+ #include < variant>
5051#include < vector>
5152
5253#if FROM_CHARS_SUPPORTED
@@ -58,38 +59,42 @@ concept arithmetic_float
5859 = std::is_same_v<T, float > || std::is_same_v<T, double >;
5960
6061template <arithmetic_float T>
61- void process (const std::vector<T> &lines) {
62+ void process (const std::vector<T> &lines, bool useDragon4, bool useErrol3 ) {
6263 using MantissaType = std::conditional_t <std::is_same_v<T, float >,
6364 uint32_t , uint64_t >;
6465 using IEEE754Type = std::conditional_t <std::is_same_v<T, float >,
6566 IEEE754f, IEEE754d>;
6667
6768 // No dragon4 implementation optimized for float instead of double ?
68- pretty_print (lines, " dragon4" , [](const std::vector<T> &lines) -> int {
69- int volume = 0 ;
70- for (const auto d : lines) {
71- uint64_t dmantissa;
72- int dexp;
73- const IEEE754Type fields = decode_ieee754 (d);
74- dragon4::Dragon4 (dmantissa, dexp, fields.mantissa , fields.exponent ,
75- true , true );
76- char buffer[100 ];
77- volume += to_chars (dmantissa, dexp, fields.sign , buffer);
78- }
79- return volume;
80- }, 10 );
69+ if (useDragon4) {
70+ pretty_print (lines, " dragon4" , [](const std::vector<T> &lines) -> int {
71+ int volume = 0 ;
72+ for (const auto d : lines) {
73+ uint64_t dmantissa;
74+ int dexp;
75+ const IEEE754Type fields = decode_ieee754 (d);
76+ dragon4::Dragon4 (dmantissa, dexp, fields.mantissa , fields.exponent ,
77+ true , true );
78+ char buffer[100 ];
79+ volume += to_chars (dmantissa, dexp, fields.sign , buffer);
80+ }
81+ return volume;
82+ }, 10 );
83+ }
8184
8285#ifdef ERROL_SUPPORTED
8386 // No errol3 implementation optimized for float instead of double ?
84- pretty_print (lines, " errol3" , [](const std::vector<T> &lines) -> int {
85- int volume = 0 ;
86- char buffer[100 ];
87- for (const auto d : lines) {
88- errol3_dtoa (d, buffer); // returns the exponent
89- volume += std::strlen (buffer);
90- }
91- return volume;
92- });
87+ if (useErrol3) {
88+ pretty_print (lines, " errol3" , [](const std::vector<T> &lines) -> int {
89+ int volume = 0 ;
90+ char buffer[100 ];
91+ for (const auto d : lines) {
92+ errol3_dtoa (d, buffer); // returns the exponent
93+ volume += std::strlen (buffer);
94+ }
95+ return volume;
96+ });
97+ }
9398#else
9499 std::cout << " # errol not supported" << std::endl;
95100#endif
@@ -263,11 +268,11 @@ void process(const std::vector<T> &lines) {
263268}
264269
265270template <typename T>
266- void fileload (const std::string &filename) {
271+ std::vector<T> fileload (const std::string &filename) {
267272 std::ifstream inputfile (filename);
268273 if (!inputfile) {
269274 std::cerr << " can't open " << filename << std::endl;
270- return ;
275+ return {} ;
271276 }
272277
273278 std::vector<T> lines;
@@ -284,11 +289,12 @@ void fileload(const std::string &filename) {
284289 }
285290 }
286291 std::cout << " # read " << lines.size () << " lines " << std::endl;
287- process ( lines) ;
292+ return lines;
288293}
289294
290295template <typename T>
291- void parse_random_numbers (size_t howmany, const std::string &random_model) {
296+ std::vector<T> get_random_numbers (size_t howmany,
297+ const std::string &random_model) {
292298 std::cout << " # parsing random numbers" << std::endl;
293299 std::vector<T> lines;
294300 auto g = get_generator_by_name<T>(random_model);
@@ -299,7 +305,7 @@ void parse_random_numbers(size_t howmany, const std::string &random_model) {
299305 const T line = g->new_float ();
300306 lines.push_back (line);
301307 }
302- process ( lines) ;
308+ return lines;
303309}
304310
305311cxxopts::Options
@@ -316,6 +322,10 @@ int main(int argc, char **argv) {
316322 cxxopts::value<std::string>()->default_value (" uniform" ))(
317323 " s,single" , " Use single precision instead of double." ,
318324 cxxopts::value<bool >()->default_value (" false" ))(
325+ " d,dragon" , " Enable dragon4 (current impl. triggers some asserts)" ,
326+ cxxopts::value<bool >()->default_value (" false" ))(
327+ " e,errol" , " Enable errol3 (current impl. returns invalid values, e.g., for 0)" ,
328+ cxxopts::value<bool >()->default_value (" false" ))(
319329 " h,help" , " Print usage." );
320330 const auto result = options.parse (argc, argv);
321331
@@ -324,28 +334,33 @@ int main(int argc, char **argv) {
324334 return EXIT_SUCCESS;
325335 }
326336
337+ const bool useDragon4 = result[" dragon" ].as <bool >();
338+ const bool useErrol3 = result[" errol" ].as <bool >();
339+
327340 const bool single = result[" single" ].as <bool >();
328341 std::cout << " number type: " << (single ? " binary32 (float)" : " binary64 (double)" ) << std::endl;
329342
343+ std::variant<std::vector<float >, std::vector<double >> numbers;
330344 const auto filename = result[" file" ].as <std::string>();
331345 if (filename.empty ()) {
332- if (single) {
333- parse_random_numbers<float >(result[" volume" ].as <size_t >(),
334- result[" model" ].as <std::string>());
335- } else {
336- parse_random_numbers<double >(result[" volume" ].as <size_t >(),
337- result[" model" ].as <std::string>());
338- }
346+ const auto volume = result[" volume" ].as <size_t >();
347+ const auto model = result[" model" ].as <std::string>();
348+ if (single)
349+ numbers = get_random_numbers<float >(volume, model);
350+ else
351+ numbers = get_random_numbers<double >(volume, model);
339352 std::cout << " # You can also provide a filename (with the -f flag):"
340353 " it should contain one string per line corresponding to a number"
341354 << std::endl;
342355 }
343356 else {
344357 if (single)
345- fileload<float >(filename);
358+ numbers = fileload<float >(filename);
346359 else
347- fileload<double >(filename);
360+ numbers = fileload<double >(filename);
348361 }
362+
363+ std::visit ([&](auto &&arg) { process (arg, useDragon4, useErrol3); }, numbers);
349364 } catch (const std::exception &e) {
350365 std::cout << " error parsing options: " << e.what () << std::endl;
351366 return EXIT_FAILURE;
0 commit comments