Simplify to_float

* Use right-sized uint type for bit fiddling
** This removes the need to special casing on endianness
* Replace ternary with just shifting the sign at the right place
** This seems to improve codegen (less instructions, no cmov)
This commit is contained in:
Lenard Szolnoki 2023-03-01 23:25:20 +00:00
parent b1d27734c5
commit 6d2fb68f5c

View File

@ -443,21 +443,12 @@ template <> inline constexpr binary_format<double>::equiv_uint
template<typename T> template<typename T>
fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &value) { fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &value) {
uint64_t word = am.mantissa; using uint = typename binary_format<T>::equiv_uint;
word |= uint64_t(am.power2) << binary_format<T>::mantissa_explicit_bits(); uint word = (uint)am.mantissa;
word = negative word |= uint(am.power2) << binary_format<T>::mantissa_explicit_bits();
? word | (uint64_t(1) << binary_format<T>::sign_index()) : word; word |= uint(negative) << binary_format<T>::sign_index();
#if FASTFLOAT_IS_BIG_ENDIAN == 1
if (std::is_same<T, float>::value) {
::memcpy(&value, (char *)&word + 4, sizeof(T)); // extract value at offset 4-7 if float on big-endian
} else {
::memcpy(&value, &word, sizeof(T)); ::memcpy(&value, &word, sizeof(T));
} }
#else
// For little-endian systems:
::memcpy(&value, &word, sizeof(T));
#endif
}
#if FASTFLOAT_SKIP_WHITE_SPACE // disabled by default #if FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
template <typename = void> template <typename = void>