in Inc/DirectXMathVector.inl [3579:3733]
inline XMVECTOR XM_CALLCONV XMVectorLog2(FXMVECTOR V) noexcept
{
#if defined(_XM_NO_INTRINSICS_)
XMVECTORF32 Result = { { {
log2f(V.vector4_f32[0]),
log2f(V.vector4_f32[1]),
log2f(V.vector4_f32[2]),
log2f(V.vector4_f32[3])
} } };
return Result.v;
#elif defined(_XM_ARM_NEON_INTRINSICS_)
int32x4_t rawBiased = vandq_s32(vreinterpretq_s32_f32(V), g_XMInfinity);
int32x4_t trailing = vandq_s32(vreinterpretq_s32_f32(V), g_XMQNaNTest);
uint32x4_t isExponentZero = vceqq_s32(vreinterpretq_s32_f32(g_XMZero), rawBiased);
// Compute exponent and significand for normals.
int32x4_t biased = vshrq_n_s32(rawBiased, 23);
int32x4_t exponentNor = vsubq_s32(biased, g_XMExponentBias);
int32x4_t trailingNor = trailing;
// Compute exponent and significand for subnormals.
int32x4_t leading = Internal::GetLeadingBit(trailing);
int32x4_t shift = vsubq_s32(g_XMNumTrailing, leading);
int32x4_t exponentSub = vsubq_s32(g_XMSubnormalExponent, shift);
int32x4_t trailingSub = vshlq_s32(trailing, shift);
trailingSub = vandq_s32(trailingSub, g_XMQNaNTest);
int32x4_t e = vbslq_s32(isExponentZero, exponentSub, exponentNor);
int32x4_t t = vbslq_s32(isExponentZero, trailingSub, trailingNor);
// Compute the approximation.
int32x4_t tmp = vorrq_s32(vreinterpretq_s32_f32(g_XMOne), t);
float32x4_t y = vsubq_f32(vreinterpretq_f32_s32(tmp), g_XMOne);
float32x4_t log2 = vmlaq_f32(g_XMLogEst6, g_XMLogEst7, y);
log2 = vmlaq_f32(g_XMLogEst5, log2, y);
log2 = vmlaq_f32(g_XMLogEst4, log2, y);
log2 = vmlaq_f32(g_XMLogEst3, log2, y);
log2 = vmlaq_f32(g_XMLogEst2, log2, y);
log2 = vmlaq_f32(g_XMLogEst1, log2, y);
log2 = vmlaq_f32(g_XMLogEst0, log2, y);
log2 = vmlaq_f32(vcvtq_f32_s32(e), log2, y);
// if (x is NaN) -> QNaN
// else if (V is positive)
// if (V is infinite) -> +inf
// else -> log2(V)
// else
// if (V is zero) -> -inf
// else -> -QNaN
uint32x4_t isInfinite = vandq_u32(vreinterpretq_u32_f32(V), g_XMAbsMask);
isInfinite = vceqq_u32(isInfinite, g_XMInfinity);
uint32x4_t isGreaterZero = vcgtq_f32(V, g_XMZero);
uint32x4_t isNotFinite = vcgtq_f32(V, g_XMInfinity);
uint32x4_t isPositive = vbicq_u32(isGreaterZero, isNotFinite);
uint32x4_t isZero = vandq_u32(vreinterpretq_u32_f32(V), g_XMAbsMask);
isZero = vceqq_u32(isZero, g_XMZero);
uint32x4_t t0 = vandq_u32(vreinterpretq_u32_f32(V), g_XMQNaNTest);
uint32x4_t t1 = vandq_u32(vreinterpretq_u32_f32(V), g_XMInfinity);
t0 = vceqq_u32(t0, g_XMZero);
t1 = vceqq_u32(t1, g_XMInfinity);
uint32x4_t isNaN = vbicq_u32(t1, t0);
float32x4_t result = vbslq_f32(isInfinite, g_XMInfinity, log2);
float32x4_t tmp2 = vbslq_f32(isZero, g_XMNegInfinity, g_XMNegQNaN);
result = vbslq_f32(isPositive, result, tmp2);
result = vbslq_f32(isNaN, g_XMQNaN, result);
return result;
#elif defined(_XM_SVML_INTRINSICS_)
XMVECTOR Result = _mm_log2_ps(V);
return Result;
#elif defined(_XM_SSE_INTRINSICS_)
__m128i rawBiased = _mm_and_si128(_mm_castps_si128(V), g_XMInfinity);
__m128i trailing = _mm_and_si128(_mm_castps_si128(V), g_XMQNaNTest);
__m128i isExponentZero = _mm_cmpeq_epi32(g_XMZero, rawBiased);
// Compute exponent and significand for normals.
__m128i biased = _mm_srli_epi32(rawBiased, 23);
__m128i exponentNor = _mm_sub_epi32(biased, g_XMExponentBias);
__m128i trailingNor = trailing;
// Compute exponent and significand for subnormals.
__m128i leading = Internal::GetLeadingBit(trailing);
__m128i shift = _mm_sub_epi32(g_XMNumTrailing, leading);
__m128i exponentSub = _mm_sub_epi32(g_XMSubnormalExponent, shift);
__m128i trailingSub = Internal::multi_sll_epi32(trailing, shift);
trailingSub = _mm_and_si128(trailingSub, g_XMQNaNTest);
__m128i select0 = _mm_and_si128(isExponentZero, exponentSub);
__m128i select1 = _mm_andnot_si128(isExponentZero, exponentNor);
__m128i e = _mm_or_si128(select0, select1);
select0 = _mm_and_si128(isExponentZero, trailingSub);
select1 = _mm_andnot_si128(isExponentZero, trailingNor);
__m128i t = _mm_or_si128(select0, select1);
// Compute the approximation.
__m128i tmp = _mm_or_si128(g_XMOne, t);
__m128 y = _mm_sub_ps(_mm_castsi128_ps(tmp), g_XMOne);
__m128 log2 = XM_FMADD_PS(g_XMLogEst7, y, g_XMLogEst6);
log2 = XM_FMADD_PS(log2, y, g_XMLogEst5);
log2 = XM_FMADD_PS(log2, y, g_XMLogEst4);
log2 = XM_FMADD_PS(log2, y, g_XMLogEst3);
log2 = XM_FMADD_PS(log2, y, g_XMLogEst2);
log2 = XM_FMADD_PS(log2, y, g_XMLogEst1);
log2 = XM_FMADD_PS(log2, y, g_XMLogEst0);
log2 = XM_FMADD_PS(log2, y, _mm_cvtepi32_ps(e));
// if (x is NaN) -> QNaN
// else if (V is positive)
// if (V is infinite) -> +inf
// else -> log2(V)
// else
// if (V is zero) -> -inf
// else -> -QNaN
__m128i isInfinite = _mm_and_si128(_mm_castps_si128(V), g_XMAbsMask);
isInfinite = _mm_cmpeq_epi32(isInfinite, g_XMInfinity);
__m128i isGreaterZero = _mm_cmpgt_epi32(_mm_castps_si128(V), g_XMZero);
__m128i isNotFinite = _mm_cmpgt_epi32(_mm_castps_si128(V), g_XMInfinity);
__m128i isPositive = _mm_andnot_si128(isNotFinite, isGreaterZero);
__m128i isZero = _mm_and_si128(_mm_castps_si128(V), g_XMAbsMask);
isZero = _mm_cmpeq_epi32(isZero, g_XMZero);
__m128i t0 = _mm_and_si128(_mm_castps_si128(V), g_XMQNaNTest);
__m128i t1 = _mm_and_si128(_mm_castps_si128(V), g_XMInfinity);
t0 = _mm_cmpeq_epi32(t0, g_XMZero);
t1 = _mm_cmpeq_epi32(t1, g_XMInfinity);
__m128i isNaN = _mm_andnot_si128(t0, t1);
select0 = _mm_and_si128(isInfinite, g_XMInfinity);
select1 = _mm_andnot_si128(isInfinite, _mm_castps_si128(log2));
__m128i result = _mm_or_si128(select0, select1);
select0 = _mm_and_si128(isZero, g_XMNegInfinity);
select1 = _mm_andnot_si128(isZero, g_XMNegQNaN);
tmp = _mm_or_si128(select0, select1);
select0 = _mm_and_si128(isPositive, result);
select1 = _mm_andnot_si128(isPositive, tmp);
result = _mm_or_si128(select0, select1);
select0 = _mm_and_si128(isNaN, g_XMQNaN);
select1 = _mm_andnot_si128(isNaN, result);
result = _mm_or_si128(select0, select1);
return _mm_castsi128_ps(result);
#endif
}