15static constexpr HalfFloat HALF_FLT_MAX = 0x7bff;
16static constexpr HalfFloat HALF_FLT_MAX_NEGATIVE = 0xfbff;
17static constexpr HalfFloat HALF_FLT_INF = 0x7c00;
18static constexpr HalfFloat HALF_FLT_INF_NEGATIVE = 0xfc00;
19static constexpr HalfFloat HALF_FLT_NANQ = 0x7e00;
20static constexpr HalfFloat HALF_FLT_NANQ_NEGATIVE = 0xfe00;
25static constexpr int FLOAT_SIGN_POS = 31;
26static constexpr int FLOAT_EXPONENT_POS = 23;
27static constexpr int FLOAT_EXPONENT_BITS = 8;
28static constexpr int FLOAT_EXPONENT_MASK = (1 << FLOAT_EXPONENT_BITS) - 1;
29static constexpr int FLOAT_EXPONENT_BIAS = 127;
30static constexpr int FLOAT_MANTISSA_BITS = 23;
31static constexpr int FLOAT_MANTISSA_MASK = (1 << FLOAT_MANTISSA_BITS) - 1;
32static constexpr int FLOAT_EXPONENT_AND_MANTISSA_MASK = FLOAT_MANTISSA_MASK + (FLOAT_EXPONENT_MASK << FLOAT_EXPONENT_POS);
35static constexpr int HALF_FLT_SIGN_POS = 15;
36static constexpr int HALF_FLT_EXPONENT_POS = 10;
37static constexpr int HALF_FLT_EXPONENT_BITS = 5;
38static constexpr int HALF_FLT_EXPONENT_MASK = (1 << HALF_FLT_EXPONENT_BITS) - 1;
39static constexpr int HALF_FLT_EXPONENT_BIAS = 15;
40static constexpr int HALF_FLT_MANTISSA_BITS = 10;
41static constexpr int HALF_FLT_MANTISSA_MASK = (1 << HALF_FLT_MANTISSA_BITS) - 1;
42static constexpr int HALF_FLT_EXPONENT_AND_MANTISSA_MASK = HALF_FLT_MANTISSA_MASK + (HALF_FLT_EXPONENT_MASK << HALF_FLT_EXPONENT_POS);
53template <
int RoundingMode>
60 uint32 exponent = (value >> FLOAT_EXPONENT_POS) & FLOAT_EXPONENT_MASK;
63 uint32 mantissa = value & FLOAT_MANTISSA_MASK;
66 HalfFloat hf_sign =
HalfFloat(value >> (FLOAT_SIGN_POS - HALF_FLT_SIGN_POS)) & (1 << HALF_FLT_SIGN_POS);
69 if (exponent == FLOAT_EXPONENT_MASK)
70 return hf_sign | (mantissa == 0? HALF_FLT_INF : HALF_FLT_NANQ);
73 int rebiased_exponent = int(exponent) - FLOAT_EXPONENT_BIAS + HALF_FLT_EXPONENT_BIAS;
76 if (rebiased_exponent >= HALF_FLT_EXPONENT_MASK)
79 return hf_sign | (round_up? HALF_FLT_INF : HALF_FLT_MAX);
83 if (rebiased_exponent < -HALF_FLT_MANTISSA_BITS)
86 return hf_sign | (round_up? 1 : 0);
91 if (rebiased_exponent <= 0)
95 mantissa |= 1 << FLOAT_MANTISSA_BITS;
96 shift = FLOAT_MANTISSA_BITS - HALF_FLT_MANTISSA_BITS + 1 - rebiased_exponent;
101 hf_exponent =
HalfFloat(rebiased_exponent << HALF_FLT_EXPONENT_POS);
102 shift = FLOAT_MANTISSA_BITS - HALF_FLT_MANTISSA_BITS;
107 HalfFloat hf = hf_sign | hf_exponent | hf_mantissa;
110 uint remainder = mantissa & ((1 << shift) - 1);
115 uint round_threshold = 1 << (shift - 1);
116 if (remainder > round_threshold
117 || (remainder == round_threshold && (hf_mantissa & 1)))
123 bool round_up = (hf_sign == 0) == (RoundingMode ==
ROUND_TO_POS_INF) && remainder != 0;
132template <
int RoundingMode>
144 __m128 val = _mm_load_ss(&inV);
145 switch (RoundingMode)
148 hf.u128 = _mm_cvtps_ph(val, _MM_FROUND_TO_NEG_INF);
151 hf.u128 = _mm_cvtps_ph(val, _MM_FROUND_TO_POS_INF);
154 hf.u128 = _mm_cvtps_ph(val, _MM_FROUND_TO_NEAREST_INT);
173 UVec4 exponent_mantissa_denormalized = ((exponent_mantissa +
UVec4::sReplicate(1 << FLOAT_EXPONENT_POS)).ReinterpretAsFloat() -
UVec4::sReplicate((FLOAT_EXPONENT_BIAS - HALF_FLT_EXPONENT_BIAS + 1) << FLOAT_EXPONENT_POS).ReinterpretAsFloat()).ReinterpretAsInt();
185 UVec4 result_exponent_mantissa =
UVec4::sSelect(
UVec4::sSelect(exponent_mantissa, exponent_mantissa_nan_inf, is_nan_inf), exponent_mantissa_denormalized, is_denormalized);
197#if defined(JPH_USE_F16C)
198 return _mm_cvtph_ps(inValue.
mValue);
199#elif defined(JPH_USE_NEON)
200 return vcvt_f32_f16(vreinterpret_f16_u32(vget_low_u32(inValue.
mValue)));
unsigned int uint
Definition Core.h:486
#define JPH_UNUSED(x)
Definition Core.h:578
#define JPH_NAMESPACE_END
Definition Core.h:418
std::uint32_t uint32
Definition Core.h:489
#define JPH_NAMESPACE_BEGIN
Definition Core.h:412
std::uint16_t uint16
Definition Core.h:488
uint16 HalfFloat
Definition HalfFloat.h:12
JPH_INLINE To BitCast(const From &inValue)
Definition Math.h:192
Definition FPException.h:92
JPH_INLINE UVec4 LogicalShiftLeft() const
Shift all components by Count bits to the left (filling with zeros from the left)
static JPH_INLINE UVec4 sSelect(UVec4Arg inNotSet, UVec4Arg inSet, UVec4Arg inControl)
Component wise select, returns inNotSet when highest bit of inControl = 0 and inSet when highest bit ...
Definition UVec4.inl:157
JPH_INLINE UVec4 Expand4Uint16Lo() const
Takes the lower 4 16 bits and expands them to X, Y, Z and W.
Definition UVec4.inl:463
static JPH_INLINE UVec4 sReplicate(uint32 inV)
Replicate int inV across all components.
Definition UVec4.inl:56
static JPH_INLINE UVec4 sAnd(UVec4Arg inV1, UVec4Arg inV2)
Logical and (component wise)
Definition UVec4.inl:202
static JPH_INLINE UVec4 sEquals(UVec4Arg inV1, UVec4Arg inV2)
Equals (component wise)
Definition UVec4.inl:143
static JPH_INLINE UVec4 sOr(UVec4Arg inV1, UVec4Arg inV2)
Logical or (component wise)
Definition UVec4.inl:174
Type mValue
Definition UVec4.h:211
static JPH_INLINE UVec4 sZero()
Vector with all zeros.
Definition UVec4.inl:45
JPH_INLINE Vec4 ReinterpretAsFloat() const
Reinterpret UVec4 as a Vec4 (doesn't change the bits)
Definition UVec4.inl:340
Definition HalfFloat.h:22
Vec4 ToFloatFallback(UVec4Arg inValue)
Convert 4 half floats (lower 64 bits) to floats, fallback version when no intrinsics available.
Definition HalfFloat.h:164
JPH_INLINE Vec4 ToFloat(UVec4Arg inValue)
Convert 4 half floats (lower 64 bits) to floats.
Definition HalfFloat.h:195
JPH_INLINE HalfFloat FromFloat(float inV)
Convert a float (32-bits) to a half float (16-bits)
Definition HalfFloat.h:133
ERoundingMode
Define half-float rounding modes.
Definition HalfFloat.h:46
@ ROUND_TO_NEG_INF
Round to negative infinity.
Definition HalfFloat.h:47
@ ROUND_TO_POS_INF
Round to positive infinity.
Definition HalfFloat.h:48
@ ROUND_TO_NEAREST
Round to nearest value.
Definition HalfFloat.h:49
HalfFloat FromFloatFallback(float inV)
Convert a float (32-bits) to a half float (16-bits), fallback version when no intrinsics available.
Definition HalfFloat.h:54