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;
50 template<
typename Real>
54 struct binary_format<double> {
55 using uint_type = std::uint64_t;
56 static constexpr std::int32_t mantissa_bits = 52;
57 static constexpr std::int32_t exponent_bias = 1023;
58 static constexpr std::int32_t infinite_power = 0x7FF;
59 static constexpr std::int32_t sign_bit = 63;
60 static constexpr std::int32_t smallest_power_of_ten = -342;
61 static constexpr std::int32_t largest_power_of_ten = 308;
62 static constexpr std::int32_t min_round_to_even = -4;
63 static constexpr std::int32_t max_round_to_even = 23;
67 struct binary_format<float> {
68 using uint_type = std::uint32_t;
69 static constexpr std::int32_t mantissa_bits = 23;
70 static constexpr std::int32_t exponent_bias = 127;
71 static constexpr std::int32_t infinite_power = 0xFF;
72 static constexpr std::int32_t sign_bit = 31;
73 static constexpr std::int32_t smallest_power_of_ten = -64;
74 static constexpr std::int32_t largest_power_of_ten = 38;
75 static constexpr std::int32_t min_round_to_even = -17;
76 static constexpr std::int32_t max_round_to_even = 10;
79 [[nodiscard]]
constexpr uint128
80 full_multiplication_generic( std::uint64_t lhs,
81 std::uint64_t rhs )
noexcept {
82 auto const lhs_hi = lhs >> 32U;
83 auto const lhs_lo = lhs & 0xFFFF'FFFFULL;
84 auto const rhs_hi = rhs >> 32U;
85 auto const rhs_lo = rhs & 0xFFFF'FFFFULL;
87 auto const lhs_hi_rhs_lo = lhs_hi * rhs_lo;
88 auto const lhs_lo_rhs_lo = lhs_lo * rhs_lo;
89 auto const middle = lhs_hi_rhs_lo + lhs_lo * rhs_hi;
90 auto const middle_carry = middle < lhs_hi_rhs_lo;
91 auto const low = lhs_lo_rhs_lo + ( middle << 32U );
93 lhs_hi * rhs_hi + ( middle >> 32U ) +
94 (
static_cast<std::uint64_t
>( middle_carry ) << 32U ) +
95 static_cast<std::uint64_t
>( low < lhs_lo_rhs_lo );
99 [[nodiscard]] DAW_ATTRIB_FLATINLINE
constexpr uint128
100 full_multiplication( std::uint64_t lhs, std::uint64_t rhs )
noexcept {
101#if ( defined( __GNUC__ ) or defined( __clang__ ) ) and \
102 defined( __SIZEOF_INT128__ )
103 if( not DAW_IS_CONSTANT_EVALUATED_COMPAT( ) ) {
104#if defined( __GNUC__ )
105#pragma GCC diagnostic push
106#pragma GCC diagnostic ignored "-Wpedantic"
108 auto const result =
static_cast<unsigned __int128
>( lhs ) * rhs;
109 return {
static_cast<std::uint64_t
>( result ),
110 static_cast<std::uint64_t
>( result >> 64U ) };
111#if defined( __GNUC__ )
112#pragma GCC diagnostic pop
115#elif defined( DAW_HAS_MSVC ) and defined( _M_X64 )
116 if( not DAW_IS_CONSTANT_EVALUATED_COMPAT( ) ) {
118 result.low = _umul128( lhs, rhs, &result.high );
122 return full_multiplication_generic( lhs, rhs );
125 template<
typename Real>
126 [[nodiscard]] DAW_ATTRIB_FLATINLINE
constexpr uint128
127 compute_product( std::int64_t exponent,
128 std::uint64_t significant_digits )
noexcept {
129 auto const index =
static_cast<std::size_t
>(
130 2 * ( exponent - ( -342 ) ) );
132 full_multiplication( significant_digits, pow5_tbl[index] );
136 DAW_CPP23_STATIC_LOCAL
constexpr std::uint64_t precision_mask =
137 daw::max_value<std::uint64_t> >>
138 ( binary_format<Real>::mantissa_bits + 3 );
139 if( ( product.high & precision_mask ) == precision_mask ) {
141 full_multiplication( significant_digits, pow5_tbl[index + 1] );
142 product.low += second.high;
144 static_cast<std::uint64_t
>( second.high > product.low );
149 [[nodiscard]]
constexpr std::int32_t
150 binary_power( std::int32_t exponent )
noexcept {
152 return ( ( 217706 * exponent ) >> 16 ) + 63;
159 template<
typename Real>
160 inline constexpr bool is_double_sized_long_double_v =
161 std::is_same_v<Real, long double> and
162 sizeof(
long double ) ==
sizeof(
double ) and
163 daw::digits<long double> ==
164 daw::digits<double> and
165 std::numeric_limits<long double>::max_exponent ==
166 std::numeric_limits<double>::max_exponent;
178 template<
typename Real =
double>
179 [[nodiscard]] DAW_ATTRIB_FLATINLINE
constexpr Real
180 parse_real_eisellemire(
bool negative, std::int64_t exponent,
181 std::uint64_t significant_digits )
noexcept {
182 static_assert( std::is_same_v<Real, float> or
183 std::is_same_v<Real, double>,
184 "parse_real_lemire supports float and double" );
185 static_assert( std::numeric_limits<Real>::is_iec559 );
186 using format = eisellemire_details::binary_format<Real>;
187 using uint_type =
typename format::uint_type;
189 std::uint64_t mantissa = 0;
190 std::int32_t power2 = 0;
191 if( significant_digits == 0 or
192 exponent < format::smallest_power_of_ten ) {
194 }
else if( exponent > format::largest_power_of_ten ) {
195 power2 = format::infinite_power;
197 auto const leading_zeroes =
static_cast<std::int32_t
>(
198 daw::cxmath::count_leading_zeroes( significant_digits ) );
199 auto const normalized_digits = significant_digits << leading_zeroes;
200 auto const product = eisellemire_details::compute_product<Real>(
201 exponent, normalized_digits );
202 auto const upper_bit =
203 static_cast<std::int32_t
>( product.high >> 63U );
204 auto const shift = upper_bit + 64 - format::mantissa_bits - 3;
206 mantissa = product.high >> shift;
207 power2 = eisellemire_details::binary_power(
208 static_cast<std::int32_t
>( exponent ) ) +
209 upper_bit - leading_zeroes + format::exponent_bias;
212 if( -power2 + 1 >= 64 ) {
216 mantissa >>= -power2 + 1;
217 mantissa += mantissa & 1U;
220 mantissa < ( std::uint64_t{ 1 } << format::mantissa_bits ) ? 0
226 if( product.low <= 1 and exponent >= format::min_round_to_even and
227 exponent <= format::max_round_to_even and
228 ( mantissa & 3U ) == 1U and
229 ( mantissa << shift ) == product.high ) {
230 mantissa &=
~std::uint64_t{ 1 };
232 mantissa += mantissa & 1U;
234 if( mantissa >= ( std::uint64_t{ 2 } << format::mantissa_bits ) ) {
235 mantissa = std::uint64_t{ 1 } << format::mantissa_bits;
238 mantissa &= ~( std::uint64_t{ 1 } << format::mantissa_bits );
239 if( power2 >= format::infinite_power ) {
241 power2 = format::infinite_power;
246 auto const bits =
static_cast<uint_type
>(
248 (
static_cast<std::uint64_t
>( power2 ) << format::mantissa_bits ) |
249 (
static_cast<std::uint64_t
>( negative ) << format::sign_bit ) );
250 return DAW_BIT_CAST( Real, bits );