32 namespace json_details {
33 namespace eisellemire_details {
39 [[nodiscard]]
constexpr bool
40 try_append_digit( std::uint64_t &value,
unsigned digit )
noexcept {
41 DAW_CPP23_STATIC_LOCAL
constexpr auto max_value =
42 daw::max_value<std::uint64_t>;
43 if( digit > 9U or value > ( max_value - digit ) / 10U ) {
46 value = value * 10U + digit;
53 template<
typename Real>
54 struct binary_format {
55 static_assert( std::numeric_limits<Real>::is_iec559 and
56 std::numeric_limits<Real>::radix == 2,
57 "Only IEEE754 binary formats are supported" );
58 using uint_type = std::conditional_t<
59 sizeof( Real ) == 2, std::uint16_t,
60 std::conditional_t<
sizeof( Real ) == 4, std::uint32_t,
62 static_assert(
sizeof( Real ) ==
sizeof( uint_type ),
63 "Formats wider than 64 bits are not supported" );
64 static constexpr std::int32_t mantissa_bits =
65 std::numeric_limits<Real>::digits - 1;
66 static constexpr std::int32_t exponent_bias =
67 std::numeric_limits<Real>::max_exponent - 1;
68 static constexpr std::int32_t infinite_power =
69 2 * std::numeric_limits<Real>::max_exponent - 1;
70 static constexpr std::int32_t sign_bit =
71 static_cast<std::int32_t
>(
sizeof( Real ) * 8U - 1U );
75 struct binary_format<double> {
76 using uint_type = std::uint64_t;
77 static constexpr std::int32_t mantissa_bits = 52;
78 static constexpr std::int32_t exponent_bias = 1023;
79 static constexpr std::int32_t infinite_power = 0x7FF;
80 static constexpr std::int32_t sign_bit = 63;
81 static constexpr std::int32_t smallest_power_of_ten = -342;
82 static constexpr std::int32_t largest_power_of_ten = 308;
83 static constexpr std::int32_t min_round_to_even = -4;
84 static constexpr std::int32_t max_round_to_even = 23;
88 struct binary_format<float> {
89 using uint_type = std::uint32_t;
90 static constexpr std::int32_t mantissa_bits = 23;
91 static constexpr std::int32_t exponent_bias = 127;
92 static constexpr std::int32_t infinite_power = 0xFF;
93 static constexpr std::int32_t sign_bit = 31;
94 static constexpr std::int32_t smallest_power_of_ten = -64;
95 static constexpr std::int32_t largest_power_of_ten = 38;
96 static constexpr std::int32_t min_round_to_even = -17;
97 static constexpr std::int32_t max_round_to_even = 10;
100 [[nodiscard]]
constexpr uint128
101 full_multiplication_generic( std::uint64_t lhs,
102 std::uint64_t rhs )
noexcept {
103 auto const lhs_hi = lhs >> 32U;
104 auto const lhs_lo = lhs & 0xFFFF'FFFFULL;
105 auto const rhs_hi = rhs >> 32U;
106 auto const rhs_lo = rhs & 0xFFFF'FFFFULL;
108 auto const lhs_hi_rhs_lo = lhs_hi * rhs_lo;
109 auto const lhs_lo_rhs_lo = lhs_lo * rhs_lo;
110 auto const middle = lhs_hi_rhs_lo + lhs_lo * rhs_hi;
111 auto const middle_carry = middle < lhs_hi_rhs_lo;
112 auto const low = lhs_lo_rhs_lo + ( middle << 32U );
114 lhs_hi * rhs_hi + ( middle >> 32U ) +
115 (
static_cast<std::uint64_t
>( middle_carry ) << 32U ) +
116 static_cast<std::uint64_t
>( low < lhs_lo_rhs_lo );
117 return { low, high };
120 [[nodiscard]] DAW_ATTRIB_FLATINLINE
constexpr uint128
121 full_multiplication( std::uint64_t lhs, std::uint64_t rhs )
noexcept {
122#if ( defined( __GNUC__ ) or defined( __clang__ ) ) and \
123 defined( __SIZEOF_INT128__ )
124 if( not DAW_IS_CONSTANT_EVALUATED_COMPAT( ) ) {
125#if defined( __GNUC__ )
126#pragma GCC diagnostic push
127#pragma GCC diagnostic ignored "-Wpedantic"
129 auto const result =
static_cast<unsigned __int128
>( lhs ) * rhs;
130 return {
static_cast<std::uint64_t
>( result ),
131 static_cast<std::uint64_t
>( result >> 64U ) };
132#if defined( __GNUC__ )
133#pragma GCC diagnostic pop
136#elif defined( DAW_HAS_MSVC ) and defined( _M_X64 )
137 if( not DAW_IS_CONSTANT_EVALUATED_COMPAT( ) ) {
139 result.low = _umul128( lhs, rhs, &result.high );
143 return full_multiplication_generic( lhs, rhs );
146 template<
typename Real>
147 [[nodiscard]] DAW_ATTRIB_FLATINLINE
constexpr uint128
148 compute_product( std::int64_t exponent,
149 std::uint64_t significant_digits )
noexcept {
150 auto const index =
static_cast<std::size_t
>(
151 2 * ( exponent - ( -342 ) ) );
153 full_multiplication( significant_digits, pow5_tbl[index] );
157 DAW_CPP23_STATIC_LOCAL
constexpr std::uint64_t precision_mask =
158 daw::max_value<std::uint64_t> >>
159 ( binary_format<Real>::mantissa_bits + 3 );
160 if( ( product.high & precision_mask ) == precision_mask ) {
162 full_multiplication( significant_digits, pow5_tbl[index + 1] );
163 product.low += second.high;
165 static_cast<std::uint64_t
>( second.high > product.low );
170 [[nodiscard]]
constexpr std::int32_t
171 binary_power( std::int32_t exponent )
noexcept {
173 return ( ( 217706 * exponent ) >> 16 ) + 63;
180 template<
typename Real>
181 inline constexpr bool is_double_sized_long_double_v =
182 std::is_same_v<Real, long double> and
183 sizeof(
long double ) ==
sizeof(
double ) and
184 daw::digits<long double> ==
185 daw::digits<double> and
186 std::numeric_limits<long double>::max_exponent ==
187 std::numeric_limits<double>::max_exponent;
189 namespace eisellemire_details {
190 template<
typename Real,
typename Format>
191 inline constexpr bool has_same_format_v =
192 std::numeric_limits<Real>::is_iec559 and
193 std::numeric_limits<Real>::radix == 2 and
194 std::numeric_limits<Real>::digits ==
195 std::numeric_limits<Format>::digits and
196 std::numeric_limits<Real>::max_exponent ==
197 std::numeric_limits<Format>::max_exponent and
198 std::numeric_limits<Real>::min_exponent ==
199 std::numeric_limits<Format>::min_exponent;
201 template<
typename Real,
bool = std::is_
floating_po
int_v<Real>>
202 struct lemire_compute {
206 template<
typename Real>
207 struct lemire_compute<Real, true> {
208 using type = std::conditional_t<
209 has_same_format_v<Real, float>, float,
210 std::conditional_t<has_same_format_v<Real, double>, double,
void>>;
218 template<
typename Real>
219 using lemire_compute_t =
220 typename eisellemire_details::lemire_compute<Real>::type;
222 template<
typename Real>
223 inline constexpr bool is_lemire_capable_v =
224 not std::is_void_v<lemire_compute_t<Real>>;
236 template<
typename Real =
double>
237 [[nodiscard]] DAW_ATTRIB_FLATINLINE
constexpr Real
238 parse_real_eisellemire(
bool negative, std::int64_t exponent,
239 std::uint64_t significant_digits )
noexcept {
240 static_assert( std::is_same_v<Real, float> or
241 std::is_same_v<Real, double>,
242 "parse_real_lemire supports float and double" );
243 static_assert( std::numeric_limits<Real>::is_iec559 );
244 using format = eisellemire_details::binary_format<Real>;
245 using uint_type =
typename format::uint_type;
247 std::uint64_t mantissa = 0;
248 std::int32_t power2 = 0;
249 if( significant_digits == 0 or
250 exponent < format::smallest_power_of_ten ) {
252 }
else if( exponent > format::largest_power_of_ten ) {
253 power2 = format::infinite_power;
255 auto const leading_zeroes =
static_cast<std::int32_t
>(
256 daw::cxmath::count_leading_zeroes( significant_digits ) );
257 auto const normalized_digits = significant_digits << leading_zeroes;
258 auto const product = eisellemire_details::compute_product<Real>(
259 exponent, normalized_digits );
260 auto const upper_bit =
261 static_cast<std::int32_t
>( product.high >> 63U );
262 auto const shift = upper_bit + 64 - format::mantissa_bits - 3;
264 mantissa = product.high >> shift;
265 power2 = eisellemire_details::binary_power(
266 static_cast<std::int32_t
>( exponent ) ) +
267 upper_bit - leading_zeroes + format::exponent_bias;
270 if( -power2 + 1 >= 64 ) {
274 mantissa >>= -power2 + 1;
275 mantissa += mantissa & 1U;
278 mantissa < ( std::uint64_t{ 1 } << format::mantissa_bits ) ? 0
284 if( product.low <= 1 and exponent >= format::min_round_to_even and
285 exponent <= format::max_round_to_even and
286 ( mantissa & 3U ) == 1U and
287 ( mantissa << shift ) == product.high ) {
288 mantissa &=
~std::uint64_t{ 1 };
290 mantissa += mantissa & 1U;
292 if( mantissa >= ( std::uint64_t{ 2 } << format::mantissa_bits ) ) {
293 mantissa = std::uint64_t{ 1 } << format::mantissa_bits;
296 mantissa &= ~( std::uint64_t{ 1 } << format::mantissa_bits );
297 if( power2 >= format::infinite_power ) {
299 power2 = format::infinite_power;
304 auto const bits =
static_cast<uint_type
>(
306 (
static_cast<std::uint64_t
>( power2 ) << format::mantissa_bits ) |
307 (
static_cast<std::uint64_t
>( negative ) << format::sign_bit ) );
308 return DAW_BIT_CAST( Real, bits );