1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-12-19 04:33:06 +00:00

Match x86 for every possible float value

This commit is contained in:
Evil Eye 2025-12-02 22:01:58 +01:00
parent be73f2b019
commit 2c4559e507

View file

@ -1,6 +1,7 @@
#include "variantimp.hpp" #include "variantimp.hpp"
#include <cmath> #include <cmath>
#include <cstring>
#include <limits> #include <limits>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
@ -15,11 +16,21 @@ namespace ESM
template <class T> template <class T>
T floatCast(float value) T floatCast(float value)
{ {
constexpr float min = static_cast<float>(std::numeric_limits<T>::lowest()); // float to int conversions for values outside T's valid range are UB. This code produces a result
constexpr float max = static_cast<float>(std::numeric_limits<T>::max()); // equivalent to static_cast<T>(value) on x86 without invoking UB.
constexpr double min = static_cast<double>(std::numeric_limits<int32_t>::lowest());
constexpr double max = static_cast<double>(std::numeric_limits<int32_t>::max());
constexpr uint32_t magic = 0x4fffffffu;
if (std::isnan(value) || value < min || value > max) if (std::isnan(value) || value < min || value > max)
{
static_assert(sizeof(float) == sizeof(uint32_t));
uint32_t bits;
std::memcpy(&bits, &value, sizeof(float));
if (bits & magic)
return static_cast<T>(std::numeric_limits<int32_t>::lowest());
return {}; return {};
return static_cast<T>(value); }
return static_cast<T>(static_cast<int32_t>(value));
} }
} }
@ -70,10 +81,7 @@ namespace ESM
esm.getHNT(value, "FLTV"); esm.getHNT(value, "FLTV");
if (type == VT_Short) if (type == VT_Short)
if (std::isnan(value)) out = floatCast<int16_t>(value);
out = 0;
else
out = floatCast<int16_t>(value);
else if (type == VT_Long) else if (type == VT_Long)
out = floatCast<int32_t>(value); out = floatCast<int32_t>(value);
else else