inline HALF XMConvertFloatToHalf()

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_
}