Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
json
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
json
Commits
810f81bb
Commit
810f81bb
authored
Jan 15, 2018
by
abolz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Regenerate src/json.hpp
parent
787204f0
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1052 additions
and
1 deletion
+1052
-1
src/json.hpp
src/json.hpp
+1052
-1
No files found.
src/json.hpp
View file @
810f81bb
...
...
@@ -6453,6 +6453,1035 @@ class binary_writer
#include <string> // string
#include <type_traits> // is_same
// #include "detail/conversions/to_chars.hpp"
#include <cassert> // assert
#include <ciso646> // or, and, not
#include <cmath> // signbit, isfinite
#include <cstdint> // intN_t, uintN_t
#include <cstring> // memcpy, memmove
namespace
nlohmann
{
namespace
detail
{
// Implements the Grisu2 algorithm for binary to decimal floating-point conversion.
//
// This implementation is a slightly modified version of the reference implementation which may be
// obtained from http://florian.loitsch.com/publications (bench.tar.gz).
//
// The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
//
// For a detailed description of the algorithm see:
//
// [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with Integers",
// Proceedings of the ACM SIGPLAN 2010 Conference on Programming Language Design and Implementation, PLDI 2010
// [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
// Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language Design and Implementation, PLDI 1996
namespace
dtoa_impl
{
template
<
typename
Target
,
typename
Source
>
Target
reinterpret_bits
(
Source
source
)
{
static_assert
(
sizeof
(
Target
)
==
sizeof
(
Source
),
"size mismatch"
);
Target
target
;
std
::
memcpy
(
&
target
,
&
source
,
sizeof
(
Source
));
return
target
;
}
struct
diyfp
// f * 2^e
{
static
constexpr
int
kPrecision
=
64
;
// = q
uint64_t
f
;
int
e
;
constexpr
diyfp
()
:
f
(
0
),
e
(
0
)
{}
constexpr
diyfp
(
uint64_t
f_
,
int
e_
)
:
f
(
f_
),
e
(
e_
)
{}
// Returns x - y.
// PRE: x.e == y.e and x.f >= y.f
static
diyfp
sub
(
diyfp
x
,
diyfp
y
);
// Returns x * y.
// The result is rounded. (Only the upper q bits are returned.)
static
diyfp
mul
(
diyfp
x
,
diyfp
y
);
// Normalize x such that the significand is >= 2^(q-1).
// PRE: x.f != 0
static
diyfp
normalize
(
diyfp
x
);
// Normalize x such that the result has the exponent E.
// PRE: e >= x.e and the upper e - x.e bits of x.f must be zero.
static
diyfp
normalize_to
(
diyfp
x
,
int
e
);
};
inline
diyfp
diyfp
::
sub
(
diyfp
x
,
diyfp
y
)
{
assert
(
x
.
e
==
y
.
e
);
assert
(
x
.
f
>=
y
.
f
);
return
diyfp
(
x
.
f
-
y
.
f
,
x
.
e
);
}
inline
diyfp
diyfp
::
mul
(
diyfp
x
,
diyfp
y
)
{
static_assert
(
kPrecision
==
64
,
"internal error"
);
// Computes:
// f = round((x.f * y.f) / 2^q)
// e = x.e + y.e + q
// Emulate the 64-bit * 64-bit multiplication:
//
// p = u * v
// = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
// = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
// = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
// = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
// = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
// = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
// = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
//
// (Since Q might be larger than 2^32 - 1)
//
// = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
//
// (Q_hi + H does not overflow a 64-bit int)
//
// = p_lo + 2^64 p_hi
const
uint64_t
u_lo
=
x
.
f
&
0xFFFFFFFF
;
const
uint64_t
u_hi
=
x
.
f
>>
32
;
const
uint64_t
v_lo
=
y
.
f
&
0xFFFFFFFF
;
const
uint64_t
v_hi
=
y
.
f
>>
32
;
const
uint64_t
p0
=
u_lo
*
v_lo
;
const
uint64_t
p1
=
u_lo
*
v_hi
;
const
uint64_t
p2
=
u_hi
*
v_lo
;
const
uint64_t
p3
=
u_hi
*
v_hi
;
const
uint64_t
p0_hi
=
p0
>>
32
;
const
uint64_t
p1_lo
=
p1
&
0xFFFFFFFF
;
const
uint64_t
p1_hi
=
p1
>>
32
;
const
uint64_t
p2_lo
=
p2
&
0xFFFFFFFF
;
const
uint64_t
p2_hi
=
p2
>>
32
;
uint64_t
Q
=
p0_hi
+
p1_lo
+
p2_lo
;
// The full product might now be computed as
//
// p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
// p_lo = p0_lo + (Q << 32)
//
// But in this particular case here, the full p_lo is not required.
// Effectively we only need to add the highest bit in p_lo to p_hi (and
// Q_hi + 1 does not overflow).
Q
+=
uint64_t
{
1
}
<<
(
64
-
32
-
1
);
// round, ties up
const
uint64_t
h
=
p3
+
p2_hi
+
p1_hi
+
(
Q
>>
32
);
return
diyfp
(
h
,
x
.
e
+
y
.
e
+
64
);
}
inline
diyfp
diyfp
::
normalize
(
diyfp
x
)
{
assert
(
x
.
f
!=
0
);
while
((
x
.
f
>>
63
)
==
0
)
{
x
.
f
<<=
1
;
x
.
e
--
;
}
return
x
;
}
inline
diyfp
diyfp
::
normalize_to
(
diyfp
x
,
int
target_exponent
)
{
const
int
delta
=
x
.
e
-
target_exponent
;
assert
(
delta
>=
0
);
assert
(((
x
.
f
<<
delta
)
>>
delta
)
==
x
.
f
);
return
diyfp
(
x
.
f
<<
delta
,
target_exponent
);
}
struct
boundaries
{
diyfp
w
;
diyfp
minus
;
diyfp
plus
;
};
// Compute the (normalized) diyfp representing the input number 'value' and its boundaries.
// PRE: value must be finite and positive
template
<
typename
FloatType
>
boundaries
compute_boundaries
(
FloatType
value
)
{
assert
(
std
::
isfinite
(
value
));
assert
(
value
>
0
);
// Convert the IEEE representation into a diyfp.
//
// If v is denormal:
// value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
// If v is normalized:
// value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
static_assert
(
std
::
numeric_limits
<
FloatType
>::
is_iec559
,
"internal error: dtoa_short requires an IEEE-754 floating-point implementation"
);
constexpr
int
kPrecision
=
std
::
numeric_limits
<
FloatType
>::
digits
;
// = p (includes the hidden bit)
constexpr
int
kBias
=
std
::
numeric_limits
<
FloatType
>::
max_exponent
-
1
+
(
kPrecision
-
1
);
constexpr
int
kMinExp
=
1
-
kBias
;
constexpr
uint64_t
kHiddenBit
=
uint64_t
{
1
}
<<
(
kPrecision
-
1
);
// = 2^(p-1)
using
bits_type
=
typename
std
::
conditional
<
kPrecision
==
24
,
uint32_t
,
uint64_t
>::
type
;
const
uint64_t
bits
=
reinterpret_bits
<
bits_type
>
(
value
);
const
uint64_t
E
=
bits
>>
(
kPrecision
-
1
);
const
uint64_t
F
=
bits
&
(
kHiddenBit
-
1
);
const
bool
is_denormal
=
(
E
==
0
);
const
diyfp
v
=
is_denormal
?
diyfp
(
F
,
1
-
kBias
)
:
diyfp
(
F
+
kHiddenBit
,
static_cast
<
int
>
(
E
)
-
kBias
);
// Compute the boundaries m- and m+ of the floating-point value
// v = f * 2^e.
//
// Determine v- and v+, the floating-point predecessor and successor if v,
// respectively.
//
// v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
// = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
//
// v+ = v + 2^e
//
// Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
// between m- and m+ round to v, regardless of how the input rounding
// algorithm breaks ties.
//
// ---+-------------+-------------+-------------+-------------+--- (A)
// v- m- v m+ v+
//
// -----------------+------+------+-------------+-------------+--- (B)
// v- m- v m+ v+
const
bool
lower_boundary_is_closer
=
(
F
==
0
and
E
>
1
);
const
diyfp
m_plus
=
diyfp
(
2
*
v
.
f
+
1
,
v
.
e
-
1
);
const
diyfp
m_minus
=
lower_boundary_is_closer
?
diyfp
(
4
*
v
.
f
-
1
,
v
.
e
-
2
)
// (B)
:
diyfp
(
2
*
v
.
f
-
1
,
v
.
e
-
1
);
// (A)
// Determine the normalized w+ = m+.
const
diyfp
w_plus
=
diyfp
::
normalize
(
m_plus
);
// Determine w- = m- such that e_(w-) = e_(w+).
const
diyfp
w_minus
=
diyfp
::
normalize_to
(
m_minus
,
w_plus
.
e
);
return
{
diyfp
::
normalize
(
v
),
w_minus
,
w_plus
};
}
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
// within a certain range [alpha, gamma] (Definition 3.2 from [1])
//
// alpha <= e = e_c + e_w + q <= gamma
//
// or
//
// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
// <= f_c * f_w * 2^gamma
//
// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
//
// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
//
// or
//
// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
//
// The choice of (alpha,gamma) determines the size of the table and the form of
// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
// in practice:
//
// The idea is to cut the number c * w = f * 2^e into two parts, which can be
// processed independently: An integral part p1, and a fractional part p2:
//
// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
// = (f div 2^-e) + (f mod 2^-e) * 2^e
// = p1 + p2 * 2^e
//
// The conversion of p1 into decimal form requires a series of divisions and
// modulos by (a power of) 10. These operations are faster for 32-bit than for
// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
// achieved by choosing
//
// -e >= 32 or e <= -32 := gamma
//
// In order to convert the fractional part
//
// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
//
// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
// d[-i] are extracted in order:
//
// (10 * p2) div 2^-e = d[-1]
// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
//
// The multiplication by 10 must not overflow. It is sufficient to choose
//
// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
//
// Since p2 = f mod 2^-e < 2^-e,
//
// -e <= 60 or e >= -60 := alpha
constexpr
int
kAlpha
=
-
60
;
constexpr
int
kGamma
=
-
32
;
struct
cached_power
// c = f * 2^e ~= 10^k
{
uint64_t
f
;
int
e
;
int
k
;
};
// For a normalized diyfp w = f * 2^e, this function returns a (normalized)
// cached power-of-ten c = f_c * 2^e_c, such that the exponent of the product
// w * c satisfies (Definition 3.2 from [1])
//
// alpha <= e_c + e + q <= gamma.
//
inline
cached_power
get_cached_power_for_binary_exponent
(
int
e
)
{
// Now
//
// alpha <= e_c + e + q <= gamma (1)
// ==> f_c * 2^alpha <= c * 2^e * 2^q
//
// and since the c's are normalized, 2^(q-1) <= f_c,
//
// ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
// ==> 2^(alpha - e - 1) <= c
//
// If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
//
// k = ceil( log_10( 2^(alpha - e - 1) ) )
// = ceil( (alpha - e - 1) * log_10(2) )
//
// From the paper:
// "In theory the result of the procedure could be wrong since c is rounded,
// and the computation itself is approximated [...]. In practice, however,
// this simple function is sufficient."
//
// For IEEE double precision floating-point numbers converted into
// normalized diyfp's w = f * 2^e, with q = 64,
//
// e >= -1022 (min IEEE exponent)
// -52 (p - 1)
// -52 (p - 1, possibly normalize denormal IEEE numbers)
// -11 (normalize the diyfp)
// = -1137
//
// and
//
// e <= +1023 (max IEEE exponent)
// -52 (p - 1)
// -11 (normalize the diyfp)
// = 960
//
// This binary exponent range [-1137,960] results in a decimal exponent
// range [-307,324]. One does not need to store a cached power for each
// k in this range. For each such k it suffices to find a cached power
// such that the exponent of the product lies in [alpha,gamma].
// This implies that the difference of the decimal exponents of adjacent
// table entries must be less than or equal to
//
// floor( (gamma - alpha) * log_10(2) ) = 8.
//
// (A smaller distance gamma-alpha would require a larger table.)
// NB:
// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
constexpr
int
kCachedPowersSize
=
79
;
constexpr
int
kCachedPowersMinDecExp
=
-
300
;
constexpr
int
kCachedPowersDecStep
=
8
;
static
constexpr
cached_power
kCachedPowers
[]
=
{
{
0xAB70FE17C79AC6CA
,
-
1060
,
-
300
},
{
0xFF77B1FCBEBCDC4F
,
-
1034
,
-
292
},
{
0xBE5691EF416BD60C
,
-
1007
,
-
284
},
{
0x8DD01FAD907FFC3C
,
-
980
,
-
276
},
{
0xD3515C2831559A83
,
-
954
,
-
268
},
{
0x9D71AC8FADA6C9B5
,
-
927
,
-
260
},
{
0xEA9C227723EE8BCB
,
-
901
,
-
252
},
{
0xAECC49914078536D
,
-
874
,
-
244
},
{
0x823C12795DB6CE57
,
-
847
,
-
236
},
{
0xC21094364DFB5637
,
-
821
,
-
228
},
{
0x9096EA6F3848984F
,
-
794
,
-
220
},
{
0xD77485CB25823AC7
,
-
768
,
-
212
},
{
0xA086CFCD97BF97F4
,
-
741
,
-
204
},
{
0xEF340A98172AACE5
,
-
715
,
-
196
},
{
0xB23867FB2A35B28E
,
-
688
,
-
188
},
{
0x84C8D4DFD2C63F3B
,
-
661
,
-
180
},
{
0xC5DD44271AD3CDBA
,
-
635
,
-
172
},
{
0x936B9FCEBB25C996
,
-
608
,
-
164
},
{
0xDBAC6C247D62A584
,
-
582
,
-
156
},
{
0xA3AB66580D5FDAF6
,
-
555
,
-
148
},
{
0xF3E2F893DEC3F126
,
-
529
,
-
140
},
{
0xB5B5ADA8AAFF80B8
,
-
502
,
-
132
},
{
0x87625F056C7C4A8B
,
-
475
,
-
124
},
{
0xC9BCFF6034C13053
,
-
449
,
-
116
},
{
0x964E858C91BA2655
,
-
422
,
-
108
},
{
0xDFF9772470297EBD
,
-
396
,
-
100
},
{
0xA6DFBD9FB8E5B88F
,
-
369
,
-
92
},
{
0xF8A95FCF88747D94
,
-
343
,
-
84
},
{
0xB94470938FA89BCF
,
-
316
,
-
76
},
{
0x8A08F0F8BF0F156B
,
-
289
,
-
68
},
{
0xCDB02555653131B6
,
-
263
,
-
60
},
{
0x993FE2C6D07B7FAC
,
-
236
,
-
52
},
{
0xE45C10C42A2B3B06
,
-
210
,
-
44
},
{
0xAA242499697392D3
,
-
183
,
-
36
},
{
0xFD87B5F28300CA0E
,
-
157
,
-
28
},
{
0xBCE5086492111AEB
,
-
130
,
-
20
},
{
0x8CBCCC096F5088CC
,
-
103
,
-
12
},
{
0xD1B71758E219652C
,
-
77
,
-
4
},
{
0x9C40000000000000
,
-
50
,
4
},
{
0xE8D4A51000000000
,
-
24
,
12
},
{
0xAD78EBC5AC620000
,
3
,
20
},
{
0x813F3978F8940984
,
30
,
28
},
{
0xC097CE7BC90715B3
,
56
,
36
},
{
0x8F7E32CE7BEA5C70
,
83
,
44
},
{
0xD5D238A4ABE98068
,
109
,
52
},
{
0x9F4F2726179A2245
,
136
,
60
},
{
0xED63A231D4C4FB27
,
162
,
68
},
{
0xB0DE65388CC8ADA8
,
189
,
76
},
{
0x83C7088E1AAB65DB
,
216
,
84
},
{
0xC45D1DF942711D9A
,
242
,
92
},
{
0x924D692CA61BE758
,
269
,
100
},
{
0xDA01EE641A708DEA
,
295
,
108
},
{
0xA26DA3999AEF774A
,
322
,
116
},
{
0xF209787BB47D6B85
,
348
,
124
},
{
0xB454E4A179DD1877
,
375
,
132
},
{
0x865B86925B9BC5C2
,
402
,
140
},
{
0xC83553C5C8965D3D
,
428
,
148
},
{
0x952AB45CFA97A0B3
,
455
,
156
},
{
0xDE469FBD99A05FE3
,
481
,
164
},
{
0xA59BC234DB398C25
,
508
,
172
},
{
0xF6C69A72A3989F5C
,
534
,
180
},
{
0xB7DCBF5354E9BECE
,
561
,
188
},
{
0x88FCF317F22241E2
,
588
,
196
},
{
0xCC20CE9BD35C78A5
,
614
,
204
},
{
0x98165AF37B2153DF
,
641
,
212
},
{
0xE2A0B5DC971F303A
,
667
,
220
},
{
0xA8D9D1535CE3B396
,
694
,
228
},
{
0xFB9B7CD9A4A7443C
,
720
,
236
},
{
0xBB764C4CA7A44410
,
747
,
244
},
{
0x8BAB8EEFB6409C1A
,
774
,
252
},
{
0xD01FEF10A657842C
,
800
,
260
},
{
0x9B10A4E5E9913129
,
827
,
268
},
{
0xE7109BFBA19C0C9D
,
853
,
276
},
{
0xAC2820D9623BF429
,
880
,
284
},
{
0x80444B5E7AA7CF85
,
907
,
292
},
{
0xBF21E44003ACDD2D
,
933
,
300
},
{
0x8E679C2F5E44FF8F
,
960
,
308
},
{
0xD433179D9C8CB841
,
986
,
316
},
{
0x9E19DB92B4E31BA9
,
1013
,
324
},
};
// This computation gives exactly the same results for k as
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
// for |e| <= 1500, but doesn't require floating-point operations.
// NB: log_10(2) ~= 78913 / 2^18
assert
(
e
>=
-
1500
);
assert
(
e
<=
1500
);
const
int
f
=
kAlpha
-
e
-
1
;
const
int
k
=
(
f
*
78913
)
/
(
1
<<
18
)
+
(
f
>
0
);
const
int
index
=
(
-
kCachedPowersMinDecExp
+
k
+
(
kCachedPowersDecStep
-
1
))
/
kCachedPowersDecStep
;
assert
(
index
>=
0
);
assert
(
index
<
kCachedPowersSize
);
static_cast
<
void
>
(
kCachedPowersSize
);
// Fix warning.
const
cached_power
cached
=
kCachedPowers
[
index
];
assert
(
kAlpha
<=
cached
.
e
+
e
+
64
);
assert
(
kGamma
>=
cached
.
e
+
e
+
64
);
return
cached
;
}
// For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
// For n == 0, returns 1 and sets pow10 := 1.
inline
int
find_largest_pow10
(
uint32_t
n
,
uint32_t
&
pow10
)
{
if
(
n
>=
1000000000
)
{
pow10
=
1000000000
;
return
10
;
}
if
(
n
>=
100000000
)
{
pow10
=
100000000
;
return
9
;
}
if
(
n
>=
10000000
)
{
pow10
=
10000000
;
return
8
;
}
if
(
n
>=
1000000
)
{
pow10
=
1000000
;
return
7
;
}
if
(
n
>=
100000
)
{
pow10
=
100000
;
return
6
;
}
if
(
n
>=
10000
)
{
pow10
=
10000
;
return
5
;
}
if
(
n
>=
1000
)
{
pow10
=
1000
;
return
4
;
}
if
(
n
>=
100
)
{
pow10
=
100
;
return
3
;
}
if
(
n
>=
10
)
{
pow10
=
10
;
return
2
;
}
pow10
=
1
;
return
1
;
}
inline
void
grisu2_round
(
char
*
buf
,
int
len
,
uint64_t
dist
,
uint64_t
delta
,
uint64_t
rest
,
uint64_t
ten_k
)
{
assert
(
len
>=
1
);
assert
(
dist
<=
delta
);
assert
(
rest
<=
delta
);
assert
(
ten_k
>
0
);
// <--------------------------- delta ---->
// <---- dist --------->
// --------------[------------------+-------------------]--------------
// M- w M+
//
// ten_k
// <------>
// <---- rest ---->
// --------------[------------------+----+--------------]--------------
// w V
// = buf * 10^k
//
// ten_k represents a unit-in-the-last-place in the decimal representation
// stored in buf.
// Decrement buf by ten_k while this takes buf closer to w.
// The tests are written in this order to avoid overflow in unsigned
// integer arithmetic.
while
(
rest
<
dist
and
delta
-
rest
>=
ten_k
and
(
rest
+
ten_k
<
dist
or
dist
-
rest
>
rest
+
ten_k
-
dist
))
{
assert
(
buf
[
len
-
1
]
!=
'0'
);
buf
[
len
-
1
]
--
;
rest
+=
ten_k
;
}
}
// Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
// M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
inline
void
grisu2_digit_gen
(
char
*
buffer
,
int
&
length
,
int
&
decimal_exponent
,
diyfp
M_minus
,
diyfp
w
,
diyfp
M_plus
)
{
static_assert
(
kAlpha
>=
-
60
,
"internal error"
);
static_assert
(
kGamma
<=
-
32
,
"internal error"
);
// Generates the digits (and the exponent) of a decimal floating-point
// number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
// w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
//
// <--------------------------- delta ---->
// <---- dist --------->
// --------------[------------------+-------------------]--------------
// M- w M+
//
// Grisu2 generates the digits of M+ from left to right and stops as soon as
// V is in [M-,M+].
assert
(
M_plus
.
e
>=
kAlpha
);
assert
(
M_plus
.
e
<=
kGamma
);
uint64_t
delta
=
diyfp
::
sub
(
M_plus
,
M_minus
).
f
;
// (significand of (M+ - M-), implicit exponent is e)
uint64_t
dist
=
diyfp
::
sub
(
M_plus
,
w
).
f
;
// (significand of (M+ - w ), implicit exponent is e)
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
//
// M+ = f * 2^e
// = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
// = ((p1 ) * 2^-e + (p2 )) * 2^e
// = p1 + p2 * 2^e
const
diyfp
one
(
uint64_t
{
1
}
<<
-
M_plus
.
e
,
M_plus
.
e
);
uint32_t
p1
=
static_cast
<
uint32_t
>
(
M_plus
.
f
>>
-
one
.
e
);
// p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
uint64_t
p2
=
M_plus
.
f
&
(
one
.
f
-
1
);
// p2 = f mod 2^-e
// 1)
//
// Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
assert
(
p1
>
0
);
uint32_t
pow10
;
const
int
k
=
find_largest_pow10
(
p1
,
pow10
);
// 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
//
// p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
// = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
//
// M+ = p1 + p2 * 2^e
// = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
// = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
// = d[k-1] * 10^(k-1) + ( rest) * 2^e
//
// Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
//
// p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
//
// but stop as soon as
//
// rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
int
n
=
k
;
while
(
n
>
0
)
{
// Invariants:
// M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
// pow10 = 10^(n-1) <= p1 < 10^n
//
const
uint32_t
d
=
p1
/
pow10
;
// d = p1 div 10^(n-1)
const
uint32_t
r
=
p1
%
pow10
;
// r = p1 mod 10^(n-1)
//
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
//
assert
(
d
<=
9
);
buffer
[
length
++
]
=
static_cast
<
char
>
(
'0'
+
d
);
// buffer := buffer * 10 + d
//
// M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
//
p1
=
r
;
n
--
;
//
// M+ = buffer * 10^n + (p1 + p2 * 2^e)
// pow10 = 10^n
//
// Now check if enough digits have been generated.
// Compute
//
// p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
//
// Note:
// Since rest and delta share the same exponent e, it suffices to
// compare the significands.
const
uint64_t
rest
=
(
uint64_t
{
p1
}
<<
-
one
.
e
)
+
p2
;
if
(
rest
<=
delta
)
{
// V = buffer * 10^n, with M- <= V <= M+.
decimal_exponent
+=
n
;
// We may now just stop. But instead look if the buffer could be
// decremented to bring V closer to w.
//
// pow10 = 10^n is now 1 ulp in the decimal representation V.
// The rounding procedure works with diyfp's with an implicit
// exponent of e.
//
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
//
const
uint64_t
ten_n
=
uint64_t
{
pow10
}
<<
-
one
.
e
;
grisu2_round
(
buffer
,
length
,
dist
,
delta
,
rest
,
ten_n
);
return
;
}
pow10
/=
10
;
//
// pow10 = 10^(n-1) <= p1 < 10^n
// Invariants restored.
}
// 2)
//
// The digits of the integral part have been generated:
//
// M+ = d[k-1]...d[1]d[0] + p2 * 2^e
// = buffer + p2 * 2^e
//
// Now generate the digits of the fractional part p2 * 2^e.
//
// Note:
// No decimal point is generated: the exponent is adjusted instead.
//
// p2 actually represents the fraction
//
// p2 * 2^e
// = p2 / 2^-e
// = d[-1] / 10^1 + d[-2] / 10^2 + ...
//
// Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
//
// p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
// + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
//
// using
//
// 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
// = ( d) * 2^-e + ( r)
//
// or
// 10^m * p2 * 2^e = d + r * 2^e
//
// i.e.
//
// M+ = buffer + p2 * 2^e
// = buffer + 10^-m * (d + r * 2^e)
// = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
//
// and stop as soon as 10^-m * r * 2^e <= delta * 2^e
assert
(
p2
>
delta
);
int
m
=
0
;
for
(;;)
{
// Invariant:
// M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
// = buffer * 10^-m + 10^-m * (p2 ) * 2^e
// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
//
assert
(
p2
<=
UINT64_MAX
/
10
);
p2
*=
10
;
const
uint64_t
d
=
p2
>>
-
one
.
e
;
// d = (10 * p2) div 2^-e
const
uint64_t
r
=
p2
&
(
one
.
f
-
1
);
// r = (10 * p2) mod 2^-e
//
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
//
assert
(
d
<=
9
);
buffer
[
length
++
]
=
static_cast
<
char
>
(
'0'
+
d
);
// buffer := buffer * 10 + d
//
// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
//
p2
=
r
;
m
++
;
//
// M+ = buffer * 10^-m + 10^-m * p2 * 2^e
// Invariant restored.
// Check if enough digits have been generated.
//
// 10^-m * p2 * 2^e <= delta * 2^e
// p2 * 2^e <= 10^m * delta * 2^e
// p2 <= 10^m * delta
delta
*=
10
;
dist
*=
10
;
if
(
p2
<=
delta
)
{
break
;
}
}
// V = buffer * 10^-m, with M- <= V <= M+.
decimal_exponent
-=
m
;
// 1 ulp in the decimal representation is now 10^-m.
// Since delta and dist are now scaled by 10^m, we need to do the
// same with ulp in order to keep the units in sync.
//
// 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
//
const
uint64_t
ten_m
=
one
.
f
;
grisu2_round
(
buffer
,
length
,
dist
,
delta
,
p2
,
ten_m
);
// By construction this algorithm generates the shortest possible decimal
// number (Loitsch, Theorem 6.2) which rounds back to w.
// For an input number of precision p, at least
//
// N = 1 + ceil(p * log_10(2))
//
// decimal digits are sufficient to identify all binary floating-point
// numbers (Matula, "In-and-Out conversions").
// This implies that the algorithm does not produce more than N decimal
// digits.
//
// N = 17 for p = 53 (IEEE double precision)
// N = 9 for p = 24 (IEEE single precision)
}
// v = buf * 10^decimal_exponent
// len is the length of the buffer (number of decimal digits)
// The buffer must be large enough, i.e. >= max_digits10.
inline
void
grisu2
(
char
*
buf
,
int
&
len
,
int
&
decimal_exponent
,
diyfp
m_minus
,
diyfp
v
,
diyfp
m_plus
)
{
assert
(
m_plus
.
e
==
m_minus
.
e
);
assert
(
m_plus
.
e
==
v
.
e
);
// --------(-----------------------+-----------------------)-------- (A)
// m- v m+
//
// --------------------(-----------+-----------------------)-------- (B)
// m- v m+
//
// First scale v (and m- and m+) such that the exponent is in the range
// [alpha, gamma].
const
cached_power
cached
=
get_cached_power_for_binary_exponent
(
m_plus
.
e
);
const
diyfp
c_minus_k
(
cached
.
f
,
cached
.
e
);
// = c ~= 10^-k
// The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
const
diyfp
w
=
diyfp
::
mul
(
v
,
c_minus_k
);
const
diyfp
w_minus
=
diyfp
::
mul
(
m_minus
,
c_minus_k
);
const
diyfp
w_plus
=
diyfp
::
mul
(
m_plus
,
c_minus_k
);
// ----(---+---)---------------(---+---)---------------(---+---)----
// w- w w+
// = c*m- = c*v = c*m+
//
// diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
// w+ are now off by a small amount.
// In fact:
//
// w - v * 10^k < 1 ulp
//
// To account for this inaccuracy, add resp. subtract 1 ulp.
//
// --------+---[---------------(---+---)---------------]---+--------
// w- M- w M+ w+
//
// Now any number in [M-, M+] (bounds included) will round to w when input,
// regardless of how the input rounding algorithm breaks ties.
//
// And digit_gen generates the shortest possible such number in [M-, M+].
// Note that this does not mean that Grisu2 always generates the shortest
// possible number in the interval (m-, m+).
const
diyfp
M_minus
(
w_minus
.
f
+
1
,
w_minus
.
e
);
const
diyfp
M_plus
(
w_plus
.
f
-
1
,
w_plus
.
e
);
decimal_exponent
=
-
cached
.
k
;
// = -(-k) = k
grisu2_digit_gen
(
buf
,
len
,
decimal_exponent
,
M_minus
,
w
,
M_plus
);
}
// v = buf * 10^decimal_exponent
// len is the length of the buffer (number of decimal digits)
// The buffer must be large enough, i.e. >= max_digits10.
template
<
typename
FloatType
>
void
grisu2
(
char
*
buf
,
int
&
len
,
int
&
decimal_exponent
,
FloatType
value
)
{
static_assert
(
diyfp
::
kPrecision
>=
std
::
numeric_limits
<
FloatType
>::
digits
+
3
,
"internal error: not enough precision"
);
assert
(
std
::
isfinite
(
value
));
assert
(
value
>
0
);
// If the neighbors (and boundaries) of 'value' are always computed for double-precision
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
// decimal representations are not exactly "short".
//
// The documentation for 'std::to_chars' (http://en.cppreference.com/w/cpp/utility/to_chars)
// says "value is converted to a string as if by std::sprintf in the default ("C") locale"
// and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
// does.
// On the other hand, the documentation for 'std::to_chars' requires that "parsing the
// representation using the corresponding std::from_chars function recovers value exactly". That
// indicates that single precision floating-point numbers should be recovered using
// 'std::strtof'.
//
// NB: If the neighbors are computed for single-precision numbers, there is a single float
// (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
// value is off by 1 ulp.
#if 0
const boundaries w = compute_boundaries(static_cast<double>(value));
#else
const
boundaries
w
=
compute_boundaries
(
value
);
#endif
grisu2
(
buf
,
len
,
decimal_exponent
,
w
.
minus
,
w
.
w
,
w
.
plus
);
}
// Appends a decimal representation of e to buf.
// Returns a pointer to the element following the exponent.
// PRE: -1000 < e < 1000
inline
char
*
append_exponent
(
char
*
buf
,
int
e
)
{
assert
(
e
>
-
1000
);
assert
(
e
<
1000
);
if
(
e
<
0
)
{
e
=
-
e
;
*
buf
++
=
'-'
;
}
else
{
*
buf
++
=
'+'
;
}
uint32_t
k
=
static_cast
<
uint32_t
>
(
e
);
if
(
k
<
10
)
{
// Always print at least two digits in the exponent.
// This is for compatibility with printf("%g").
*
buf
++
=
'0'
;
*
buf
++
=
static_cast
<
char
>
(
'0'
+
k
);
}
else
if
(
k
<
100
)
{
*
buf
++
=
static_cast
<
char
>
(
'0'
+
k
/
10
);
k
%=
10
;
*
buf
++
=
static_cast
<
char
>
(
'0'
+
k
);
}
else
{
*
buf
++
=
static_cast
<
char
>
(
'0'
+
k
/
100
);
k
%=
100
;
*
buf
++
=
static_cast
<
char
>
(
'0'
+
k
/
10
);
k
%=
10
;
*
buf
++
=
static_cast
<
char
>
(
'0'
+
k
);
}
return
buf
;
}
// Prettify v = buf * 10^decimal_exponent
// If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point notation.
// Otherwise it will be printed in exponential notation.
// PRE: min_exp < 0
// PRE: max_exp > 0
inline
char
*
format_buffer
(
char
*
buf
,
int
len
,
int
decimal_exponent
,
int
min_exp
,
int
max_exp
)
{
assert
(
min_exp
<
0
);
assert
(
max_exp
>
0
);
const
int
k
=
len
;
const
int
n
=
len
+
decimal_exponent
;
// v = buf * 10^(n-k)
// k is the length of the buffer (number of decimal digits)
// n is the position of the decimal point relative to the start of the buffer.
if
(
k
<=
n
and
n
<=
max_exp
)
{
// digits[000]
// len <= max_exp + 2
std
::
memset
(
buf
+
k
,
'0'
,
static_cast
<
size_t
>
(
n
-
k
));
// Make it look like a floating-point number (#362, #378)
buf
[
n
+
0
]
=
'.'
;
buf
[
n
+
1
]
=
'0'
;
return
buf
+
(
n
+
2
);
}
if
(
0
<
n
and
n
<=
max_exp
)
{
// dig.its
// len <= max_digits10 + 1
assert
(
k
>
n
);
std
::
memmove
(
buf
+
(
n
+
1
),
buf
+
n
,
static_cast
<
size_t
>
(
k
-
n
));
buf
[
n
]
=
'.'
;
return
buf
+
(
k
+
1
);
}
if
(
min_exp
<
n
and
n
<=
0
)
{
// 0.[000]digits
// len <= 2 + (-min_exp - 1) + max_digits10
std
::
memmove
(
buf
+
(
2
+
-
n
),
buf
,
static_cast
<
size_t
>
(
k
));
buf
[
0
]
=
'0'
;
buf
[
1
]
=
'.'
;
std
::
memset
(
buf
+
2
,
'0'
,
static_cast
<
size_t
>
(
-
n
));
return
buf
+
(
2
+
(
-
n
)
+
k
);
}
if
(
k
==
1
)
{
// dE+123
// len <= 1 + 5
buf
+=
1
;
}
else
{
// d.igitsE+123
// len <= max_digits10 + 1 + 5
std
::
memmove
(
buf
+
2
,
buf
+
1
,
static_cast
<
size_t
>
(
k
-
1
));
buf
[
1
]
=
'.'
;
buf
+=
1
+
k
;
}
*
buf
++
=
'e'
;
return
append_exponent
(
buf
,
n
-
1
);
}
}
// namespace dtoa_impl
// Generates a decimal representation of the floating-point number value in [first, last).
//
// The format of the resulting decimal representation is similar to printf's %g format.
// Returns an iterator pointing past-the-end of the decimal representation.
//
// Note: The input number must be finite, i.e. NaN's and Inf's are not supported.
// Note: The buffer must be large enough.
// Note: The result is NOT null-terminated.
template
<
typename
FloatType
>
char
*
to_chars
(
char
*
first
,
char
*
last
,
FloatType
value
)
{
static_cast
<
void
>
(
last
);
// maybe unused - fix warning
assert
(
std
::
isfinite
(
value
));
// Use signbit(value) instead of (value < 0) since signbit works for -0.
if
(
std
::
signbit
(
value
))
{
value
=
-
value
;
*
first
++
=
'-'
;
}
if
(
value
==
0
)
// +-0
{
*
first
++
=
'0'
;
// Make it look like a floating-point number (#362, #378)
*
first
++
=
'.'
;
*
first
++
=
'0'
;
return
first
;
}
assert
(
last
-
first
>=
std
::
numeric_limits
<
FloatType
>::
max_digits10
);
// Compute v = buffer * 10^decimal_exponent.
// The decimal digits are stored in the buffer, which needs to be interpreted
// as an unsigned decimal integer.
// len is the length of the buffer, i.e. the number of decimal digits.
int
len
=
0
;
int
decimal_exponent
=
0
;
dtoa_impl
::
grisu2
(
first
,
len
,
decimal_exponent
,
value
);
assert
(
len
<=
std
::
numeric_limits
<
FloatType
>::
max_digits10
);
// Format the buffer like printf("%.*g", prec, value)
constexpr
int
kMinExp
=
-
4
;
// Use digits10 here to increase compatibility with version 2.
constexpr
int
kMaxExp
=
std
::
numeric_limits
<
FloatType
>::
digits10
;
assert
(
last
-
first
>=
kMaxExp
+
2
);
assert
(
last
-
first
>=
2
+
(
-
kMinExp
-
1
)
+
std
::
numeric_limits
<
FloatType
>::
max_digits10
);
assert
(
last
-
first
>=
std
::
numeric_limits
<
FloatType
>::
max_digits10
+
6
);
return
dtoa_impl
::
format_buffer
(
first
,
len
,
decimal_exponent
,
kMinExp
,
kMaxExp
);
}
}
// namespace detail
}
// namespace nlohmann
// #include "detail/macro_scope.hpp"
// #include "detail/meta.hpp"
...
...
@@ -7079,12 +8108,34 @@ 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
;
}
// 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 text -> float -> text round-trip
static
constexpr
auto
d
=
std
::
numeric_limits
<
number_float_t
>::
digits10
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment