@@ -260,6 +260,88 @@ struct is_supported_char_type
260260 > {
261261};
262262
263+ union float_union {
264+ float f;
265+ uint32_t bits;
266+ };
267+
268+ union double_union {
269+ double f;
270+ uint64_t bits;
271+ };
272+
273+ template <typename T, typename U> constexpr T bit_cast (const U &u);
274+
275+ template <>
276+ fastfloat_really_inline constexpr float bit_cast (const uint32_t &u) {
277+ float_union fu;
278+ fu.bits = u;
279+ return fu.f ;
280+ }
281+
282+ template <>
283+ fastfloat_really_inline constexpr double bit_cast (const uint64_t &u) {
284+ double_union fu;
285+ fu.bits = u;
286+ return fu.f ;
287+ }
288+
289+ template <>
290+ fastfloat_really_inline constexpr uint32_t bit_cast (const float &u) {
291+ float_union fu;
292+ fu.f = u;
293+ return fu.bits ;
294+ }
295+
296+ template <>
297+ fastfloat_really_inline constexpr uint64_t bit_cast (const double &u) {
298+ double_union fu;
299+ fu.f = u;
300+ return fu.bits ;
301+ }
302+
303+ #ifdef __STDCPP_FLOAT16_T__
304+ union float16_union {
305+ std::float16_t f;
306+ uint16_t bits;
307+ };
308+
309+ template <>
310+ fastfloat_really_inline constexpr uint16_t bit_cast (const std::float16_t &u) {
311+ float16_union fu;
312+ fu.f = u;
313+ return fu.bits ;
314+ }
315+
316+ template <>
317+ fastfloat_really_inline constexpr std::float16_t bit_cast (const uint16_t &u) {
318+ float16_union fu;
319+ fu.bits = u;
320+ return fu.f ;
321+ }
322+ #endif // __STDCPP_FLOAT16_T__
323+
324+ #ifdef __STDCPP_BFLOAT16_T__
325+ union bfloat16_union {
326+ std::bfloat16_t f;
327+ uint16_t bits;
328+ };
329+
330+ template <>
331+ fastfloat_really_inline constexpr uint16_t bit_cast (const std::bfloat16_t &u) {
332+ bfloat16_union fu;
333+ fu.f = u;
334+ return fu.bits ;
335+ }
336+
337+ template <>
338+ fastfloat_really_inline constexpr std::bfloat16_t bit_cast (const uint16_t &u) {
339+ bfloat16_union fu;
340+ fu.bits = u;
341+ return fu.f ;
342+ }
343+ #endif // __STDCPP_BFLOAT16_T__
344+
263345// Compares two ASCII strings in a case insensitive manner.
264346template <typename UC>
265347inline FASTFLOAT_CONSTEXPR14 bool
@@ -630,12 +712,13 @@ inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
630712
631713// credit: Jakub Jelínek
632714#ifdef __STDCPP_FLOAT16_T__
633-
634715template <typename U> struct binary_format_lookup_tables <std::float16_t , U> {
635- static constexpr std::float16_t powers_of_ten[] = {};
636- static constexpr uint64_t max_mantissa[] = {};
716+ static constexpr std::float16_t powers_of_ten[] = {1 }; // todo: fix this
717+ static constexpr uint64_t max_mantissa[] = {1 }; // todo: fix this
637718};
638719
720+ #if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
721+
639722template <typename U>
640723constexpr std::float16_t
641724 binary_format_lookup_tables<std::float16_t , U>::powers_of_ten[];
@@ -644,6 +727,33 @@ template <typename U>
644727constexpr uint64_t
645728 binary_format_lookup_tables<std::float16_t , U>::max_mantissa[];
646729
730+ #endif
731+
732+ template <>
733+ inline constexpr std::float16_t
734+ binary_format<std::float16_t >::exact_power_of_ten(int64_t power) {
735+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
736+ return (void )powers_of_ten[0 ], powers_of_ten[power];
737+ }
738+
739+ template <>
740+ inline constexpr binary_format<std::float16_t >::equiv_uint
741+ binary_format<std::float16_t >::exponent_mask() {
742+ return 0x7C00 ;
743+ }
744+
745+ template <>
746+ inline constexpr binary_format<std::float16_t >::equiv_uint
747+ binary_format<std::float16_t >::mantissa_mask() {
748+ return 0x03FF ;
749+ }
750+
751+ template <>
752+ inline constexpr binary_format<std::float16_t >::equiv_uint
753+ binary_format<std::float16_t >::hidden_bit_mask() {
754+ return 0x0400 ;
755+ }
756+
647757template <>
648758inline constexpr int binary_format<std::float16_t >::max_exponent_fast_path() {
649759 return 0 ;
@@ -655,6 +765,13 @@ binary_format<std::float16_t>::max_mantissa_fast_path() {
655765 return 0 ;
656766}
657767
768+ template <>
769+ inline constexpr uint64_t
770+ binary_format<std::float16_t >::max_mantissa_fast_path(int64_t power) {
771+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
772+ return (void )max_mantissa[0 ], max_mantissa[power];
773+ }
774+
658775template <>
659776inline constexpr int binary_format<std::float16_t >::min_exponent_fast_path() {
660777 return 0 ;
@@ -705,13 +822,13 @@ template <> constexpr size_t binary_format<std::float16_t>::max_digits() {
705822
706823// credit: Jakub Jelínek
707824#ifdef __STDCPP_BFLOAT16_T__
708-
709825template <typename U> struct binary_format_lookup_tables <std::bfloat16_t , U> {
710- static constexpr std::bfloat16_t powers_of_ten[] = {};
711-
712- static constexpr uint64_t max_mantissa[] = {};
826+ static constexpr std::bfloat16_t powers_of_ten[] = {1 }; // todo: fix this
827+ static constexpr uint64_t max_mantissa[] = {1 }; // todo: fix this
713828};
714829
830+ #if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
831+
715832template <typename U>
716833constexpr std::bfloat16_t
717834 binary_format_lookup_tables<std::bfloat16_t , U>::powers_of_ten[];
@@ -720,17 +837,51 @@ template <typename U>
720837constexpr uint64_t
721838 binary_format_lookup_tables<std::bfloat16_t , U>::max_mantissa[];
722839
840+ #endif
841+
842+ template <>
843+ inline constexpr std::bfloat16_t
844+ binary_format<std::bfloat16_t >::exact_power_of_ten(int64_t power) {
845+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
846+ return (void )powers_of_ten[0 ], powers_of_ten[power];
847+ }
848+
723849template <>
724850inline constexpr int binary_format<std::bfloat16_t >::max_exponent_fast_path() {
725851 return 0 ;
726852}
727853
854+ template <>
855+ inline constexpr binary_format<std::bfloat16_t >::equiv_uint
856+ binary_format<std::bfloat16_t >::exponent_mask() {
857+ return 0x7F80 ;
858+ }
859+
860+ template <>
861+ inline constexpr binary_format<std::bfloat16_t >::equiv_uint
862+ binary_format<std::bfloat16_t >::mantissa_mask() {
863+ return 0x007F ;
864+ }
865+
866+ template <>
867+ inline constexpr binary_format<std::bfloat16_t >::equiv_uint
868+ binary_format<std::bfloat16_t >::hidden_bit_mask() {
869+ return 0x0080 ;
870+ }
871+
728872template <>
729873inline constexpr uint64_t
730874binary_format<std::bfloat16_t >::max_mantissa_fast_path() {
731875 return 0 ;
732876}
733877
878+ template <>
879+ inline constexpr uint64_t
880+ binary_format<std::bfloat16_t >::max_mantissa_fast_path(int64_t power) {
881+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
882+ return (void )max_mantissa[0 ], max_mantissa[power];
883+ }
884+
734885template <>
735886inline constexpr int binary_format<std::bfloat16_t >::min_exponent_fast_path() {
736887 return 0 ;
@@ -892,6 +1043,34 @@ to_float(bool negative, adjusted_mantissa am, T &value) {
8921043#endif
8931044}
8941045
1046+ #ifdef __STDCPP_FLOAT16_T__
1047+ template <>
1048+ fastfloat_really_inline void to_float<std::float16_t >(bool negative,
1049+ adjusted_mantissa am,
1050+ std::float16_t &value) {
1051+ constexpr int mantissa_bits =
1052+ binary_format<std::float16_t >::mantissa_explicit_bits ();
1053+ value = bit_cast<std::float16_t >(
1054+ uint16_t (am.mantissa | (uint16_t (am.power2 ) << mantissa_bits) |
1055+ (negative ? 0x8000 : 0 )));
1056+ }
1057+
1058+ #endif // __STDCPP_FLOAT16_T__
1059+
1060+ #ifdef __STDCPP_BFLOAT16_T__
1061+ template <>
1062+ fastfloat_really_inline void to_float<std::bfloat16_t >(bool negative,
1063+ adjusted_mantissa am,
1064+ std::bfloat16_t &value) {
1065+ constexpr int mantissa_bits =
1066+ binary_format<std::bfloat16_t >::mantissa_explicit_bits ();
1067+ value = bit_cast<std::bfloat16_t >(
1068+ uint16_t (am.mantissa | (uint16_t (am.power2 ) << mantissa_bits) |
1069+ (negative ? 0x8000 : 0 )));
1070+ }
1071+
1072+ #endif // __STDCPP_BFLOAT16_T__
1073+
8951074template <typename = void > struct space_lut {
8961075 static constexpr bool value[] = {
8971076 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
@@ -944,10 +1123,12 @@ template <> constexpr char16_t const *str_const_nan<char16_t>() {
9441123template <> constexpr char32_t const *str_const_nan<char32_t >() {
9451124 return U" nan" ;
9461125}
1126+
9471127#ifdef __cpp_char8_t
9481128template <> constexpr char8_t const *str_const_nan<char8_t >() {
9491129 return u8" nan" ;
9501130}
1131+
9511132#endif
9521133
9531134template <typename UC> constexpr UC const *str_const_inf ();
@@ -965,10 +1146,12 @@ template <> constexpr char16_t const *str_const_inf<char16_t>() {
9651146template <> constexpr char32_t const *str_const_inf<char32_t >() {
9661147 return U" infinity" ;
9671148}
1149+
9681150#ifdef __cpp_char8_t
9691151template <> constexpr char8_t const *str_const_inf<char8_t >() {
9701152 return u8" infinity" ;
9711153}
1154+
9721155#endif
9731156
9741157template <typename = void > struct int_luts {
@@ -1038,6 +1221,7 @@ fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) {
10381221
10391222static_assert (std::is_same<equiv_uint_t <double >, uint64_t >::value,
10401223 " equiv_uint should be uint64_t for double" );
1224+
10411225static_assert (std::is_same<equiv_uint_t <float >, uint32_t >::value,
10421226 " equiv_uint should be uint32_t for float" );
10431227
@@ -1051,6 +1235,18 @@ static_assert(std::is_same<equiv_uint_t<std::float32_t>, uint32_t>::value,
10511235 " equiv_uint should be uint32_t for std::float32_t" );
10521236#endif
10531237
1238+ #ifdef __STDCPP_FLOAT16_T__
1239+ static_assert (
1240+ std::is_same<binary_format<std::float16_t >::equiv_uint, uint16_t >::value,
1241+ " equiv_uint should be uint16_t for std::float16_t" );
1242+ #endif
1243+
1244+ #ifdef __STDCPP_BFLOAT16_T__
1245+ static_assert (
1246+ std::is_same<binary_format<std::bfloat16_t >::equiv_uint, uint16_t >::value,
1247+ " equiv_uint should be uint16_t for std::bfloat16_t" );
1248+ #endif
1249+
10541250constexpr chars_format operator ~(chars_format rhs) noexcept {
10551251 using int_type = std::underlying_type<chars_format>::type;
10561252 return static_cast <chars_format>(~static_cast <int_type>(rhs));
0 commit comments