From 7529af8f991e138669f277c7b8ce2c3d9130aa22 Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Wed, 20 Sep 2023 19:57:55 -0600 Subject: [PATCH] Workaround intel bug (#3652) * Workaround intel bug Potential workaround / restructure for the intel bug that is the cause of #3645. Make the variable in the external struct instead an embedded static constexpr variable in the only function that uses the variable. * Finish the proposed change -- remove struct accessor * Refactor proposed intel fix. Moved variable out of function to avoid specialization on Float. Made it a separate function that is called from format_float. * Fix incorrect function name. * Add missing inline. --- include/fmt/format.h | 48 ++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 66a9e226..30addcb7 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1740,28 +1740,6 @@ FMT_CONSTEXPR inline fp operator*(fp x, fp y) { return {multiply(x.f, y.f), x.e + y.e + 64}; } -template struct basic_data { - // For checking rounding thresholds. - // The kth entry is chosen to be the smallest integer such that the - // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k. - static constexpr uint32_t fractional_part_rounding_thresholds[8] = { - 2576980378U, // ceil(2^31 + 2^32/10^1) - 2190433321U, // ceil(2^31 + 2^32/10^2) - 2151778616U, // ceil(2^31 + 2^32/10^3) - 2147913145U, // ceil(2^31 + 2^32/10^4) - 2147526598U, // ceil(2^31 + 2^32/10^5) - 2147487943U, // ceil(2^31 + 2^32/10^6) - 2147484078U, // ceil(2^31 + 2^32/10^7) - 2147483691U // ceil(2^31 + 2^32/10^8) - }; -}; -// This is a struct rather than an alias to avoid shadowing warnings in gcc. -struct data : basic_data<> {}; - -#if FMT_CPLUSPLUS < 201703L -template -constexpr uint32_t basic_data::fractional_part_rounding_thresholds[]; -#endif template () == num_bits()> using convert_float_result = @@ -3280,9 +3258,27 @@ FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision, format_hexfloat(static_cast(value), precision, specs, buf); } +FMT_CONSTEXPR inline uint32_t fractional_part_rounding_thresholds(int index) { + // For checking rounding thresholds. + // The kth entry is chosen to be the smallest integer such that the + // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k. + constexpr uint32_t thresholds[8] = { + 2576980378U, // ceil(2^31 + 2^32/10^1) + 2190433321U, // ceil(2^31 + 2^32/10^2) + 2151778616U, // ceil(2^31 + 2^32/10^3) + 2147913145U, // ceil(2^31 + 2^32/10^4) + 2147526598U, // ceil(2^31 + 2^32/10^5) + 2147487943U, // ceil(2^31 + 2^32/10^6) + 2147484078U, // ceil(2^31 + 2^32/10^7) + 2147483691U // ceil(2^31 + 2^32/10^8) + }; + return thresholds[index]; +} + template FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, buffer& buf) -> int { + // float is passed as double to reduce the number of instantiations. static_assert(!std::is_same::value, ""); FMT_ASSERT(value >= 0, "value is negative"); @@ -3485,8 +3481,8 @@ FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, if (precision < 9) { uint32_t fractional_part = static_cast(prod); should_round_up = fractional_part >= - data::fractional_part_rounding_thresholds - [8 - number_of_digits_to_print] || + fractional_part_rounding_thresholds + (8 - number_of_digits_to_print) || ((fractional_part >> 31) & ((digits & 1) | (second_third_subsegments != 0) | has_more_segments)) != 0; @@ -3525,8 +3521,8 @@ FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, // consisting of a genuine digit from the input. uint32_t fractional_part = static_cast(prod); should_round_up = fractional_part >= - data::fractional_part_rounding_thresholds - [8 - number_of_digits_to_print] || + fractional_part_rounding_thresholds + (8 - number_of_digits_to_print) || ((fractional_part >> 31) & ((digits & 1) | (third_subsegment != 0) | has_more_segments)) != 0;