31 namespace json_details {
32 namespace eisellemire_details {
38 [[nodiscard]]
constexpr bool
39 try_append_digit( std::uint64_t &value,
unsigned digit )
noexcept {
40 constexpr auto max_value = std::numeric_limits<std::uint64_t>::max( );
41 if( digit > 9U or value > ( max_value - digit ) / 10U ) {
44 value = value * 10U + digit;
48 template<
typename Real>
52 struct binary_format<double> {
53 using uint_type = std::uint64_t;
54 static constexpr std::int32_t mantissa_bits = 52;
55 static constexpr std::int32_t exponent_bias = 1023;
56 static constexpr std::int32_t infinite_power = 0x7FF;
57 static constexpr std::int32_t sign_bit = 63;
58 static constexpr std::int32_t smallest_power_of_ten = -342;
59 static constexpr std::int32_t largest_power_of_ten = 308;
60 static constexpr std::int32_t min_round_to_even = -4;
61 static constexpr std::int32_t max_round_to_even = 23;
65 struct binary_format<float> {
66 using uint_type = std::uint32_t;
67 static constexpr std::int32_t mantissa_bits = 23;
68 static constexpr std::int32_t exponent_bias = 127;
69 static constexpr std::int32_t infinite_power = 0xFF;
70 static constexpr std::int32_t sign_bit = 31;
71 static constexpr std::int32_t smallest_power_of_ten = -64;
72 static constexpr std::int32_t largest_power_of_ten = 38;
73 static constexpr std::int32_t min_round_to_even = -17;
74 static constexpr std::int32_t max_round_to_even = 10;
77 [[nodiscard]]
constexpr uint128
78 full_multiplication_generic( std::uint64_t lhs,
79 std::uint64_t rhs )
noexcept {
80 auto const lhs_hi = lhs >> 32U;
81 auto const lhs_lo = lhs & 0xFFFF'FFFFULL;
82 auto const rhs_hi = rhs >> 32U;
83 auto const rhs_lo = rhs & 0xFFFF'FFFFULL;
85 auto const lhs_hi_rhs_lo = lhs_hi * rhs_lo;
86 auto const lhs_lo_rhs_lo = lhs_lo * rhs_lo;
87 auto const middle = lhs_hi_rhs_lo + lhs_lo * rhs_hi;
88 auto const middle_carry = middle < lhs_hi_rhs_lo;
89 auto const low = lhs_lo_rhs_lo + ( middle << 32U );
91 lhs_hi * rhs_hi + ( middle >> 32U ) +
92 (
static_cast<std::uint64_t
>( middle_carry ) << 32U ) +
93 static_cast<std::uint64_t
>( low < lhs_lo_rhs_lo );
97 [[nodiscard]] DAW_ATTRIB_FLATINLINE
constexpr uint128
98 full_multiplication( std::uint64_t lhs, std::uint64_t rhs )
noexcept {
99#if ( defined( __GNUC__ ) or defined( __clang__ ) ) and \
100 defined( __SIZEOF_INT128__ )
101 if( not DAW_IS_CONSTANT_EVALUATED_COMPAT( ) ) {
102#if defined( __GNUC__ )
103#pragma GCC diagnostic push
104#pragma GCC diagnostic ignored "-Wpedantic"
106 auto const result =
static_cast<unsigned __int128
>( lhs ) * rhs;
107 return {
static_cast<std::uint64_t
>( result ),
108 static_cast<std::uint64_t
>( result >> 64U ) };
109#if defined( __GNUC__ )
110#pragma GCC diagnostic pop
113#elif defined( DAW_HAS_MSVC ) and defined( _M_X64 )
114 if( not DAW_IS_CONSTANT_EVALUATED_COMPAT( ) ) {
116 result.low = _umul128( lhs, rhs, &result.high );
120 return full_multiplication_generic( lhs, rhs );
123 template<
typename Real>
124 [[nodiscard]] DAW_ATTRIB_FLATINLINE
constexpr uint128
125 compute_product( std::int64_t exponent,
126 std::uint64_t significant_digits )
noexcept {
127 auto const index =
static_cast<std::size_t
>(
128 2 * ( exponent - ( -342 ) ) );
130 full_multiplication( significant_digits, pow5_tbl[index] );
134 constexpr std::uint64_t precision_mask =
135 std::numeric_limits<std::uint64_t>::max( ) >>
136 ( binary_format<Real>::mantissa_bits + 3 );
137 if( ( product.high & precision_mask ) == precision_mask ) {
139 full_multiplication( significant_digits, pow5_tbl[index + 1] );
140 product.low += second.high;
142 static_cast<std::uint64_t
>( second.high > product.low );
147 [[nodiscard]]
constexpr std::int32_t
148 binary_power( std::int32_t exponent )
noexcept {
150 return ( ( 217706 * exponent ) >> 16 ) + 63;
164 template<
typename Real =
double>
165 [[nodiscard]] DAW_ATTRIB_FLATINLINE
constexpr Real
166 parse_real_eisellemire(
bool negative, std::int64_t exponent,
167 std::uint64_t significant_digits )
noexcept {
168 static_assert( std::is_same_v<Real, float> or
169 std::is_same_v<Real, double>,
170 "parse_real_lemire supports float and double" );
171 static_assert( std::numeric_limits<Real>::is_iec559 );
172 using format = eisellemire_details::binary_format<Real>;
173 using uint_type =
typename format::uint_type;
175 std::uint64_t mantissa = 0;
176 std::int32_t power2 = 0;
177 if( significant_digits == 0 or
178 exponent < format::smallest_power_of_ten ) {
180 }
else if( exponent > format::largest_power_of_ten ) {
181 power2 = format::infinite_power;
183 auto const leading_zeroes =
static_cast<std::int32_t
>(
184 daw::cxmath::count_leading_zeroes( significant_digits ) );
185 auto const normalized_digits = significant_digits << leading_zeroes;
186 auto const product = eisellemire_details::compute_product<Real>(
187 exponent, normalized_digits );
188 auto const upper_bit =
189 static_cast<std::int32_t
>( product.high >> 63U );
190 auto const shift = upper_bit + 64 - format::mantissa_bits - 3;
192 mantissa = product.high >> shift;
193 power2 = eisellemire_details::binary_power(
194 static_cast<std::int32_t
>( exponent ) ) +
195 upper_bit - leading_zeroes + format::exponent_bias;
198 if( -power2 + 1 >= 64 ) {
202 mantissa >>= -power2 + 1;
203 mantissa += mantissa & 1U;
206 mantissa < ( std::uint64_t{ 1 } << format::mantissa_bits ) ? 0
212 if( product.low <= 1 and exponent >= format::min_round_to_even and
213 exponent <= format::max_round_to_even and
214 ( mantissa & 3U ) == 1U and
215 ( mantissa << shift ) == product.high ) {
216 mantissa &=
~std::uint64_t{ 1 };
218 mantissa += mantissa & 1U;
220 if( mantissa >= ( std::uint64_t{ 2 } << format::mantissa_bits ) ) {
221 mantissa = std::uint64_t{ 1 } << format::mantissa_bits;
224 mantissa &= ~( std::uint64_t{ 1 } << format::mantissa_bits );
225 if( power2 >= format::infinite_power ) {
227 power2 = format::infinite_power;
232 auto const bits =
static_cast<uint_type
>(
234 (
static_cast<std::uint64_t
>( power2 ) << format::mantissa_bits ) |
235 (
static_cast<std::uint64_t
>( negative ) << format::sign_bit ) );
236 return DAW_BIT_CAST( Real, bits );