| 2918 | // Formats a floating-point number using the hexfloat format. |
| 2919 | template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)> |
| 2920 | FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision, float_specs specs, buffer<char>& buf) { |
| 2921 | // float is passed as double to reduce the number of instantiations and to |
| 2922 | // simplify implementation. |
| 2923 | static_assert(!std::is_same<Float, float>::value, ""); |
| 2924 | |
| 2925 | using info = dragonbox::float_info<Float>; |
| 2926 | |
| 2927 | // Assume Float is in the format [sign][exponent][significand]. |
| 2928 | using carrier_uint = typename info::carrier_uint; |
| 2929 | |
| 2930 | constexpr auto num_float_significand_bits = detail::num_significand_bits<Float>(); |
| 2931 | |
| 2932 | basic_fp<carrier_uint> f(value); |
| 2933 | f.e += num_float_significand_bits; |
| 2934 | if (!has_implicit_bit<Float>()) --f.e; |
| 2935 | |
| 2936 | constexpr auto num_fraction_bits = num_float_significand_bits + (has_implicit_bit<Float>() ? 1 : 0); |
| 2937 | constexpr auto num_xdigits = (num_fraction_bits + 3) / 4; |
| 2938 | |
| 2939 | constexpr auto leading_shift = ((num_xdigits - 1) * 4); |
| 2940 | const auto leading_mask = carrier_uint(0xF) << leading_shift; |
| 2941 | const auto leading_xdigit = static_cast<uint32_t>((f.f & leading_mask) >> leading_shift); |
| 2942 | if (leading_xdigit > 1) f.e -= (32 - countl_zero(leading_xdigit) - 1); |
| 2943 | |
| 2944 | int print_xdigits = num_xdigits - 1; |
| 2945 | if (precision >= 0 && print_xdigits > precision) { |
| 2946 | const int shift = ((print_xdigits - precision - 1) * 4); |
| 2947 | const auto mask = carrier_uint(0xF) << shift; |
| 2948 | const auto v = static_cast<uint32_t>((f.f & mask) >> shift); |
| 2949 | |
| 2950 | if (v >= 8) { |
| 2951 | const auto inc = carrier_uint(1) << (shift + 4); |
| 2952 | f.f += inc; |
| 2953 | f.f &= ~(inc - 1); |
| 2954 | } |
| 2955 | |
| 2956 | // Check long double overflow |
| 2957 | if (!has_implicit_bit<Float>()) { |
| 2958 | const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; |
| 2959 | if ((f.f & implicit_bit) == implicit_bit) { |
| 2960 | f.f >>= 4; |
| 2961 | f.e += 4; |
| 2962 | } |
| 2963 | } |
| 2964 | |
| 2965 | print_xdigits = precision; |
| 2966 | } |
| 2967 | |
| 2968 | char xdigits[num_bits<carrier_uint>() / 4]; |
| 2969 | detail::fill_n(xdigits, sizeof(xdigits), '0'); |
| 2970 | format_uint<4>(xdigits, f.f, num_xdigits, specs.upper); |
| 2971 | |
| 2972 | // Remove zero tail |
| 2973 | while (print_xdigits > 0 && xdigits[print_xdigits] == '0') --print_xdigits; |
| 2974 | |
| 2975 | buf.push_back('0'); |
| 2976 | buf.push_back(specs.upper ? 'X' : 'x'); |
| 2977 | buf.push_back(xdigits[0]); |
nothing calls this directly
no test coverage detected