123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- #ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_DECIMAL_TO_BINARY_HPP
- #define BOOST_CHARCONV_DETAIL_FASTFLOAT_DECIMAL_TO_BINARY_HPP
- #include <boost/charconv/detail/fast_float/float_common.hpp>
- #include <boost/charconv/detail/fast_float/fast_table.hpp>
- #include <cfloat>
- #include <cinttypes>
- #include <cmath>
- #include <cstdint>
- #include <cstdlib>
- #include <cstring>
- namespace boost { namespace charconv { namespace detail { namespace fast_float {
- template <int bit_precision>
- BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
- value128 compute_product_approximation(int64_t q, uint64_t w) {
- const int index = 2 * int(q - powers::smallest_power_of_five);
-
-
-
- value128 firstproduct = full_multiplication(w, powers::power_of_five_128[index]);
- static_assert((bit_precision >= 0) && (bit_precision <= 64), " precision should be in (0,64]");
- constexpr uint64_t precision_mask = (bit_precision < 64) ?
- (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision)
- : uint64_t(0xFFFFFFFFFFFFFFFF);
- if((firstproduct.high & precision_mask) == precision_mask) {
-
- value128 secondproduct = full_multiplication(w, powers::power_of_five_128[index + 1]);
- firstproduct.low += secondproduct.high;
- if(secondproduct.high > firstproduct.low) {
- firstproduct.high++;
- }
- }
- return firstproduct;
- }
- namespace detail {
- constexpr BOOST_FORCEINLINE int32_t power(int32_t q) noexcept {
- return (((152170 + 65536) * q) >> 16) + 63;
- }
- }
- template <typename binary>
- BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
- adjusted_mantissa compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept {
- int hilz = int(w >> 63) ^ 1;
- adjusted_mantissa answer;
- answer.mantissa = w << hilz;
- int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent();
- answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 + invalid_am_bias);
- return answer;
- }
- template <typename binary>
- BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
- adjusted_mantissa compute_error(int64_t q, uint64_t w) noexcept {
- int lz = leading_zeroes(w);
- w <<= lz;
- value128 product = compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
- return compute_error_scaled<binary>(q, product.high, lz);
- }
- template <typename binary>
- BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
- adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
- adjusted_mantissa answer;
- if ((w == 0) || (q < binary::smallest_power_of_ten())) {
- answer.power2 = 0;
- answer.mantissa = 0;
-
- return answer;
- }
- if (q > binary::largest_power_of_ten()) {
-
- answer.power2 = binary::infinite_power();
- answer.mantissa = 0;
- return answer;
- }
-
-
- int lz = leading_zeroes(w);
- w <<= lz;
-
-
-
-
- value128 product = compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
-
-
-
-
-
-
-
-
- int upperbit = int(product.high >> 63);
- answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3);
- answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz - binary::minimum_exponent());
- if (answer.power2 <= 0) {
-
- if(-answer.power2 + 1 >= 64) {
- answer.power2 = 0;
- answer.mantissa = 0;
-
- return answer;
- }
-
- answer.mantissa >>= -answer.power2 + 1;
-
-
- answer.mantissa += (answer.mantissa & 1);
- answer.mantissa >>= 1;
-
-
-
-
-
-
-
- answer.power2 = (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) ? 0 : 1;
- return answer;
- }
-
-
-
- if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && (q <= binary::max_exponent_round_to_even()) &&
- ((answer.mantissa & 3) == 1) ) {
-
-
-
- if((answer.mantissa << (upperbit + 64 - binary::mantissa_explicit_bits() - 3)) == product.high) {
- answer.mantissa &= ~uint64_t(1);
- }
- }
- answer.mantissa += (answer.mantissa & 1);
- answer.mantissa >>= 1;
- if (answer.mantissa >= (uint64_t(2) << binary::mantissa_explicit_bits())) {
- answer.mantissa = (uint64_t(1) << binary::mantissa_explicit_bits());
- answer.power2++;
- }
- answer.mantissa &= ~(uint64_t(1) << binary::mantissa_explicit_bits());
- if (answer.power2 >= binary::infinite_power()) {
- answer.power2 = binary::infinite_power();
- answer.mantissa = 0;
- }
- return answer;
- }
- }}}}
- #endif
|