make it build
diff --git a/include/fast_float/digit_comparison.h b/include/fast_float/digit_comparison.h index 303fff9..0c170b9 100644 --- a/include/fast_float/digit_comparison.h +++ b/include/fast_float/digit_comparison.h
@@ -72,7 +72,7 @@ binary_format<T>::minimum_exponent(); equiv_uint bits; #if FASTFLOAT_HAS_BIT_CAST - bits = std::bit_cast<equiv_uint>(value); + bits = bit_cast<equiv_uint>(value); #else ::memcpy(&bits, &value, sizeof(T)); #endif
diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 6c96c9f..fb60416 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h
@@ -212,6 +212,89 @@ ; } +union float_union { + float f; + uint32_t bits; +}; + +union double_union { + double f; + uint64_t bits; +}; + +template <typename T, typename U> +constexpr T bit_cast(const U &u); + +template<> +fastfloat_really_inline constexpr float bit_cast(const uint32_t &u) { + float_union fu; + fu.bits = u; + return fu.f; +} + +template<> +fastfloat_really_inline constexpr double bit_cast(const uint64_t &u) { + double_union fu; + fu.bits = u; + return fu.f; +} + +template<> +fastfloat_really_inline constexpr uint32_t bit_cast(const float &u) { + float_union fu; + fu.f = u; + return fu.bits; +} + +template<> +fastfloat_really_inline constexpr uint64_t bit_cast(const double &u) { + double_union fu; + fu.f = u; + return fu.bits; +} + +#ifdef __STDCPP_FLOAT16_T__ +union float16_union { + std::float16_t f; + uint16_t bits; +}; + +template<> +fastfloat_really_inline constexpr uint16_t bit_cast(const std::float16_t &u) { + float16_union fu; + fu.f = u; + return fu.bits; +} + +template<> +fastfloat_really_inline constexpr std::float16_t bit_cast(const uint16_t &u) { + float16_union fu; + fu.bits = u; + return fu.f; +} +#endif // __STDCPP_FLOAT16_T__ +#ifdef __STDCPP_BFLOAT16_T__ +union bfloat16_union { + std::bfloat16_t f; + uint16_t bits; +}; + +template<> +fastfloat_really_inline constexpr uint16_t bit_cast(const std::bfloat16_t &u) { + bfloat16_union fu; + fu.f = u; + return fu.bits; +} + +template<> +fastfloat_really_inline constexpr std::bfloat16_t bit_cast(const uint16_t &u) { + bfloat16_union fu; + fu.bits = u; + return fu.f; +} +#endif // __STDCPP_BFLOAT16_T__ + + template <typename UC> fastfloat_really_inline constexpr bool is_supported_char_type() { return std::is_same<UC, char>::value || std::is_same<UC, wchar_t>::value || @@ -384,7 +467,7 @@ template <typename T> struct binary_format : binary_format_lookup_tables<T> { using equiv_uint = - typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type; + typename std::conditional<sizeof(T) == 2, uint16_t, typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type>::type; static inline constexpr int mantissa_explicit_bits(); static inline constexpr int minimum_exponent(); @@ -566,10 +649,9 @@ // credit: Jakub Jelínek #ifdef __STDCPP_FLOAT16_T__ - template <typename U> struct binary_format_lookup_tables<std::float16_t, U> { - static constexpr std::float16_t powers_of_ten[] = {}; - static constexpr uint64_t max_mantissa[] = {}; + static constexpr std::float16_t powers_of_ten[] = {1};// todo: fix this + static constexpr uint64_t max_mantissa[] = {1};// todo: fix this }; template <typename U> @@ -581,6 +663,30 @@ binary_format_lookup_tables<std::float16_t, U>::max_mantissa[]; template <> +inline constexpr std::float16_t +binary_format<std::float16_t>::exact_power_of_ten(int64_t power) { + return powers_of_ten[power]; +} + +template <> +inline constexpr binary_format<std::float16_t>::equiv_uint +binary_format<std::float16_t>::exponent_mask() { + return 0x7C00; +} + +template <> +inline constexpr binary_format<std::float16_t>::equiv_uint +binary_format<std::float16_t>::mantissa_mask() { + return 0x03FF; +} + +template <> +inline constexpr binary_format<std::float16_t>::equiv_uint +binary_format<std::float16_t>::hidden_bit_mask() { + return 0x0400; +} + +template <> inline constexpr int binary_format<std::float16_t>::max_exponent_fast_path() { return 0; } @@ -592,6 +698,12 @@ } template <> +inline constexpr uint64_t +binary_format<std::float16_t>::max_mantissa_fast_path(int64_t power) { + return max_mantissa[power]; +} + +template <> inline constexpr int binary_format<std::float16_t>::min_exponent_fast_path() { return 0; } @@ -640,11 +752,10 @@ // credit: Jakub Jelínek #ifdef __STDCPP_BFLOAT16_T__ - template <typename U> struct binary_format_lookup_tables<std::bfloat16_t, U> { - static constexpr std::bfloat16_t powers_of_ten[] = {}; + static constexpr std::bfloat16_t powers_of_ten[] = {1};// todo: fix this - static constexpr uint64_t max_mantissa[] = {}; + static constexpr uint64_t max_mantissa[] = {1};// todo: fix this }; template <typename U> @@ -656,17 +767,47 @@ binary_format_lookup_tables<std::bfloat16_t, U>::max_mantissa[]; template <> +inline constexpr std::bfloat16_t +binary_format<std::bfloat16_t>::exact_power_of_ten(int64_t power) { + return (void)powers_of_ten[0], powers_of_ten[power]; +} + +template <> inline constexpr int binary_format<std::bfloat16_t>::max_exponent_fast_path() { return 0; } template <> +inline constexpr binary_format<std::bfloat16_t>::equiv_uint +binary_format<std::bfloat16_t>::exponent_mask() { + return 0x7F80; +} + +template <> +inline constexpr binary_format<std::bfloat16_t>::equiv_uint +binary_format<std::bfloat16_t>::mantissa_mask() { + return 0x007F; +} + +template <> +inline constexpr binary_format<std::bfloat16_t>::equiv_uint +binary_format<std::bfloat16_t>::hidden_bit_mask() { + return 0x0080; +} + +template <> inline constexpr uint64_t binary_format<std::bfloat16_t>::max_mantissa_fast_path() { return 0; } template <> +inline constexpr uint64_t +binary_format<std::bfloat16_t>::max_mantissa_fast_path(int64_t power) { + return max_mantissa[power]; +} + +template <> inline constexpr int binary_format<std::bfloat16_t>::min_exponent_fast_path() { return 0; } @@ -818,6 +959,32 @@ ::memcpy(&value, &word, sizeof(T)); #endif } +#ifdef __STDCPP_FLOAT16_T__ +template<> +fastfloat_really_inline void +to_float<std::float16_t>(bool negative, adjusted_mantissa am, + std::float16_t &value) +{ + constexpr int mantissa_bits + = binary_format<std::float16_t>::mantissa_explicit_bits(); + value = bit_cast<std::float16_t> (uint16_t(am.mantissa + | (uint16_t(am.power2) << mantissa_bits) + | (negative ? 0x8000 : 0))); +} +#endif // __STDCPP_FLOAT16_T__ +#ifdef __STDCPP_BFLOAT16_T__ +template<> +fastfloat_really_inline void +to_float<std::bfloat16_t>(bool negative, adjusted_mantissa am, + std::bfloat16_t &value) +{ + constexpr int mantissa_bits + = binary_format<std::bfloat16_t>::mantissa_explicit_bits(); + value = bit_cast<std::bfloat16_t>(uint16_t(am.mantissa + | (uint16_t(am.power2) << mantissa_bits) + | (negative ? 0x8000 : 0))); +} +#endif // __STDCPP_BFLOAT16_T__ #ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default template <typename = void> struct space_lut { @@ -938,6 +1105,21 @@ return int_luts<>::min_safe_u64[base - 2]; } + + +static_assert(std::is_same<binary_format<double>::equiv_uint, uint64_t>::value, + "equiv_uint should be uint64_t for double"); +static_assert(std::is_same<binary_format<float>::equiv_uint, uint32_t>::value, + "equiv_uint should be uint32_t for float"); +#ifdef __STDCPP_FLOAT16_T__ +static_assert(std::is_same<binary_format<std::float16_t>::equiv_uint, uint16_t>::value, + "equiv_uint should be uint16_t for std::float16_t"); +#endif // __STDCPP_FLOAT16_T__ +#ifdef __STDCPP_BFLOAT16_T__ +static_assert(std::is_same<binary_format<std::bfloat16_t>::equiv_uint, uint16_t>::value, + "equiv_uint should be uint16_t for std::bfloat16_t"); +#endif // __STDCPP_BFLOAT16_T__ + } // namespace fast_float #endif
diff --git a/tests/example_test.cpp b/tests/example_test.cpp index 6406a2e..03457f3 100644 --- a/tests/example_test.cpp +++ b/tests/example_test.cpp
@@ -122,6 +122,7 @@ } std::cout << "parsed the number " << result << std::endl; #ifdef __STDCPP_FLOAT16_T__ + printf("16-bit float\n"); // Parse as 16-bit float std::float16_t parsed_16{}; input = "10000e-1452";