]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/json/test/double.cpp
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 // Official repository: https://github.com/boostorg/json
11 #include <boost/json/stream_parser.hpp>
12 #include <boost/json/parse.hpp>
13 #include <boost/json/serialize.hpp>
19 #include "parse-vectors.hpp"
21 #include "test_suite.hpp"
25 template<std::size_t N
, class... Args
>
27 sprintf(char (&buf
)[N
],
28 char const* format
, Args
&&... args
)
31 sprintf_s(buf
, format
,
32 std::forward
<Args
>(args
)...);
34 std::sprintf(buf
, format
,
35 std::forward
<Args
>(args
)...);
52 operator()(string_view s
) const
54 BOOST_TEST_CHECKPOINT();
57 p
.write(s
.data(), s
.size(), ec
);
60 if(! BOOST_TEST(! ec
))
62 auto const jv
= p
.release();
63 double const d
= jv
.as_double();
70 within_1ulp(double x
, double y
)
73 std::memcpy(&bx
, &x
, sizeof(x
));
74 std::memcpy(&by
, &y
, sizeof(y
));
81 case 0xffffffffffffffff:
94 const parse_options
& po
= parse_options())
96 stream_parser
p(storage_ptr(), po
);
98 p
.reset(std::move(sp
));
99 p
.write(s
.data(), s
.size(), ec
);
108 check_round_trip(value
const& jv1
,
109 const parse_options
& po
= parse_options())
112 //to_string_test(jv1); // use this if serializer is broken
115 from_string_test(s2
, {}, po
);
116 BOOST_TEST(equal(jv1
, jv2
));
126 const parse_options
& po
= parse_options())
129 from_string_test(s
, sp
, po
);
135 grind_one(string_view s
)
139 check_round_trip(jv
);
145 grind(string_view s
, F
const& f
,
146 const parse_options
& po
= parse_options())
150 grind_one(s
, {}, f
, po
);
152 fail_loop([&](storage_ptr
const& sp
)
154 grind_one(s
, sp
, f
, po
);
159 // Destroy the stream_parser at every
160 // split point to check leaks.
161 for(std::size_t i
= 1;
166 stream_parser
p(storage_ptr(), po
);
169 p
.write(s
.data(), i
, ec
);
181 catch(std::exception
const&)
190 const parse_options
& po
= parse_options())
193 [](value
const& jv
, const parse_options
& po
)
195 check_round_trip(jv
, po
);
201 grind_double(string_view s
, double v
)
204 [v
](value
const& jv
, const parse_options
&)
206 if(! BOOST_TEST(jv
.is_double()))
208 BOOST_TEST(jv
.get_double() == v
);
212 // Verify that f converts to the
213 // same double produced by `strtod`.
214 // Requires `s` is not represented by an integral type.
217 fc(std::string
const& s
, F
const& f
)
221 std::strtod(s
.c_str(), &str_end
);
222 // BOOST_TEST(str_end == &s.back() + 1);
223 double const got
= f(s
);
224 auto same
= got
== need
;
226 true : within_1ulp(got
, need
);
228 if( !BOOST_TEST(close
) )
230 std::cerr
<< "Failure on '" << s
<< "': " << got
<< " != " << need
<< "\n";
235 fc(std::string
const& s
)
238 fc(s
+ std::string( 64, ' ' ), f_boost
{});
244 grind_double("-1.010", -1.01);
245 grind_double("-0.010", -0.01);
246 grind_double("-0.0", -0.0);
247 grind_double("-0e0", -0.0);
248 grind_double( "18.4", 18.4);
249 grind_double("-18.4", -18.4);
250 grind_double( "18446744073709551616", 1.8446744073709552e+19);
251 grind_double("-18446744073709551616", -1.8446744073709552e+19);
252 grind_double( "18446744073709551616.0", 1.8446744073709552e+19);
253 grind_double( "18446744073709551616.00009", 1.8446744073709552e+19);
254 grind_double( "1844674407370955161600000", 1.8446744073709552e+24);
255 grind_double("-1844674407370955161600000", -1.8446744073709552e+24);
256 grind_double( "1844674407370955161600000.0", 1.8446744073709552e+24);
257 grind_double( "1844674407370955161600000.00009", 1.8446744073709552e+24);
258 grind_double( "19700720435664.186294290058937593e13", 1.9700720435664185e+26);
260 grind_double( "1.0", 1.0);
261 grind_double( "1.1", 1.1);
262 grind_double( "1.11", 1.11);
263 grind_double( "1.11111", 1.11111);
264 grind_double( "11.1111", 11.1111);
265 grind_double( "111.111", 111.111);
267 fc("-0.9999999999999999999999");
268 fc("-0.9999999999999999");
269 fc("-0.9007199254740991");
270 fc("-0.999999999999999");
271 fc("-0.99999999999999");
272 fc("-0.9999999999999");
273 fc("-0.999999999999");
274 fc("-0.99999999999");
301 fc("0.999999999999");
302 fc("0.9999999999999");
303 fc("0.99999999999999");
304 fc("0.999999999999999");
305 fc("0.9007199254740991");
306 fc("0.9999999999999999");
307 fc("0.9999999999999999999999");
308 fc("0.999999999999999999999999999");
320 fc("999999999999999999.0");
321 fc("999999999999999999999.0");
322 fc("999999999999999999999e5");
323 fc("999999999999999999999.0e5");
325 fc("0.00000000000000001");
335 "00000000000000000000000000000000000000000000000000" // 50 zeroes
338 "00000000000000000000000000000000000000000000000000" // 50 zeroes
342 "00000000000000000000000000000000000000000000000000"
343 "00000000000000000000000000000000000000000000000000"
344 "00000000000000000000000000000000000000000000000000"
345 "00000000000000000000000000000000000000000000000000"
346 "00000000000000000000000000000000000000000000000000"
347 "00000000000000000000000000000000000000000000000000"
348 "00000000000000000000000000000000000000000000000000"
349 "00000000000000000000000000000000000000000000000000"
350 "00000000000000000000000000000000000000000000000000"
351 "00000000000000000000000000000000000000000000000000" // 500 zeroes
354 "00000000000000000000000000000000000000000000000000"
355 "00000000000000000000000000000000000000000000000000"
356 "00000000000000000000000000000000000000000000000000"
357 "00000000000000000000000000000000000000000000000000"
358 "00000000000000000000000000000000000000000000000000"
359 "00000000000000000000000000000000000000000000000000"
360 "00000000000000000000000000000000000000000000000000"
361 "00000000000000000000000000000000000000000000000000"
362 "00000000000000000000000000000000000000000000000000"
363 "00000000000000000000000000000000000000000000000000" // 500 zeroes
367 "00000000000000000000000000000000000000000000000000"
368 "00000000000000000000000000000000000000000000000000"
369 "00000000000000000000000000000000000000000000000000"
370 "00000000000000000000000000000000000000000000000000"
371 "00000000000000000000000000000000000000000000000000"
372 "00000000000000000000000000000000000000000000000000"
373 "00000000000000000000000000000000000000000000000000"
374 "00000000000000000000000000000000000000000000000000"
375 "00000000000000000000000000000000000000000000000000"
376 "00000000000000000000000000000000000000000000000000" // 500 zeroes
380 void checkAccuracy(const char* nm
, int max_ulp
)
382 double x
= std::strtod( nm
, 0 );
383 double y
= boost::json::parse( nm
).as_double();
384 std::uint64_t bx
, by
;
385 std::memcpy( &bx
, &x
, sizeof(x
) );
386 std::memcpy( &by
, &y
, sizeof(y
) );
387 std::int64_t diff
= bx
- by
;
388 if (!BOOST_TEST(std::abs( diff
) <= max_ulp
))
390 "%s: difference %" PRId64
" ulp\n"
391 " strtod: %.13a %.16g\n"
392 " boost.json: %.13a %.16g\n\n",
393 nm
, diff
, x
, x
, y
, y
);
401 checkAccuracy("10199214983525025199.13135016100190689227e-308", 2);
403 for( int i
= 0; i
< 1000000; ++i
)
405 unsigned long long x1
= rng();
406 unsigned long long x2
= rng();
407 int x3
= std::uniform_int_distribution
<>( -308, +308 )( rng
);
410 sprintf( buffer
, "%llu.%llue%d", x1
, x2
, x3
);
412 checkAccuracy( buffer
, 2 );
415 for( int i
= -326; i
<= +309; ++i
)
418 sprintf( buffer
, "1e%d", i
);
420 checkAccuracy( buffer
, 0 );
432 TEST_SUITE(double_test
, "boost.json.double");