mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
We need to update some of our exhaustive tests to the new API
This commit is contained in:
parent
843fb97064
commit
ca43e6722e
2
.github/workflows/ubuntu22-clang.yml
vendored
2
.github/workflows/ubuntu22-clang.yml
vendored
@ -22,4 +22,4 @@ jobs:
|
|||||||
cd build20 &&
|
cd build20 &&
|
||||||
CXX=clang++-14 cmake -DFASTFLOAT_CONSTEXPR_TESTS=ON -DCMAKE_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON .. &&
|
CXX=clang++-14 cmake -DFASTFLOAT_CONSTEXPR_TESTS=ON -DCMAKE_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest --output-on-failure
|
ctest --output-on-failure
|
||||||
2
.github/workflows/ubuntu22-gcc12.yml
vendored
2
.github/workflows/ubuntu22-gcc12.yml
vendored
@ -20,4 +20,4 @@ jobs:
|
|||||||
cd build20 &&
|
cd build20 &&
|
||||||
CXX=g++-12 CXXFLAGS=-Werror cmake -DFASTFLOAT_CONSTEXPR_TESTS=ON -DCMAKE_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON .. &&
|
CXX=g++-12 CXXFLAGS=-Werror cmake -DFASTFLOAT_CONSTEXPR_TESTS=ON -DCMAKE_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest --output-on-failure
|
ctest --output-on-failure
|
||||||
2
.github/workflows/ubuntu22.yml
vendored
2
.github/workflows/ubuntu22.yml
vendored
@ -13,4 +13,4 @@ jobs:
|
|||||||
cd build &&
|
cd build &&
|
||||||
cmake -DFASTFLOAT_TEST=ON .. &&
|
cmake -DFASTFLOAT_TEST=ON .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest --output-on-failure
|
ctest --output-on-failure
|
||||||
10
README.md
10
README.md
@ -189,11 +189,11 @@ It can parse random floating-point numbers at a speed of 1 GB/s on some systems.
|
|||||||
$ ./build/benchmarks/benchmark
|
$ ./build/benchmarks/benchmark
|
||||||
# parsing random integers in the range [0,1)
|
# parsing random integers in the range [0,1)
|
||||||
volume = 2.09808 MB
|
volume = 2.09808 MB
|
||||||
netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
|
netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
|
||||||
doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
|
doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
|
||||||
strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
|
strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
|
||||||
abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
|
abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
|
||||||
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
|
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
|
||||||
```
|
```
|
||||||
|
|
||||||
See https://github.com/lemire/simple_fastfloat_benchmark for our benchmarking code.
|
See https://github.com/lemire/simple_fastfloat_benchmark for our benchmarking code.
|
||||||
|
|||||||
@ -48,9 +48,9 @@ namespace detail {
|
|||||||
* where
|
* where
|
||||||
* p = log(5**q)/log(2) = q * log(5)/log(2)
|
* p = log(5**q)/log(2) = q * log(5)/log(2)
|
||||||
*
|
*
|
||||||
* For negative values of q in (-400,0), we have that
|
* For negative values of q in (-400,0), we have that
|
||||||
* f = (((152170 + 65536) * q ) >> 16);
|
* f = (((152170 + 65536) * q ) >> 16);
|
||||||
* is equal to
|
* is equal to
|
||||||
* -ceil(p) + q
|
* -ceil(p) + q
|
||||||
* where
|
* where
|
||||||
* p = log(5**-q)/log(2) = -q * log(5)/log(2)
|
* p = log(5**-q)/log(2) = -q * log(5)/log(2)
|
||||||
|
|||||||
@ -31,7 +31,7 @@ for filename in ['LICENSE-MIT', 'LICENSE-APACHE']:
|
|||||||
processed_files[filename] = text
|
processed_files[filename] = text
|
||||||
|
|
||||||
# code
|
# code
|
||||||
for filename in [ 'constexpr_feature_detect.h', 'fast_float.h', 'float_common.h', 'ascii_number.h',
|
for filename in [ 'constexpr_feature_detect.h', 'fast_float.h', 'float_common.h', 'ascii_number.h',
|
||||||
'fast_table.h', 'decimal_to_binary.h', 'bigint.h',
|
'fast_table.h', 'decimal_to_binary.h', 'bigint.h',
|
||||||
'ascii_number.h', 'digit_comparison.h', 'parse_number.h']:
|
'ascii_number.h', 'digit_comparison.h', 'parse_number.h']:
|
||||||
with open('include/fast_float/' + filename, encoding='utf8') as f:
|
with open('include/fast_float/' + filename, encoding='utf8') as f:
|
||||||
@ -73,10 +73,10 @@ def license_content(license_arg):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
text = ''.join([
|
text = ''.join([
|
||||||
processed_files['AUTHORS'], processed_files['CONTRIBUTORS'],
|
processed_files['AUTHORS'], processed_files['CONTRIBUTORS'],
|
||||||
*license_content(args.license),
|
*license_content(args.license),
|
||||||
processed_files['constexpr_feature_detect.h'],
|
processed_files['constexpr_feature_detect.h'],
|
||||||
processed_files['fast_float.h'], processed_files['float_common.h'],
|
processed_files['fast_float.h'], processed_files['float_common.h'],
|
||||||
processed_files['ascii_number.h'], processed_files['fast_table.h'],
|
processed_files['ascii_number.h'], processed_files['fast_table.h'],
|
||||||
processed_files['decimal_to_binary.h'], processed_files['bigint.h'],
|
processed_files['decimal_to_binary.h'], processed_files['bigint.h'],
|
||||||
processed_files['ascii_number.h'], processed_files['digit_comparison.h'],
|
processed_files['ascii_number.h'], processed_files['digit_comparison.h'],
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
#
|
#
|
||||||
# Reference :
|
# Reference :
|
||||||
# Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to appear)
|
# Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to appear)
|
||||||
#
|
#
|
||||||
|
|
||||||
all_tqs = []
|
all_tqs = []
|
||||||
|
|
||||||
# Generates all possible values of T[q]
|
# Generates all possible values of T[q]
|
||||||
# Appendix B of Number parsing at a gigabyte per second.
|
# Appendix B of Number parsing at a gigabyte per second.
|
||||||
# Software: Practice and Experience 2021;51(8):1700–1727.
|
# Software: Practice and Experience 2021;51(8):1700–1727.
|
||||||
for q in range(-342, -27):
|
for q in range(-342, -27):
|
||||||
power5 = 5**-q
|
power5 = 5**-q
|
||||||
@ -44,9 +44,9 @@ def continued_fraction(numer, denom):
|
|||||||
numer, denom = denom, rem
|
numer, denom = denom, rem
|
||||||
return cf
|
return cf
|
||||||
|
|
||||||
# Given a continued fraction [a0; a1, a2, ..., an], returns
|
# Given a continued fraction [a0; a1, a2, ..., an], returns
|
||||||
# all the convergents of that continued fraction
|
# all the convergents of that continued fraction
|
||||||
# as pairs of the form (numer, denom), where numer/denom is
|
# as pairs of the form (numer, denom), where numer/denom is
|
||||||
# a convergent of the continued fraction in simple form.
|
# a convergent of the continued fraction in simple form.
|
||||||
def convergents(cf):
|
def convergents(cf):
|
||||||
p_n_minus_2 = 0
|
p_n_minus_2 = 0
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
const std::string input = "3,1416 xyz ";
|
const std::string input = "3,1416 xyz ";
|
||||||
double result;
|
double result;
|
||||||
|
|||||||
@ -30,7 +30,10 @@ void allvalues() {
|
|||||||
const char *string_end = to_string(v, buffer);
|
const char *string_end = to_string(v, buffer);
|
||||||
float result_value;
|
float result_value;
|
||||||
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
||||||
if (result.ec != std::errc()) {
|
// Starting with version 4.0 for fast_float, we return result_out_of_range if the
|
||||||
|
// value is either too small (too close to zero) or too large (effectively infinity).
|
||||||
|
// So std::errc::result_out_of_range is normal for well-formed input strings.
|
||||||
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "parsing error ? " << buffer << std::endl;
|
std::cerr << "parsing error ? " << buffer << std::endl;
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -46,7 +49,7 @@ void allvalues() {
|
|||||||
} else if (result_value != v) {
|
} else if (result_value != v) {
|
||||||
std::cerr << "no match ? " << buffer << std::endl;
|
std::cerr << "no match ? " << buffer << std::endl;
|
||||||
std::cout << "started with " << std::hexfloat << v << std::endl;
|
std::cout << "started with " << std::hexfloat << v << std::endl;
|
||||||
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
||||||
std::cout << std::dec;
|
std::cout << std::dec;
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ bool basic_test_64bit(std::string vals, double val) {
|
|||||||
double result_value;
|
double result_value;
|
||||||
auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(),
|
auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(),
|
||||||
result_value);
|
result_value);
|
||||||
if (result.ec != std::errc()) {
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << " I could not parse " << vals << std::endl;
|
std::cerr << " I could not parse " << vals << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -30,11 +30,11 @@ bool basic_test_64bit(std::string vals, double val) {
|
|||||||
std::cerr << vals << std::endl;
|
std::cerr << vals << std::endl;
|
||||||
std::cerr << "not nan" << result_value << std::endl;
|
std::cerr << "not nan" << result_value << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if(copysign(1,result_value) != copysign(1,val)) {
|
} else if(copysign(1,result_value) != copysign(1,val)) {
|
||||||
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
|
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
} else if (result_value != val) {
|
} else if (result_value != val) {
|
||||||
std::cerr << vals << std::endl;
|
std::cerr << vals << std::endl;
|
||||||
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
|
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
|
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||||
// Anything at all that is related to cygwin, msys and so forth will
|
// Anything at all that is related to cygwin, msys and so forth will
|
||||||
// always use this fallback because we cannot rely on it behaving as normal
|
// always use this fallback because we cannot rely on it behaving as normal
|
||||||
// gcc.
|
// gcc.
|
||||||
@ -73,7 +73,7 @@ bool allvalues() {
|
|||||||
}
|
}
|
||||||
uint32_t word = uint32_t(w);
|
uint32_t word = uint32_t(w);
|
||||||
memcpy(&v, &word, sizeof(v));
|
memcpy(&v, &word, sizeof(v));
|
||||||
if(std::isfinite(v)) {
|
if(std::isfinite(v)) {
|
||||||
float nextf = std::nextafterf(v, INFINITY);
|
float nextf = std::nextafterf(v, INFINITY);
|
||||||
if(copysign(1,v) != copysign(1,nextf)) { continue; }
|
if(copysign(1,v) != copysign(1,nextf)) { continue; }
|
||||||
if(!std::isfinite(nextf)) { continue; }
|
if(!std::isfinite(nextf)) { continue; }
|
||||||
@ -90,7 +90,10 @@ bool allvalues() {
|
|||||||
|
|
||||||
float result_value;
|
float result_value;
|
||||||
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
||||||
if (result.ec != std::errc()) {
|
// Starting with version 4.0 for fast_float, we return result_out_of_range if the
|
||||||
|
// value is either too small (too close to zero) or too large (effectively infinity).
|
||||||
|
// So std::errc::result_out_of_range is normal for well-formed input strings.
|
||||||
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "parsing error ? " << buffer << std::endl;
|
std::cerr << "parsing error ? " << buffer << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -120,7 +123,7 @@ bool allvalues() {
|
|||||||
std::cerr << "expected_midv " << std::hexfloat << expected_midv << std::endl;
|
std::cerr << "expected_midv " << std::hexfloat << expected_midv << std::endl;
|
||||||
std::cout << "started with " << std::hexfloat << midv << std::endl;
|
std::cout << "started with " << std::hexfloat << midv << std::endl;
|
||||||
std::cout << "round down to " << std::hexfloat << str_answer << std::endl;
|
std::cout << "round down to " << std::hexfloat << str_answer << std::endl;
|
||||||
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
||||||
std::cout << std::dec;
|
std::cout << std::dec;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -133,7 +136,7 @@ bool allvalues() {
|
|||||||
inline void Assert(bool Assertion) {
|
inline void Assert(bool Assertion) {
|
||||||
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
|
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
|
||||||
if (!Assertion) { std::cerr << "Omitting hard failure on msys/cygwin/sun systems."; }
|
if (!Assertion) { std::cerr << "Omitting hard failure on msys/cygwin/sun systems."; }
|
||||||
#else
|
#else
|
||||||
if (!Assertion) { throw std::runtime_error("bug"); }
|
if (!Assertion) { throw std::runtime_error("bug"); }
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ find_package(FastFloat REQUIRED)
|
|||||||
file(WRITE main.cpp "
|
file(WRITE main.cpp "
|
||||||
#include \"fast_float/fast_float.h\"
|
#include \"fast_float/fast_float.h\"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
const std::string input = \"3.1416 xyz \";
|
const std::string input = \"3.1416 xyz \";
|
||||||
double result;
|
double result;
|
||||||
|
|||||||
@ -29,7 +29,10 @@ void allvalues() {
|
|||||||
const char *string_end = to_string(v, buffer);
|
const char *string_end = to_string(v, buffer);
|
||||||
float result_value;
|
float result_value;
|
||||||
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
||||||
if (result.ec != std::errc()) {
|
// Starting with version 4.0 for fast_float, we return result_out_of_range if the
|
||||||
|
// value is either too small (too close to zero) or too large (effectively infinity).
|
||||||
|
// So std::errc::result_out_of_range is normal for well-formed input strings.
|
||||||
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "parsing error ? " << buffer << std::endl;
|
std::cerr << "parsing error ? " << buffer << std::endl;
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -46,7 +49,7 @@ void allvalues() {
|
|||||||
} else if (result_value != v) {
|
} else if (result_value != v) {
|
||||||
std::cerr << "no match ? " << buffer << " got " << result_value << " expected " << v << std::endl;
|
std::cerr << "no match ? " << buffer << " got " << result_value << " expected " << v << std::endl;
|
||||||
std::cout << "started with " << std::hexfloat << v << std::endl;
|
std::cout << "started with " << std::hexfloat << v << std::endl;
|
||||||
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
||||||
std::cout << std::dec;
|
std::cout << std::dec;
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,10 @@ void all_32bit_values() {
|
|||||||
const char *string_end = to_string(v, buffer);
|
const char *string_end = to_string(v, buffer);
|
||||||
double result_value;
|
double result_value;
|
||||||
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
||||||
if (result.ec != std::errc()) {
|
// Starting with version 4.0 for fast_float, we return result_out_of_range if the
|
||||||
|
// value is either too small (too close to zero) or too large (effectively infinity).
|
||||||
|
// So std::errc::result_out_of_range is normal for well-formed input strings.
|
||||||
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "parsing error ? " << buffer << std::endl;
|
std::cerr << "parsing error ? " << buffer << std::endl;
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -49,7 +52,7 @@ void all_32bit_values() {
|
|||||||
} else if (result_value != v) {
|
} else if (result_value != v) {
|
||||||
std::cerr << "no match ? " << buffer << std::endl;
|
std::cerr << "no match ? " << buffer << std::endl;
|
||||||
std::cout << "started with " << std::hexfloat << v << std::endl;
|
std::cout << "started with " << std::hexfloat << v << std::endl;
|
||||||
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
||||||
std::cout << std::dec;
|
std::cout << std::dec;
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,9 +27,9 @@ static fast_float::value128 g_lehmer64_state;
|
|||||||
* Society 68.225 (1999): 249-260.
|
* Society 68.225 (1999): 249-260.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline void lehmer64_seed(uint64_t seed) {
|
static inline void lehmer64_seed(uint64_t seed) {
|
||||||
g_lehmer64_state.high = 0;
|
g_lehmer64_state.high = 0;
|
||||||
g_lehmer64_state.low = seed;
|
g_lehmer64_state.low = seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t lehmer64() {
|
static inline uint64_t lehmer64() {
|
||||||
@ -56,7 +56,10 @@ void random_values(size_t N) {
|
|||||||
const char *string_end = to_string(v, buffer);
|
const char *string_end = to_string(v, buffer);
|
||||||
double result_value;
|
double result_value;
|
||||||
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
||||||
if (result.ec != std::errc()) {
|
// Starting with version 4.0 for fast_float, we return result_out_of_range if the
|
||||||
|
// value is either too small (too close to zero) or too large (effectively infinity).
|
||||||
|
// So std::errc::result_out_of_range is normal for well-formed input strings.
|
||||||
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "parsing error ? " << buffer << std::endl;
|
std::cerr << "parsing error ? " << buffer << std::endl;
|
||||||
errors++;
|
errors++;
|
||||||
if (errors > 10) {
|
if (errors > 10) {
|
||||||
@ -80,7 +83,7 @@ void random_values(size_t N) {
|
|||||||
} else if (result_value != v) {
|
} else if (result_value != v) {
|
||||||
std::cerr << "no match ? '" << buffer << "'" << std::endl;
|
std::cerr << "no match ? '" << buffer << "'" << std::endl;
|
||||||
std::cout << "started with " << std::hexfloat << v << std::endl;
|
std::cout << "started with " << std::hexfloat << v << std::endl;
|
||||||
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
||||||
std::cout << std::dec;
|
std::cout << std::dec;
|
||||||
errors++;
|
errors++;
|
||||||
if (errors > 10) {
|
if (errors > 10) {
|
||||||
|
|||||||
@ -22,7 +22,7 @@ bool test() {
|
|||||||
while((begin < end) && (std::isspace(*begin))) { begin++; }
|
while((begin < end) && (std::isspace(*begin))) { begin++; }
|
||||||
auto result = fast_float::from_chars(begin, end,
|
auto result = fast_float::from_chars(begin, end,
|
||||||
result_value);
|
result_value);
|
||||||
if (result.ec != std::errc()) {
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
printf("parsing %.*s\n", int(end - begin), begin);
|
printf("parsing %.*s\n", int(end - begin), begin);
|
||||||
std::cerr << " I could not parse " << std::endl;
|
std::cerr << " I could not parse " << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -40,7 +40,7 @@ bool test() {
|
|||||||
}
|
}
|
||||||
if(begin != end) {
|
if(begin != end) {
|
||||||
std::cerr << " bad ending " << std::endl;
|
std::cerr << " bad ending " << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,7 +105,7 @@ bool tester() {
|
|||||||
double result_value;
|
double result_value;
|
||||||
auto result =
|
auto result =
|
||||||
fast_float::from_chars(to_be_parsed.data(), to_be_parsed.data() + to_be_parsed.size(), result_value);
|
fast_float::from_chars(to_be_parsed.data(), to_be_parsed.data() + to_be_parsed.size(), result_value);
|
||||||
if (result.ec != std::errc()) {
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
std::cout << to_be_parsed << std::endl;
|
std::cout << to_be_parsed << std::endl;
|
||||||
std::cerr << " I could not parse " << std::endl;
|
std::cerr << " I could not parse " << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -29,9 +29,9 @@ static fast_float::value128 g_lehmer64_state;
|
|||||||
* Society 68.225 (1999): 249-260.
|
* Society 68.225 (1999): 249-260.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline void lehmer64_seed(uint64_t seed) {
|
static inline void lehmer64_seed(uint64_t seed) {
|
||||||
g_lehmer64_state.high = 0;
|
g_lehmer64_state.high = 0;
|
||||||
g_lehmer64_state.low = seed;
|
g_lehmer64_state.low = seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t lehmer64() {
|
static inline uint64_t lehmer64() {
|
||||||
@ -59,7 +59,10 @@ void random_values(size_t N) {
|
|||||||
const char *string_end = to_string(v, buffer);
|
const char *string_end = to_string(v, buffer);
|
||||||
double result_value;
|
double result_value;
|
||||||
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
auto result = fast_float::from_chars(buffer, string_end, result_value);
|
||||||
if (result.ec != std::errc()) {
|
// Starting with version 4.0 for fast_float, we return result_out_of_range if the
|
||||||
|
// value is either too small (too close to zero) or too large (effectively infinity).
|
||||||
|
// So std::errc::result_out_of_range is normal for well-formed input strings.
|
||||||
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "parsing error ? " << buffer << std::endl;
|
std::cerr << "parsing error ? " << buffer << std::endl;
|
||||||
errors++;
|
errors++;
|
||||||
if (errors > 10) {
|
if (errors > 10) {
|
||||||
@ -83,7 +86,7 @@ void random_values(size_t N) {
|
|||||||
} else if (result_value != v) {
|
} else if (result_value != v) {
|
||||||
std::cerr << "no match ? " << buffer << std::endl;
|
std::cerr << "no match ? " << buffer << std::endl;
|
||||||
std::cout << "started with " << std::hexfloat << v << std::endl;
|
std::cout << "started with " << std::hexfloat << v << std::endl;
|
||||||
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
std::cout << "got back " << std::hexfloat << result_value << std::endl;
|
||||||
std::cout << std::dec;
|
std::cout << std::dec;
|
||||||
errors++;
|
errors++;
|
||||||
if (errors > 10) {
|
if (errors > 10) {
|
||||||
|
|||||||
@ -101,7 +101,12 @@ size_t build_random_string(RandomEngine &rand, char *buffer) {
|
|||||||
if (i == size_t(location_of_decimal_separator)) {
|
if (i == size_t(location_of_decimal_separator)) {
|
||||||
buffer[pos++] = '.';
|
buffer[pos++] = '.';
|
||||||
}
|
}
|
||||||
buffer[pos++] = char(rand.next_digit() + '0');
|
buffer[pos] = char(rand.next_digit() + '0');
|
||||||
|
// We can have a leading zero only if location_of_decimal_separator = 1.
|
||||||
|
while(i == 0 && 1 != size_t(location_of_decimal_separator) && buffer[pos] == '0') {
|
||||||
|
buffer[pos] = char(rand.next_digit() + '0');
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
}
|
}
|
||||||
if (rand.next_bool()) {
|
if (rand.next_bool()) {
|
||||||
if (rand.next_bool()) {
|
if (rand.next_bool()) {
|
||||||
@ -178,7 +183,7 @@ bool tester(uint64_t seed, size_t volume) {
|
|||||||
double result_value;
|
double result_value;
|
||||||
auto result =
|
auto result =
|
||||||
fast_float::from_chars(buffer, buffer + length, result_value);
|
fast_float::from_chars(buffer, buffer + length, result_value);
|
||||||
if (result.ec != std::errc()) {
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
printf("parsing %.*s\n", int(length), buffer);
|
printf("parsing %.*s\n", int(length), buffer);
|
||||||
std::cerr << " I could not parse " << std::endl;
|
std::cerr << " I could not parse " << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -201,7 +206,7 @@ bool tester(uint64_t seed, size_t volume) {
|
|||||||
float result_value;
|
float result_value;
|
||||||
auto result =
|
auto result =
|
||||||
fast_float::from_chars(buffer, buffer + length, result_value);
|
fast_float::from_chars(buffer, buffer + length, result_value);
|
||||||
if (result.ec != std::errc()) {
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
printf("parsing %.*s\n", int(length), buffer);
|
printf("parsing %.*s\n", int(length), buffer);
|
||||||
std::cerr << " I could not parse " << std::endl;
|
std::cerr << " I could not parse " << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -97,7 +97,12 @@ size_t build_random_string(RandomEngine &rand, char *buffer) {
|
|||||||
if (i == size_t(location_of_decimal_separator)) {
|
if (i == size_t(location_of_decimal_separator)) {
|
||||||
buffer[pos++] = '.';
|
buffer[pos++] = '.';
|
||||||
}
|
}
|
||||||
buffer[pos++] = char(rand.next_digit() + '0');
|
buffer[pos] = char(rand.next_digit() + '0');
|
||||||
|
// We can have a leading zero only if location_of_decimal_separator = 1.
|
||||||
|
while(i == 0 && 1 != size_t(location_of_decimal_separator) && buffer[pos] == '0') {
|
||||||
|
buffer[pos] = char(rand.next_digit() + '0');
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
}
|
}
|
||||||
if (rand.next_bool()) {
|
if (rand.next_bool()) {
|
||||||
if (rand.next_bool()) {
|
if (rand.next_bool()) {
|
||||||
@ -174,7 +179,7 @@ bool tester(uint64_t seed, size_t volume) {
|
|||||||
double result_value;
|
double result_value;
|
||||||
auto result =
|
auto result =
|
||||||
fast_float::from_chars(buffer, buffer + length, result_value);
|
fast_float::from_chars(buffer, buffer + length, result_value);
|
||||||
if (result.ec != std::errc()) {
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
printf("parsing %.*s\n", int(length), buffer);
|
printf("parsing %.*s\n", int(length), buffer);
|
||||||
std::cerr << " I could not parse " << std::endl;
|
std::cerr << " I could not parse " << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -197,7 +202,7 @@ bool tester(uint64_t seed, size_t volume) {
|
|||||||
float result_value;
|
float result_value;
|
||||||
auto result =
|
auto result =
|
||||||
fast_float::from_chars(buffer, buffer + length, result_value);
|
fast_float::from_chars(buffer, buffer + length, result_value);
|
||||||
if (result.ec != std::errc()) {
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
printf("parsing %.*s\n", int(length), buffer);
|
printf("parsing %.*s\n", int(length), buffer);
|
||||||
std::cerr << " I could not parse " << std::endl;
|
std::cerr << " I could not parse " << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -85,7 +85,7 @@ bool test() {
|
|||||||
}
|
}
|
||||||
if(begin != end) {
|
if(begin != end) {
|
||||||
std::cerr << " bad ending " << std::endl;
|
std::cerr << " bad ending " << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -239,7 +239,7 @@ bool partow_test() {
|
|||||||
T result_value;
|
T result_value;
|
||||||
auto result = fast_float::from_chars(st.data(), st.data() + st.size(),
|
auto result = fast_float::from_chars(st.data(), st.data() + st.size(),
|
||||||
result_value);
|
result_value);
|
||||||
if (result.ec != std::errc()) {
|
if (result.ec != std::errc() && result.ec != std::errc::result_out_of_range) {
|
||||||
printf("parsing %.*s\n", int(st.size()), st.data());
|
printf("parsing %.*s\n", int(st.size()), st.data());
|
||||||
std::cerr << " I could not parse " << std::endl;
|
std::cerr << " I could not parse " << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -270,7 +270,7 @@ int main() {
|
|||||||
std::cout << "32 bits checks" << std::endl;
|
std::cout << "32 bits checks" << std::endl;
|
||||||
Assert(partow_test<float>());
|
Assert(partow_test<float>());
|
||||||
Assert(test<float>());
|
Assert(test<float>());
|
||||||
|
|
||||||
std::cout << "64 bits checks" << std::endl;
|
std::cout << "64 bits checks" << std::endl;
|
||||||
Assert(partow_test<double>());
|
Assert(partow_test<double>());
|
||||||
Assert(test<double>());
|
Assert(test<double>());
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user