commit
010e596001
10 changed files with 2650 additions and 18 deletions
|
@ -821,6 +821,10 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I
|
|||
|
||||
The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](http://bjoern.hoehrmann.de/) <bjoern@hoehrmann.de>
|
||||
|
||||
* * *
|
||||
|
||||
The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](http://florian.loitsch.com/)
|
||||
|
||||
## Contact
|
||||
|
||||
If you have questions regarding the library, I would like to invite you to [open an issue at GitHub](https://github.com/nlohmann/json/issues/new). Please describe your request, problem, or question as detailed as possible, and also mention the version of the library you are using as well as the version of your compiler and operating system. Opening an issue at GitHub allows other users and contributors to this library to collaborate. For instance, I have little experience with MSVC, and most issues in this regard have been solved by a growing community. If you have a look at the [closed issues](https://github.com/nlohmann/json/issues?q=is%3Aissue+is%3Aclosed), you will see that we react quite timely in most cases.
|
||||
|
|
1027
develop/detail/conversions/to_chars.hpp
Normal file
1027
develop/detail/conversions/to_chars.hpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -14,6 +14,7 @@
|
|||
#include <string> // string
|
||||
#include <type_traits> // is_same
|
||||
|
||||
#include "detail/conversions/to_chars.hpp"
|
||||
#include "detail/macro_scope.hpp"
|
||||
#include "detail/meta.hpp"
|
||||
#include "detail/parsing/output_adapters.hpp"
|
||||
|
@ -475,14 +476,36 @@ class serializer
|
|||
void dump_float(number_float_t x)
|
||||
{
|
||||
// NaN / inf
|
||||
if (not std::isfinite(x) or std::isnan(x))
|
||||
if (not std::isfinite(x))
|
||||
{
|
||||
o->write_characters("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
// get number of digits for a text -> float -> text round-trip
|
||||
static constexpr auto d = std::numeric_limits<number_float_t>::digits10;
|
||||
// If number_float_t is an IEEE-754 single or double precision number,
|
||||
// use the Grisu2 algorithm to produce short numbers which are guaranteed
|
||||
// to round-trip, using strtof and strtod, resp.
|
||||
//
|
||||
// NB: The test below works if <long double> == <double>.
|
||||
static constexpr bool is_ieee_single_or_double
|
||||
= (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
|
||||
(std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
|
||||
|
||||
dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
|
||||
}
|
||||
|
||||
void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
|
||||
{
|
||||
char* begin = number_buffer.data();
|
||||
char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
|
||||
|
||||
o->write_characters(begin, static_cast<size_t>(end - begin));
|
||||
}
|
||||
|
||||
void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
|
||||
{
|
||||
// get number of digits for a float -> text -> float round-trip
|
||||
static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
|
||||
|
||||
// the actual conversion
|
||||
std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
|
||||
|
|
1057
src/json.hpp
1057
src/json.hpp
File diff suppressed because it is too large
Load diff
|
@ -1 +1 @@
|
|||
[1.7976931348623157e308]
|
||||
[1.7976931348623157e+308]
|
|
@ -1 +1 @@
|
|||
[1.2345E-30]
|
||||
[1.2345e-30]
|
|
@ -1 +1 @@
|
|||
[1.2345E+30]
|
||||
[1.2345e+30]
|
|
@ -593,6 +593,64 @@ TEST_CASE("regression tests")
|
|||
"[json.exception.out_of_range.406] number overflow parsing '22e2222'");
|
||||
}
|
||||
|
||||
SECTION("issue #360 - Loss of precision when serializing <double>")
|
||||
{
|
||||
auto check_roundtrip = [](double number)
|
||||
{
|
||||
CAPTURE(number);
|
||||
|
||||
json j = number;
|
||||
CHECK(j.is_number_float());
|
||||
|
||||
std::stringstream ss;
|
||||
ss << j;
|
||||
|
||||
CHECK_NOTHROW(ss >> j);
|
||||
CHECK(j.is_number_float());
|
||||
CHECK(j.get<json::number_float_t>() == number);
|
||||
};
|
||||
|
||||
check_roundtrip(100000000000.1236);
|
||||
check_roundtrip(std::numeric_limits<json::number_float_t>::max());
|
||||
|
||||
// Some more numbers which fail to roundtrip when serialized with digits10 significand digits (instead of max_digits10)
|
||||
check_roundtrip(1.541888611948064e-17);
|
||||
check_roundtrip(5.418771028591015e-16);
|
||||
check_roundtrip(9.398685592608595e-15);
|
||||
check_roundtrip(8.826843952762347e-14);
|
||||
check_roundtrip(8.143291313475335e-13);
|
||||
check_roundtrip(4.851328172762508e-12);
|
||||
check_roundtrip(6.677850998084358e-11);
|
||||
check_roundtrip(3.995398518174525e-10);
|
||||
check_roundtrip(1.960452605645124e-9);
|
||||
check_roundtrip(3.551812586302883e-8);
|
||||
check_roundtrip(2.947988411689261e-7);
|
||||
check_roundtrip(8.210166748056192e-6);
|
||||
check_roundtrip(6.104889704266753e-5);
|
||||
check_roundtrip(0.0008629954631330876);
|
||||
check_roundtrip(0.004936993881051611);
|
||||
check_roundtrip(0.08309725102608073);
|
||||
check_roundtrip(0.5210494268499783);
|
||||
check_roundtrip(6.382927930939767);
|
||||
check_roundtrip(59.94947245358671);
|
||||
check_roundtrip(361.0838651266122);
|
||||
check_roundtrip(4678.354596181877);
|
||||
check_roundtrip(61412.17658956043);
|
||||
check_roundtrip(725696.0799057782);
|
||||
check_roundtrip(2811732.583399828);
|
||||
check_roundtrip(30178351.07533605);
|
||||
check_roundtrip(689684880.3235844);
|
||||
check_roundtrip(5714887673.555147);
|
||||
check_roundtrip(84652038821.18808);
|
||||
check_roundtrip(156510583431.7721);
|
||||
check_roundtrip(5938450569021.732);
|
||||
check_roundtrip(83623297654460.33);
|
||||
check_roundtrip(701466573254773.6);
|
||||
check_roundtrip(1369013370304513);
|
||||
check_roundtrip(96963648023094720);
|
||||
check_roundtrip(3.478237409280108e+17);
|
||||
}
|
||||
|
||||
SECTION("issue #366 - json::parse on failed stream gets stuck")
|
||||
{
|
||||
std::ifstream f("file_not_found.json");
|
||||
|
@ -785,7 +843,7 @@ TEST_CASE("regression tests")
|
|||
{
|
||||
json j = json::parse("166020696663385964490");
|
||||
CHECK(j.is_number_float());
|
||||
CHECK(j.dump() == "1.66020696663386e+20");
|
||||
CHECK(j.get<json::number_float_t>() == static_cast<json::number_float_t>(166020696663385964490.0));
|
||||
}
|
||||
|
||||
SECTION("issue #405 - Heap-buffer-overflow (OSS-Fuzz issue 342)")
|
||||
|
|
|
@ -307,15 +307,15 @@ TEST_CASE("compliance tests from nativejson-benchmark")
|
|||
"test/data/json_roundtrip/roundtrip21.json",
|
||||
"test/data/json_roundtrip/roundtrip22.json",
|
||||
"test/data/json_roundtrip/roundtrip23.json",
|
||||
//"test/data/json_roundtrip/roundtrip24.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip25.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip26.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip27.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip28.json", // roundtrip error
|
||||
"test/data/json_roundtrip/roundtrip24.json",
|
||||
"test/data/json_roundtrip/roundtrip25.json",
|
||||
"test/data/json_roundtrip/roundtrip26.json",
|
||||
"test/data/json_roundtrip/roundtrip27.json",
|
||||
//"test/data/json_roundtrip/roundtrip28.json", // incompatible with roundtrip24
|
||||
"test/data/json_roundtrip/roundtrip29.json",
|
||||
//"test/data/json_roundtrip/roundtrip30.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip31.json", // roundtrip error
|
||||
"test/data/json_roundtrip/roundtrip32.json"
|
||||
"test/data/json_roundtrip/roundtrip30.json",
|
||||
"test/data/json_roundtrip/roundtrip31.json"
|
||||
//"test/data/json_roundtrip/roundtrip32.json" // same as roundtrip31
|
||||
})
|
||||
{
|
||||
CAPTURE(filename);
|
||||
|
|
469
test/src/unit-to_chars.cpp
Normal file
469
test/src/unit-to_chars.cpp
Normal file
|
@ -0,0 +1,469 @@
|
|||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 3.0.1
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
// XXX:
|
||||
// Only compile these tests if 'float' and 'double' are IEEE-754 single- and
|
||||
// double-precision numbers, resp.
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::detail::dtoa_impl::reinterpret_bits;
|
||||
|
||||
static float make_float(uint32_t sign_bit, uint32_t biased_exponent, uint32_t significand)
|
||||
{
|
||||
assert(sign_bit == 0 || sign_bit == 1);
|
||||
assert(biased_exponent <= 0xFF);
|
||||
assert(significand <= 0x007FFFFF);
|
||||
|
||||
uint32_t bits = 0;
|
||||
|
||||
bits |= sign_bit << 31;
|
||||
bits |= biased_exponent << 23;
|
||||
bits |= significand;
|
||||
|
||||
return reinterpret_bits<float>(bits);
|
||||
}
|
||||
|
||||
// ldexp -- convert f * 2^e to IEEE single precision
|
||||
static float make_float(uint64_t f, int e)
|
||||
{
|
||||
constexpr uint64_t kHiddenBit = 0x00800000;
|
||||
constexpr uint64_t kSignificandMask = 0x007FFFFF;
|
||||
constexpr int kPhysicalSignificandSize = 23; // Excludes the hidden bit.
|
||||
constexpr int kExponentBias = 0x7F + kPhysicalSignificandSize;
|
||||
constexpr int kDenormalExponent = 1 - kExponentBias;
|
||||
constexpr int kMaxExponent = 0xFF - kExponentBias;
|
||||
|
||||
while (f > kHiddenBit + kSignificandMask) {
|
||||
f >>= 1;
|
||||
e++;
|
||||
}
|
||||
if (e >= kMaxExponent) {
|
||||
return std::numeric_limits<float>::infinity();
|
||||
}
|
||||
if (e < kDenormalExponent) {
|
||||
return 0.0;
|
||||
}
|
||||
while (e > kDenormalExponent && (f & kHiddenBit) == 0) {
|
||||
f <<= 1;
|
||||
e--;
|
||||
}
|
||||
|
||||
uint64_t biased_exponent;
|
||||
if (e == kDenormalExponent && (f & kHiddenBit) == 0)
|
||||
biased_exponent = 0;
|
||||
else
|
||||
biased_exponent = static_cast<uint64_t>(e + kExponentBias);
|
||||
|
||||
uint64_t bits = (f & kSignificandMask) | (biased_exponent << kPhysicalSignificandSize);
|
||||
return reinterpret_bits<float>(static_cast<uint32_t>(bits));
|
||||
}
|
||||
|
||||
static double make_double(uint64_t sign_bit, uint64_t biased_exponent, uint64_t significand)
|
||||
{
|
||||
assert(sign_bit == 0 || sign_bit == 1);
|
||||
assert(biased_exponent <= 0x7FF);
|
||||
assert(significand <= 0x000FFFFFFFFFFFFF);
|
||||
|
||||
uint64_t bits = 0;
|
||||
|
||||
bits |= sign_bit << 63;
|
||||
bits |= biased_exponent << 52;
|
||||
bits |= significand;
|
||||
|
||||
return reinterpret_bits<double>(bits);
|
||||
}
|
||||
|
||||
// ldexp -- convert f * 2^e to IEEE double precision
|
||||
static double make_double(uint64_t f, int e)
|
||||
{
|
||||
constexpr uint64_t kHiddenBit = 0x0010000000000000;
|
||||
constexpr uint64_t kSignificandMask = 0x000FFFFFFFFFFFFF;
|
||||
constexpr int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
|
||||
constexpr int kExponentBias = 0x3FF + kPhysicalSignificandSize;
|
||||
constexpr int kDenormalExponent = 1 - kExponentBias;
|
||||
constexpr int kMaxExponent = 0x7FF - kExponentBias;
|
||||
|
||||
while (f > kHiddenBit + kSignificandMask) {
|
||||
f >>= 1;
|
||||
e++;
|
||||
}
|
||||
if (e >= kMaxExponent) {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (e < kDenormalExponent) {
|
||||
return 0.0;
|
||||
}
|
||||
while (e > kDenormalExponent && (f & kHiddenBit) == 0) {
|
||||
f <<= 1;
|
||||
e--;
|
||||
}
|
||||
|
||||
uint64_t biased_exponent;
|
||||
if (e == kDenormalExponent && (f & kHiddenBit) == 0)
|
||||
biased_exponent = 0;
|
||||
else
|
||||
biased_exponent = static_cast<uint64_t>(e + kExponentBias);
|
||||
|
||||
uint64_t bits = (f & kSignificandMask) | (biased_exponent << kPhysicalSignificandSize);
|
||||
return reinterpret_bits<double>(bits);
|
||||
}
|
||||
|
||||
TEST_CASE("digit gen")
|
||||
{
|
||||
SECTION("single precision")
|
||||
{
|
||||
auto check_float = [](float number, const std::string& digits, int expected_exponent)
|
||||
{
|
||||
CAPTURE(number);
|
||||
CAPTURE(digits);
|
||||
CAPTURE(expected_exponent);
|
||||
|
||||
char buf[32];
|
||||
int len = 0;
|
||||
int exponent = 0;
|
||||
nlohmann::detail::dtoa_impl::grisu2(buf, len, exponent, number);
|
||||
|
||||
CHECK(digits == std::string(buf, buf + len));
|
||||
CHECK(expected_exponent == exponent);
|
||||
};
|
||||
|
||||
check_float(make_float(0, 0, 0x00000001), "1", -45); // min denormal
|
||||
check_float(make_float(0, 0, 0x007FFFFF), "11754942", -45); // max denormal
|
||||
check_float(make_float(0, 1, 0x00000000), "11754944", -45); // min normal
|
||||
check_float(make_float(0, 1, 0x00000001), "11754945", -45);
|
||||
check_float(make_float(0, 1, 0x007FFFFF), "23509886", -45);
|
||||
check_float(make_float(0, 2, 0x00000000), "23509887", -45);
|
||||
check_float(make_float(0, 2, 0x00000001), "2350989", -44);
|
||||
check_float(make_float(0, 24, 0x00000000), "98607613", -39); // fail if no special case in normalized boundaries
|
||||
check_float(make_float(0, 30, 0x00000000), "63108872", -37); // fail if no special case in normalized boundaries
|
||||
check_float(make_float(0, 31, 0x00000000), "12621775", -36); // fail if no special case in normalized boundaries
|
||||
check_float(make_float(0, 57, 0x00000000), "84703295", -29); // fail if no special case in normalized boundaries
|
||||
check_float(make_float(0, 254, 0x007FFFFE), "34028233", 31);
|
||||
check_float(make_float(0, 254, 0x007FFFFF), "34028235", 31); // max normal
|
||||
|
||||
// V. Paxson and W. Kahan, "A Program for Testing IEEE Binary-Decimal Conversion", manuscript, May 1991,
|
||||
// ftp://ftp.ee.lbl.gov/testbase-report.ps.Z (report)
|
||||
// ftp://ftp.ee.lbl.gov/testbase.tar.Z (program)
|
||||
|
||||
// Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP
|
||||
check_float(make_float(12676506, -102), "25", -25);
|
||||
check_float(make_float(12676506, -103), "125", -26);
|
||||
check_float(make_float(15445013, 86), "1195", 30);
|
||||
check_float(make_float(13734123, -138), "39415", -39);
|
||||
check_float(make_float(12428269, -130), "913085", -38);
|
||||
check_float(make_float(15334037, -146), "1719005", -43);
|
||||
check_float(make_float(11518287, -41), "52379105", -13);
|
||||
check_float(make_float(12584953, -145), "2821644", -43);
|
||||
check_float(make_float(15961084, -125), "37524328", -38);
|
||||
check_float(make_float(14915817, -146), "16721209", -44);
|
||||
check_float(make_float(10845484, -102), "21388946", -31);
|
||||
check_float(make_float(16431059, -61), "7125836", -18);
|
||||
|
||||
// Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP
|
||||
check_float(make_float(16093626, 69), "95", 26);
|
||||
check_float(make_float( 9983778, 25), "335", 12);
|
||||
check_float(make_float(12745034, 104), "2585", 35);
|
||||
check_float(make_float(12706553, 72), "60005", 24);
|
||||
check_float(make_float(11005028, 45), "387205", 15);
|
||||
check_float(make_float(15059547, 71), "3555835", 22);
|
||||
check_float(make_float(16015691, -99), "25268305", -30);
|
||||
check_float(make_float( 8667859, 56), "6245851", 17);
|
||||
check_float(make_float(14855922, -82), "30721327", -25);
|
||||
check_float(make_float(14855922, -83), "15360663", -25);
|
||||
check_float(make_float(10144164, -110), "781478", -32);
|
||||
check_float(make_float(13248074, 95), "52481028", 28);
|
||||
}
|
||||
|
||||
SECTION("double precision")
|
||||
{
|
||||
auto check_double = [](double number, const std::string& digits, int expected_exponent)
|
||||
{
|
||||
CAPTURE(number);
|
||||
CAPTURE(digits);
|
||||
CAPTURE(expected_exponent);
|
||||
|
||||
char buf[32];
|
||||
int len = 0;
|
||||
int exponent = 0;
|
||||
nlohmann::detail::dtoa_impl::grisu2(buf, len, exponent, number);
|
||||
|
||||
CHECK(digits == std::string(buf, buf + len));
|
||||
CHECK(expected_exponent == exponent);
|
||||
};
|
||||
|
||||
check_double(make_double(0, 0, 0x0000000000000001), "5", -324); // min denormal
|
||||
check_double(make_double(0, 0, 0x000FFFFFFFFFFFFF), "2225073858507201", -323); // max denormal
|
||||
check_double(make_double(0, 1, 0x0000000000000000), "22250738585072014", -324); // min normal
|
||||
check_double(make_double(0, 1, 0x0000000000000001), "2225073858507202", -323);
|
||||
check_double(make_double(0, 1, 0x000FFFFFFFFFFFFF), "44501477170144023", -324);
|
||||
check_double(make_double(0, 2, 0x0000000000000000), "4450147717014403", -323);
|
||||
check_double(make_double(0, 2, 0x0000000000000001), "4450147717014404", -323);
|
||||
check_double(make_double(0, 4, 0x0000000000000000), "17800590868057611", -323); // fail if no special case in normalized boundaries
|
||||
check_double(make_double(0, 5, 0x0000000000000000), "35601181736115222", -323); // fail if no special case in normalized boundaries
|
||||
check_double(make_double(0, 6, 0x0000000000000000), "7120236347223045", -322); // fail if no special case in normalized boundaries
|
||||
check_double(make_double(0, 10, 0x0000000000000000), "11392378155556871", -321); // fail if no special case in normalized boundaries
|
||||
check_double(make_double(0, 2046, 0x000FFFFFFFFFFFFE), "17976931348623155", 292);
|
||||
check_double(make_double(0, 2046, 0x000FFFFFFFFFFFFF), "17976931348623157", 292); // max normal
|
||||
|
||||
// Test different paths in DigitGen
|
||||
check_double( 10000, "1", 4);
|
||||
check_double( 1200000, "12", 5);
|
||||
check_double(4.9406564584124654e-324, "5", -324); // exit integral loop
|
||||
check_double(2.2250738585072009e-308, "2225073858507201", -323); // exit fractional loop
|
||||
check_double( 1.82877982605164e-99, "182877982605164", -113);
|
||||
check_double( 1.1505466208671903e-09, "11505466208671903", -25);
|
||||
check_double( 5.5645893133766722e+20, "5564589313376672", 5);
|
||||
check_double( 53.034830388866226, "53034830388866226", -15);
|
||||
check_double( 0.0021066531670178605, "21066531670178605", -19);
|
||||
|
||||
// V. Paxson and W. Kahan, "A Program for Testing IEEE Binary-Decimal Conversion", manuscript, May 1991,
|
||||
// ftp://ftp.ee.lbl.gov/testbase-report.ps.Z (report)
|
||||
// ftp://ftp.ee.lbl.gov/testbase.tar.Z (program)
|
||||
|
||||
// Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP
|
||||
check_double(make_double(8511030020275656, -342) /* 9.5e-088 */, "95", -89);
|
||||
check_double(make_double(5201988407066741, -824) /* 4.65e-233 */, "465", -235);
|
||||
check_double(make_double(6406892948269899, +237) /* 1.415e+087 */, "1415", 84);
|
||||
check_double(make_double(8431154198732492, +72) /* 3.9815e+037 */, "39815", 33);
|
||||
check_double(make_double(6475049196144587, +99) /* 4.10405e+045 */, "410405", 40);
|
||||
check_double(make_double(8274307542972842, +726) /* 2.920845e+234 */, "2920845", 228);
|
||||
check_double(make_double(5381065484265332, -456) /* 2.8919465e-122 */, "28919465", -129);
|
||||
check_double(make_double(6761728585499734, -1057) /* 4.37877185e-303 */, "437877185", -311);
|
||||
check_double(make_double(7976538478610756, +376) /* 1.227701635e+129 */, "1227701635", 120);
|
||||
check_double(make_double(5982403858958067, +377) /* 1.8415524525e+129 */, "18415524525", 119);
|
||||
check_double(make_double(5536995190630837, +93) /* 5.48357443505e+043 */, "548357443505", 32);
|
||||
check_double(make_double(7225450889282194, +710) /* 3.891901811465e+229 */, "3891901811465", 217);
|
||||
check_double(make_double(7225450889282194, +709) /* 1.9459509057325e+229 */, "19459509057325", 216);
|
||||
check_double(make_double(8703372741147379, +117) /* 1.44609583816055e+051 */, "144609583816055", 37);
|
||||
check_double(make_double(8944262675275217, -1001) /* 4.173677474585315e-286 */, "4173677474585315", -301);
|
||||
check_double(make_double(7459803696087692, -707) /* 1.1079507728788885e-197 */, "11079507728788885", -213);
|
||||
check_double(make_double(6080469016670379, -381) /* 1.234550136632744e-099 */, "1234550136632744", -114);
|
||||
check_double(make_double(8385515147034757, +721) /* 9.2503171196036502e+232 */, "925031711960365", 218);
|
||||
check_double(make_double(7514216811389786, -828) /* 4.1980471502848898e-234 */, "419804715028489", -248);
|
||||
check_double(make_double(8397297803260511, -345) /* 1.1716315319786511e-088 */, "11716315319786511", -104);
|
||||
check_double(make_double(6733459239310543, +202) /* 4.3281007284461249e+076 */, "4328100728446125", 61);
|
||||
check_double(make_double(8091450587292794, -473) /* 3.3177101181600311e-127 */, "3317710118160031", -142);
|
||||
|
||||
// Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP
|
||||
check_double(make_double(6567258882077402, +952) /* 2.5e+302 */, "25", 301);
|
||||
check_double(make_double(6712731423444934, +535) /* 7.55e+176 */, "755", 174);
|
||||
check_double(make_double(6712731423444934, +534) /* 3.775e+176 */, "3775", 173);
|
||||
check_double(make_double(5298405411573037, -957) /* 4.3495e-273 */, "43495", -277);
|
||||
check_double(make_double(5137311167659507, -144) /* 2.30365e-028 */, "230365", -33);
|
||||
check_double(make_double(6722280709661868, +363) /* 1.263005e+125 */, "1263005", 119);
|
||||
check_double(make_double(5344436398034927, -169) /* 7.1422105e-036 */, "71422105", -43);
|
||||
check_double(make_double(8369123604277281, -853) /* 1.39345735e-241 */, "139345735", -249);
|
||||
check_double(make_double(8995822108487663, -780) /* 1.414634485e-219 */, "1414634485", -228);
|
||||
check_double(make_double(8942832835564782, -383) /* 4.5392779195e-100 */, "45392779195", -110);
|
||||
check_double(make_double(8942832835564782, -384) /* 2.26963895975e-100 */, "226963895975", -111);
|
||||
check_double(make_double(8942832835564782, -385) /* 1.134819479875e-100 */, "1134819479875", -112);
|
||||
check_double(make_double(6965949469487146, -249) /* 7.7003665618895e-060 */, "77003665618895", -73);
|
||||
check_double(make_double(6965949469487146, -250) /* 3.85018328094475e-060 */, "385018328094475", -74);
|
||||
check_double(make_double(6965949469487146, -251) /* 1.925091640472375e-060 */, "1925091640472375", -75);
|
||||
check_double(make_double(7487252720986826, +548) /* 6.8985865317742005e+180 */, "68985865317742005", 164);
|
||||
check_double(make_double(5592117679628511, +164) /* 1.3076622631878654e+065 */, "13076622631878654", 49);
|
||||
check_double(make_double(8887055249355788, +665) /* 1.3605202075612124e+216 */, "13605202075612124", 200);
|
||||
check_double(make_double(6994187472632449, +690) /* 3.5928102174759597e+223 */, "35928102174759597", 207);
|
||||
check_double(make_double(8797576579012143, +588) /* 8.9125197712484552e+192 */, "8912519771248455", 177);
|
||||
check_double(make_double(7363326733505337, +272) /* 5.5876975736230114e+097 */, "55876975736230114", 81);
|
||||
check_double(make_double(8549497411294502, -448) /* 1.1762578307285404e-119 */, "11762578307285404", -135);
|
||||
|
||||
// Table 20: Stress Inputs for Converting 56-bit Binary to Decimal, < 1/2 ULP
|
||||
check_double(make_double(50883641005312716, -172) /* 8.4999999999999993e-036 */, "8499999999999999", -51);
|
||||
check_double(make_double(38162730753984537, -170) /* 2.5499999999999999e-035 */, "255", -37);
|
||||
check_double(make_double(50832789069151999, -101) /* 2.0049999999999997e-014 */, "20049999999999997", -30);
|
||||
check_double(make_double(51822367833714164, -109) /* 7.9844999999999994e-017 */, "7984499999999999", -32);
|
||||
check_double(make_double(66840152193508133, -172) /* 1.1165499999999999e-035 */, "11165499999999999", -51);
|
||||
check_double(make_double(55111239245584393, -138) /* 1.581615e-025 */, "1581615", -31);
|
||||
check_double(make_double(71704866733321482, -112) /* 1.3809855e-017 */, "13809855", -24);
|
||||
check_double(make_double(67160949328233173, -142) /* 1.2046404499999999e-026 */, "12046404499999999", -42);
|
||||
check_double(make_double(53237141308040189, -152) /* 9.3251405449999991e-030 */, "9325140544999999", -45);
|
||||
check_double(make_double(62785329394975786, -112) /* 1.2092014595e-017 */, "12092014595", -27);
|
||||
check_double(make_double(48367680154689523, -77) /* 3.2007045838499998e-007 */, "320070458385", -18);
|
||||
check_double(make_double(42552223180606797, -102) /* 8.391946324354999e-015 */, "8391946324354999", -30);
|
||||
check_double(make_double(63626356173011241, -112) /* 1.2253990460585e-017 */, "12253990460585", -30);
|
||||
check_double(make_double(43566388595783643, -99) /* 6.8735641489760495e-014 */, "687356414897605", -28);
|
||||
check_double(make_double(54512669636675272, -159) /* 7.459816430480385e-032 */, "7459816430480385", -47);
|
||||
check_double(make_double(52306490527514614, -167) /* 2.7960588398142552e-034 */, "2796058839814255", -49);
|
||||
check_double(make_double(52306490527514614, -168) /* 1.3980294199071276e-034 */, "13980294199071276", -50);
|
||||
check_double(make_double(41024721590449423, -89) /* 6.6279012373057359e-011 */, "6627901237305736", -26);
|
||||
check_double(make_double(37664020415894738, -132) /* 6.9177880043968072e-024 */, "6917788004396807", -39);
|
||||
check_double(make_double(37549883692866294, -93) /* 3.7915693108349708e-012 */, "3791569310834971", -27);
|
||||
check_double(make_double(69124110374399839, -104) /* 3.4080817676591365e-015 */, "34080817676591365", -31);
|
||||
check_double(make_double(69124110374399839, -105) /* 1.7040408838295683e-015 */, "17040408838295683", -31);
|
||||
|
||||
// Table 21: Stress Inputs for Converting 56-bit Binary to Decimal, > 1/2 ULP
|
||||
check_double(make_double(49517601571415211, -94) /* 2.4999999999999998e-012 */, "25", -13);
|
||||
check_double(make_double(49517601571415211, -95) /* 1.2499999999999999e-012 */, "125", -14);
|
||||
check_double(make_double(54390733528642804, -133) /* 4.9949999999999996e-024 */, "49949999999999996", -40); // shortest: 4995e-27
|
||||
check_double(make_double(71805402319113924, -157) /* 3.9304999999999998e-031 */, "39304999999999998", -47); // shortest: 39305e-35
|
||||
check_double(make_double(40435277969631694, -179) /* 5.2770499999999992e-038 */, "5277049999999999", -53);
|
||||
check_double(make_double(57241991568619049, -165) /* 1.223955e-033 */, "1223955", -39);
|
||||
check_double(make_double(65224162876242886, +58) /* 1.8799584999999998e+034 */, "18799584999999998", 18);
|
||||
check_double(make_double(70173376848895368, -138) /* 2.01387715e-025 */, "201387715", -33);
|
||||
check_double(make_double(37072848117383207, -99) /* 5.8490641049999989e-014 */, "5849064104999999", -29);
|
||||
check_double(make_double(56845051585389697, -176) /* 5.9349003054999999e-037 */, "59349003055", -47);
|
||||
check_double(make_double(54791673366936431, -145) /* 1.2284718039499998e-027 */, "12284718039499998", -43);
|
||||
check_double(make_double(66800318669106231, -169) /* 8.9270767180849991e-035 */, "8927076718084999", -50);
|
||||
check_double(make_double(66800318669106231, -170) /* 4.4635383590424995e-035 */, "44635383590424995", -51);
|
||||
check_double(make_double(66574323440112438, -119) /* 1.0016990862549499e-019 */, "10016990862549499", -35);
|
||||
check_double(make_double(65645179969330963, -173) /* 5.4829412628024647e-036 */, "5482941262802465", -51);
|
||||
check_double(make_double(61847254334681076, -109) /* 9.5290783281036439e-017 */, "9529078328103644", -32);
|
||||
check_double(make_double(39990712921393606, -145) /* 8.9662279366405553e-028 */, "8966227936640555", -43);
|
||||
check_double(make_double(59292318184400283, -149) /* 8.3086234418058538e-029 */, "8308623441805854", -44);
|
||||
check_double(make_double(69116558615326153, -143) /* 6.1985873566126555e-027 */, "61985873566126555", -43);
|
||||
check_double(make_double(69116558615326153, -144) /* 3.0992936783063277e-027 */, "30992936783063277", -43);
|
||||
check_double(make_double(39462549494468513, -152) /* 6.9123512506176015e-030 */, "6912351250617602", -45);
|
||||
check_double(make_double(39462549494468513, -153) /* 3.4561756253088008e-030 */, "3456175625308801", -45);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("formatting")
|
||||
{
|
||||
SECTION("single precision")
|
||||
{
|
||||
auto check_float = [](float number, const std::string& expected)
|
||||
{
|
||||
char buf[32];
|
||||
char* end = nlohmann::detail::to_chars(buf, buf + 32, number);
|
||||
std::string actual(buf, end);
|
||||
|
||||
CHECK(actual == expected);
|
||||
};
|
||||
// %.9g
|
||||
check_float( -1.2345e-22f, "-1.2345e-22" ); // -1.23450004e-22
|
||||
check_float( -1.2345e-21f, "-1.2345e-21" ); // -1.23450002e-21
|
||||
check_float( -1.2345e-20f, "-1.2345e-20" ); // -1.23450002e-20
|
||||
check_float( -1.2345e-19f, "-1.2345e-19" ); // -1.23449999e-19
|
||||
check_float( -1.2345e-18f, "-1.2345e-18" ); // -1.23449996e-18
|
||||
check_float( -1.2345e-17f, "-1.2345e-17" ); // -1.23449998e-17
|
||||
check_float( -1.2345e-16f, "-1.2345e-16" ); // -1.23449996e-16
|
||||
check_float( -1.2345e-15f, "-1.2345e-15" ); // -1.23450002e-15
|
||||
check_float( -1.2345e-14f, "-1.2345e-14" ); // -1.23450004e-14
|
||||
check_float( -1.2345e-13f, "-1.2345e-13" ); // -1.23449997e-13
|
||||
check_float( -1.2345e-12f, "-1.2345e-12" ); // -1.23450002e-12
|
||||
check_float( -1.2345e-11f, "-1.2345e-11" ); // -1.2345e-11
|
||||
check_float( -1.2345e-10f, "-1.2345e-10" ); // -1.2345e-10
|
||||
check_float( -1.2345e-9f, "-1.2345e-09" ); // -1.23449995e-09
|
||||
check_float( -1.2345e-8f, "-1.2345e-08" ); // -1.23449997e-08
|
||||
check_float( -1.2345e-7f, "-1.2345e-07" ); // -1.23449993e-07
|
||||
check_float( -1.2345e-6f, "-1.2345e-06" ); // -1.23450002e-06
|
||||
check_float( -1.2345e-5f, "-1.2345e-05" ); // -1.2345e-05
|
||||
check_float( -1.2345e-4f, "-0.00012345" ); // -0.000123449994
|
||||
check_float( -1.2345e-3f, "-0.0012345" ); // -0.00123449997
|
||||
check_float( -1.2345e-2f, "-0.012345" ); // -0.0123450002
|
||||
check_float( -1.2345e-1f, "-0.12345" ); // -0.123450004
|
||||
check_float( -0.0f, "-0.0" ); // -0
|
||||
check_float( 0.0f, "0.0" ); // 0
|
||||
check_float( 1.2345e+0f, "1.2345" ); // 1.23450005
|
||||
check_float( 1.2345e+1f, "12.345" ); // 12.3450003
|
||||
check_float( 1.2345e+2f, "123.45" ); // 123.449997
|
||||
check_float( 1.2345e+3f, "1234.5" ); // 1234.5
|
||||
check_float( 1.2345e+4f, "12345.0" ); // 12345
|
||||
check_float( 1.2345e+5f, "123450.0" ); // 123450
|
||||
check_float( 1.2345e+6f, "1.2345e+06" ); // 1234500
|
||||
check_float( 1.2345e+7f, "1.2345e+07" ); // 12345000
|
||||
check_float( 1.2345e+8f, "1.2345e+08" ); // 123450000
|
||||
check_float( 1.2345e+9f, "1.2345e+09" ); // 1.23449997e+09
|
||||
check_float( 1.2345e+10f, "1.2345e+10" ); // 1.23449999e+10
|
||||
check_float( 1.2345e+11f, "1.2345e+11" ); // 1.23449999e+11
|
||||
check_float( 1.2345e+12f, "1.2345e+12" ); // 1.23450006e+12
|
||||
check_float( 1.2345e+13f, "1.2345e+13" ); // 1.23449995e+13
|
||||
check_float( 1.2345e+14f, "1.2345e+14" ); // 1.23450002e+14
|
||||
check_float( 1.2345e+15f, "1.2345e+15" ); // 1.23450003e+15
|
||||
check_float( 1.2345e+16f, "1.2345e+16" ); // 1.23449998e+16
|
||||
check_float( 1.2345e+17f, "1.2345e+17" ); // 1.23449996e+17
|
||||
check_float( 1.2345e+18f, "1.2345e+18" ); // 1.23450004e+18
|
||||
check_float( 1.2345e+19f, "1.2345e+19" ); // 1.23449999e+19
|
||||
check_float( 1.2345e+20f, "1.2345e+20" ); // 1.23449999e+20
|
||||
check_float( 1.2345e+21f, "1.2345e+21" ); // 1.23449999e+21
|
||||
check_float( 1.2345e+22f, "1.2345e+22" ); // 1.23450005e+22
|
||||
}
|
||||
|
||||
SECTION("double precision")
|
||||
{
|
||||
auto check_double = [](double number, const std::string& expected)
|
||||
{
|
||||
char buf[32];
|
||||
char* end = nlohmann::detail::to_chars(buf, buf + 32, number);
|
||||
std::string actual(buf, end);
|
||||
|
||||
CHECK(actual == expected);
|
||||
};
|
||||
// dtoa %.15g %.17g shortest
|
||||
check_double( -1.2345e-22, "-1.2345e-22" ); // -1.2345e-22 -1.2345000000000001e-22 -1.2345e-22
|
||||
check_double( -1.2345e-21, "-1.2345e-21" ); // -1.2345e-21 -1.2345000000000001e-21 -1.2345e-21
|
||||
check_double( -1.2345e-20, "-1.2345e-20" ); // -1.2345e-20 -1.2345e-20 -1.2345e-20
|
||||
check_double( -1.2345e-19, "-1.2345e-19" ); // -1.2345e-19 -1.2345000000000001e-19 -1.2345e-19
|
||||
check_double( -1.2345e-18, "-1.2345e-18" ); // -1.2345e-18 -1.2345000000000001e-18 -1.2345e-18
|
||||
check_double( -1.2345e-17, "-1.2345e-17" ); // -1.2345e-17 -1.2345e-17 -1.2345e-17
|
||||
check_double( -1.2345e-16, "-1.2345e-16" ); // -1.2345e-16 -1.2344999999999999e-16 -1.2345e-16
|
||||
check_double( -1.2345e-15, "-1.2345e-15" ); // -1.2345e-15 -1.2345e-15 -1.2345e-15
|
||||
check_double( -1.2345e-14, "-1.2345e-14" ); // -1.2345e-14 -1.2345e-14 -1.2345e-14
|
||||
check_double( -1.2345e-13, "-1.2345e-13" ); // -1.2345e-13 -1.2344999999999999e-13 -1.2345e-13
|
||||
check_double( -1.2345e-12, "-1.2345e-12" ); // -1.2345e-12 -1.2345e-12 -1.2345e-12
|
||||
check_double( -1.2345e-11, "-1.2345e-11" ); // -1.2345e-11 -1.2345e-11 -1.2345e-11
|
||||
check_double( -1.2345e-10, "-1.2345e-10" ); // -1.2345e-10 -1.2345e-10 -1.2345e-10
|
||||
check_double( -1.2345e-9, "-1.2345e-09" ); // -1.2345e-09 -1.2345e-09 -1.2345e-9
|
||||
check_double( -1.2345e-8, "-1.2345e-08" ); // -1.2345e-08 -1.2345000000000001e-08 -1.2345e-8
|
||||
check_double( -1.2345e-7, "-1.2345e-07" ); // -1.2345e-07 -1.2345000000000001e-07 -1.2345e-7
|
||||
check_double( -1.2345e-6, "-1.2345e-06" ); // -1.2345e-06 -1.2345e-06 -1.2345e-6
|
||||
check_double( -1.2345e-5, "-1.2345e-05" ); // -1.2345e-05 -1.2345e-05 -1.2345e-5
|
||||
check_double( -1.2345e-4, "-0.00012345" ); // -0.00012345 -0.00012344999999999999 -0.00012345
|
||||
check_double( -1.2345e-3, "-0.0012345" ); // -0.0012345 -0.0012344999999999999 -0.0012345
|
||||
check_double( -1.2345e-2, "-0.012345" ); // -0.012345 -0.012345 -0.012345
|
||||
check_double( -1.2345e-1, "-0.12345" ); // -0.12345 -0.12345 -0.12345
|
||||
check_double( -0.0, "-0.0" ); // -0 -0 -0
|
||||
check_double( 0.0, "0.0" ); // 0 0 0
|
||||
check_double( 1.2345e+0, "1.2345" ); // 1.2345 1.2344999999999999 1.2345
|
||||
check_double( 1.2345e+1, "12.345" ); // 12.345 12.345000000000001 12.345
|
||||
check_double( 1.2345e+2, "123.45" ); // 123.45 123.45 123.45
|
||||
check_double( 1.2345e+3, "1234.5" ); // 1234.5 1234.5 1234.5
|
||||
check_double( 1.2345e+4, "12345.0" ); // 12345 12345 12345
|
||||
check_double( 1.2345e+5, "123450.0" ); // 123450 123450 123450
|
||||
check_double( 1.2345e+6, "1234500.0" ); // 1234500 1234500 1234500
|
||||
check_double( 1.2345e+7, "12345000.0" ); // 12345000 12345000 12345000
|
||||
check_double( 1.2345e+8, "123450000.0" ); // 123450000 123450000 123450000
|
||||
check_double( 1.2345e+9, "1234500000.0" ); // 1234500000 1234500000 1234500000
|
||||
check_double( 1.2345e+10, "12345000000.0" ); // 12345000000 12345000000 12345000000
|
||||
check_double( 1.2345e+11, "123450000000.0" ); // 123450000000 123450000000 123450000000
|
||||
check_double( 1.2345e+12, "1234500000000.0" ); // 1234500000000 1234500000000 1234500000000
|
||||
check_double( 1.2345e+13, "12345000000000.0" ); // 12345000000000 12345000000000 12345000000000
|
||||
check_double( 1.2345e+14, "123450000000000.0" ); // 123450000000000 123450000000000 123450000000000
|
||||
check_double( 1.2345e+15, "1.2345e+15" ); // 1.2345e+15 1234500000000000 1.2345e15
|
||||
check_double( 1.2345e+16, "1.2345e+16" ); // 1.2345e+16 12345000000000000 1.2345e16
|
||||
check_double( 1.2345e+17, "1.2345e+17" ); // 1.2345e+17 1.2345e+17 1.2345e17
|
||||
check_double( 1.2345e+18, "1.2345e+18" ); // 1.2345e+18 1.2345e+18 1.2345e18
|
||||
check_double( 1.2345e+19, "1.2345e+19" ); // 1.2345e+19 1.2345e+19 1.2345e19
|
||||
check_double( 1.2345e+20, "1.2345e+20" ); // 1.2345e+20 1.2345e+20 1.2345e20
|
||||
check_double( 1.2345e+21, "1.2344999999999999e+21" ); // 1.2345e+21 1.2344999999999999e+21 1.2345e21
|
||||
check_double( 1.2345e+22, "1.2345e+22" ); // 1.2345e+22 1.2345e+22 1.2345e22
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue