@@ -260,6 +260,88 @@ struct is_supported_char_type
260
260
> {
261
261
};
262
262
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
+
263
345
// Compares two ASCII strings in a case insensitive manner.
264
346
template <typename UC>
265
347
inline FASTFLOAT_CONSTEXPR14 bool
@@ -630,12 +712,13 @@ inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
630
712
631
713
// credit: Jakub Jelínek
632
714
#ifdef __STDCPP_FLOAT16_T__
633
-
634
715
template <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
637
718
};
638
719
720
+ #if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
721
+
639
722
template <typename U>
640
723
constexpr std::float16_t
641
724
binary_format_lookup_tables<std::float16_t , U>::powers_of_ten[];
@@ -644,6 +727,33 @@ template <typename U>
644
727
constexpr uint64_t
645
728
binary_format_lookup_tables<std::float16_t , U>::max_mantissa[];
646
729
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
+
647
757
template <>
648
758
inline constexpr int binary_format<std::float16_t >::max_exponent_fast_path() {
649
759
return 0 ;
@@ -655,6 +765,13 @@ binary_format<std::float16_t>::max_mantissa_fast_path() {
655
765
return 0 ;
656
766
}
657
767
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
+
658
775
template <>
659
776
inline constexpr int binary_format<std::float16_t >::min_exponent_fast_path() {
660
777
return 0 ;
@@ -705,13 +822,13 @@ template <> constexpr size_t binary_format<std::float16_t>::max_digits() {
705
822
706
823
// credit: Jakub Jelínek
707
824
#ifdef __STDCPP_BFLOAT16_T__
708
-
709
825
template <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
713
828
};
714
829
830
+ #if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
831
+
715
832
template <typename U>
716
833
constexpr std::bfloat16_t
717
834
binary_format_lookup_tables<std::bfloat16_t , U>::powers_of_ten[];
@@ -720,17 +837,51 @@ template <typename U>
720
837
constexpr uint64_t
721
838
binary_format_lookup_tables<std::bfloat16_t , U>::max_mantissa[];
722
839
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
+
723
849
template <>
724
850
inline constexpr int binary_format<std::bfloat16_t >::max_exponent_fast_path() {
725
851
return 0 ;
726
852
}
727
853
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
+
728
872
template <>
729
873
inline constexpr uint64_t
730
874
binary_format<std::bfloat16_t >::max_mantissa_fast_path() {
731
875
return 0 ;
732
876
}
733
877
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
+
734
885
template <>
735
886
inline constexpr int binary_format<std::bfloat16_t >::min_exponent_fast_path() {
736
887
return 0 ;
@@ -892,6 +1043,34 @@ to_float(bool negative, adjusted_mantissa am, T &value) {
892
1043
#endif
893
1044
}
894
1045
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
+
895
1074
template <typename = void > struct space_lut {
896
1075
static constexpr bool value[] = {
897
1076
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>() {
944
1123
template <> constexpr char32_t const *str_const_nan<char32_t >() {
945
1124
return U" nan" ;
946
1125
}
1126
+
947
1127
#ifdef __cpp_char8_t
948
1128
template <> constexpr char8_t const *str_const_nan<char8_t >() {
949
1129
return u8" nan" ;
950
1130
}
1131
+
951
1132
#endif
952
1133
953
1134
template <typename UC> constexpr UC const *str_const_inf ();
@@ -965,10 +1146,12 @@ template <> constexpr char16_t const *str_const_inf<char16_t>() {
965
1146
template <> constexpr char32_t const *str_const_inf<char32_t >() {
966
1147
return U" infinity" ;
967
1148
}
1149
+
968
1150
#ifdef __cpp_char8_t
969
1151
template <> constexpr char8_t const *str_const_inf<char8_t >() {
970
1152
return u8" infinity" ;
971
1153
}
1154
+
972
1155
#endif
973
1156
974
1157
template <typename = void > struct int_luts {
@@ -1038,6 +1221,7 @@ fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) {
1038
1221
1039
1222
static_assert (std::is_same<equiv_uint_t <double >, uint64_t >::value,
1040
1223
" equiv_uint should be uint64_t for double" );
1224
+
1041
1225
static_assert (std::is_same<equiv_uint_t <float >, uint32_t >::value,
1042
1226
" equiv_uint should be uint32_t for float" );
1043
1227
@@ -1051,6 +1235,18 @@ static_assert(std::is_same<equiv_uint_t<std::float32_t>, uint32_t>::value,
1051
1235
" equiv_uint should be uint32_t for std::float32_t" );
1052
1236
#endif
1053
1237
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
+
1054
1250
constexpr chars_format operator ~(chars_format rhs) noexcept {
1055
1251
using int_type = std::underlying_type<chars_format>::type;
1056
1252
return static_cast <chars_format>(~static_cast <int_type>(rhs));
0 commit comments