| 3070 | // Formats a floating-point number using the hexfloat format. |
| 3071 | template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)> |
| 3072 | FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs, |
| 3073 | buffer<char>& buf) { |
| 3074 | // float is passed as double to reduce the number of instantiations and to |
| 3075 | // simplify implementation. |
| 3076 | static_assert(!std::is_same<Float, float>::value, ""); |
| 3077 | |
| 3078 | using info = dragonbox::float_info<Float>; |
| 3079 | |
| 3080 | // Assume Float is in the format [sign][exponent][significand]. |
| 3081 | using carrier_uint = typename info::carrier_uint; |
| 3082 | |
| 3083 | const auto num_float_significand_bits = detail::num_significand_bits<Float>(); |
| 3084 | |
| 3085 | basic_fp<carrier_uint> f(value); |
| 3086 | f.e += num_float_significand_bits; |
| 3087 | if (!has_implicit_bit<Float>()) --f.e; |
| 3088 | |
| 3089 | const auto num_fraction_bits = |
| 3090 | num_float_significand_bits + (has_implicit_bit<Float>() ? 1 : 0); |
| 3091 | const auto num_xdigits = (num_fraction_bits + 3) / 4; |
| 3092 | |
| 3093 | const auto leading_shift = ((num_xdigits - 1) * 4); |
| 3094 | const auto leading_mask = carrier_uint(0xF) << leading_shift; |
| 3095 | const auto leading_xdigit = |
| 3096 | static_cast<uint32_t>((f.f & leading_mask) >> leading_shift); |
| 3097 | if (leading_xdigit > 1) f.e -= (32 - countl_zero(leading_xdigit) - 1); |
| 3098 | |
| 3099 | int print_xdigits = num_xdigits - 1; |
| 3100 | if (specs.precision >= 0 && print_xdigits > specs.precision) { |
| 3101 | const int shift = ((print_xdigits - specs.precision - 1) * 4); |
| 3102 | const auto mask = carrier_uint(0xF) << shift; |
| 3103 | const auto v = static_cast<uint32_t>((f.f & mask) >> shift); |
| 3104 | |
| 3105 | if (v >= 8) { |
| 3106 | const auto inc = carrier_uint(1) << (shift + 4); |
| 3107 | f.f += inc; |
| 3108 | f.f &= ~(inc - 1); |
| 3109 | } |
| 3110 | |
| 3111 | // Check long double overflow |
| 3112 | if (!has_implicit_bit<Float>()) { |
| 3113 | const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; |
| 3114 | if ((f.f & implicit_bit) == implicit_bit) { |
| 3115 | f.f >>= 4; |
| 3116 | f.e += 4; |
| 3117 | } |
| 3118 | } |
| 3119 | |
| 3120 | print_xdigits = specs.precision; |
| 3121 | } |
| 3122 | |
| 3123 | char xdigits[num_bits<carrier_uint>() / 4]; |
| 3124 | detail::fill_n(xdigits, sizeof(xdigits), '0'); |
| 3125 | format_base2e(4, xdigits, f.f, num_xdigits, specs.upper()); |
| 3126 | |
| 3127 | // Remove zero tail |
| 3128 | while (print_xdigits > 0 && xdigits[print_xdigits] == '0') --print_xdigits; |
| 3129 |
nothing calls this directly
no test coverage detected