in Inc/DirectXPackedVector.inl [386:429]
inline HALF XMConvertFloatToHalf(float Value) noexcept
{
#if defined(_XM_F16C_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
__m128 V1 = _mm_set_ss(Value);
__m128i V2 = _mm_cvtps_ph(V1, _MM_FROUND_TO_NEAREST_INT);
return static_cast<HALF>(_mm_extract_epi16(V2, 0));
#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__) && !defined(_XM_NO_INTRINSICS_) && (!defined(__GNUC__) || (__ARM_FP & 2))
float32x4_t vFloat = vdupq_n_f32(Value);
float16x4_t vHalf = vcvt_f16_f32(vFloat);
return vget_lane_u16(vreinterpret_u16_f16(vHalf), 0);
#else
uint32_t Result;
auto IValue = reinterpret_cast<uint32_t*>(&Value)[0];
uint32_t Sign = (IValue & 0x80000000U) >> 16U;
IValue = IValue & 0x7FFFFFFFU; // Hack off the sign
if (IValue >= 0x47800000 /*e+16*/)
{
// The number is too large to be represented as a half. Return infinity or NaN
Result = 0x7C00U | ((IValue > 0x7F800000) ? (0x200 | ((IValue >> 13U) & 0x3FFU)) : 0U);
}
else if (IValue <= 0x33000000U /*e-25*/)
{
Result = 0;
}
else if (IValue < 0x38800000U /*e-14*/)
{
// The number is too small to be represented as a normalized half.
// Convert it to a denormalized value.
uint32_t Shift = 125U - (IValue >> 23U);
IValue = 0x800000U | (IValue & 0x7FFFFFU);
Result = IValue >> (Shift + 1);
uint32_t s = (IValue & ((1U << Shift) - 1)) != 0;
Result += (Result | s) & ((IValue >> Shift) & 1U);
}
else
{
// Rebias the exponent to represent the value as a normalized half.
IValue += 0xC8000000U;
Result = ((IValue + 0x0FFFU + ((IValue >> 13U) & 1U)) >> 13U) & 0x7FFFU;
}
return static_cast<HALF>(Result | Sign);
#endif // !_XM_F16C_INTRINSICS_
}