+/************************************************************************
+* *
+* xnamathconvert.inl -- SIMD C++ Math library for Windows and Xbox 360 *
+* Conversion, loading, and storing functions *
+* *
+* Copyright (c) Microsoft Corp. All rights reserved. *
+* *
+************************************************************************/
+
+#if defined(_MSC_VER) && (_MSC_VER > 1000)
+#pragma once
+#endif
+
+#ifndef __XNAMATHCONVERT_INL__
+#define __XNAMATHCONVERT_INL__
+
+#define XM_PACK_FACTOR (FLOAT)(1 << 22)
+#define XM_UNPACK_FACTOR_UNSIGNED (FLOAT)(1 << 23)
+#define XM_UNPACK_FACTOR_SIGNED XM_PACK_FACTOR
+
+#define XM_UNPACK_UNSIGNEDN_OFFSET(BitsX, BitsY, BitsZ, BitsW) \
+ {-XM_UNPACK_FACTOR_UNSIGNED / (FLOAT)((1 << (BitsX)) - 1), \
+ -XM_UNPACK_FACTOR_UNSIGNED / (FLOAT)((1 << (BitsY)) - 1), \
+ -XM_UNPACK_FACTOR_UNSIGNED / (FLOAT)((1 << (BitsZ)) - 1), \
+ -XM_UNPACK_FACTOR_UNSIGNED / (FLOAT)((1 << (BitsW)) - 1)}
+
+#define XM_UNPACK_UNSIGNEDN_SCALE(BitsX, BitsY, BitsZ, BitsW) \
+ {XM_UNPACK_FACTOR_UNSIGNED / (FLOAT)((1 << (BitsX)) - 1), \
+ XM_UNPACK_FACTOR_UNSIGNED / (FLOAT)((1 << (BitsY)) - 1), \
+ XM_UNPACK_FACTOR_UNSIGNED / (FLOAT)((1 << (BitsZ)) - 1), \
+ XM_UNPACK_FACTOR_UNSIGNED / (FLOAT)((1 << (BitsW)) - 1)}
+
+#define XM_UNPACK_SIGNEDN_SCALE(BitsX, BitsY, BitsZ, BitsW) \
+ {-XM_UNPACK_FACTOR_SIGNED / (FLOAT)((1 << ((BitsX) - 1)) - 1), \
+ -XM_UNPACK_FACTOR_SIGNED / (FLOAT)((1 << ((BitsY) - 1)) - 1), \
+ -XM_UNPACK_FACTOR_SIGNED / (FLOAT)((1 << ((BitsZ) - 1)) - 1), \
+ -XM_UNPACK_FACTOR_SIGNED / (FLOAT)((1 << ((BitsW) - 1)) - 1)}
+
+//#define XM_UNPACK_SIGNEDN_OFFSET(BitsX, BitsY, BitsZ, BitsW) \
+// {-XM_UNPACK_FACTOR_SIGNED / (FLOAT)((1 << ((BitsX) - 1)) - 1) * 3.0f, \
+// -XM_UNPACK_FACTOR_SIGNED / (FLOAT)((1 << ((BitsY) - 1)) - 1) * 3.0f, \
+// -XM_UNPACK_FACTOR_SIGNED / (FLOAT)((1 << ((BitsZ) - 1)) - 1) * 3.0f, \
+// -XM_UNPACK_FACTOR_SIGNED / (FLOAT)((1 << ((BitsW) - 1)) - 1) * 3.0f}
+
+#define XM_PACK_UNSIGNEDN_SCALE(BitsX, BitsY, BitsZ, BitsW) \
+ {-(FLOAT)((1 << (BitsX)) - 1) / XM_PACK_FACTOR, \
+ -(FLOAT)((1 << (BitsY)) - 1) / XM_PACK_FACTOR, \
+ -(FLOAT)((1 << (BitsZ)) - 1) / XM_PACK_FACTOR, \
+ -(FLOAT)((1 << (BitsW)) - 1) / XM_PACK_FACTOR}
+
+#define XM_PACK_SIGNEDN_SCALE(BitsX, BitsY, BitsZ, BitsW) \
+ {-(FLOAT)((1 << ((BitsX) - 1)) - 1) / XM_PACK_FACTOR, \
+ -(FLOAT)((1 << ((BitsY) - 1)) - 1) / XM_PACK_FACTOR, \
+ -(FLOAT)((1 << ((BitsZ) - 1)) - 1) / XM_PACK_FACTOR, \
+ -(FLOAT)((1 << ((BitsW) - 1)) - 1) / XM_PACK_FACTOR}
+
+#define XM_PACK_OFFSET XMVectorSplatConstant(3, 0)
+//#define XM_UNPACK_OFFSET XM_PACK_OFFSET
+
+/****************************************************************************
+ *
+ * Data conversion
+ *
+ ****************************************************************************/
+
+//------------------------------------------------------------------------------
+
+XMFINLINE FLOAT XMConvertHalfToFloat
+(
+ HALF Value
+)
+{
+#if defined(_XM_NO_INTRINSICS_) || defined(_XM_SSE_INTRINSICS_)
+
+ UINT Mantissa;
+ UINT Exponent;
+ UINT Result;
+
+ Mantissa = (UINT)(Value & 0x03FF);
+
+ if ((Value & 0x7C00) != 0) // The value is normalized
+ {
+ Exponent = (UINT)((Value >> 10) & 0x1F);
+ }
+ else if (Mantissa != 0) // The value is denormalized
+ {
+ // Normalize the value in the resulting float
+ Exponent = 1;
+
+ do
+ {
+ Exponent--;
+ Mantissa <<= 1;
+ } while ((Mantissa & 0x0400) == 0);
+
+ Mantissa &= 0x03FF;
+ }
+ else // The value is zero
+ {
+ Exponent = (UINT)-112;
+ }
+
+ Result = ((Value & 0x8000) << 16) | // Sign
+ ((Exponent + 112) << 23) | // Exponent
+ (Mantissa << 13); // Mantissa
+
+ return *(FLOAT*)&Result;
+
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+XMINLINE FLOAT* XMConvertHalfToFloatStream
+(
+ FLOAT* pOutputStream,
+ size_t OutputStride,
+ CONST HALF* pInputStream,
+ size_t InputStride,
+ size_t HalfCount
+)
+{
+#if defined(_XM_NO_INTRINSICS_) || defined(_XM_SSE_INTRINSICS_)
+
+ size_t i;
+ CONST BYTE* pHalf = (CONST BYTE*)pInputStream;
+ BYTE* pFloat = (BYTE*)pOutputStream;
+
+ XMASSERT(pOutputStream);
+ XMASSERT(pInputStream);
+
+ for (i = 0; i < HalfCount; i++)
+ {
+ *(FLOAT*)pFloat = XMConvertHalfToFloat(*(const HALF*)pHalf);
+ pHalf += InputStride;
+ pFloat += OutputStride;
+ }
+
+ return pOutputStream;
+
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE HALF XMConvertFloatToHalf
+(
+ FLOAT Value
+)
+{
+#if defined(_XM_NO_INTRINSICS_) || defined(_XM_SSE_INTRINSICS_)
+ UINT Result;
+
+ UINT IValue = ((UINT *)(&Value))[0];
+ UINT Sign = (IValue & 0x80000000U) >> 16U;
+ IValue = IValue & 0x7FFFFFFFU; // Hack off the sign
+
+ if (IValue > 0x47FFEFFFU)
+ {
+ // The number is too large to be represented as a half. Saturate to infinity.
+ Result = 0x7FFFU;
+ }
+ else
+ {
+ if (IValue < 0x38800000U)
+ {
+ // The number is too small to be represented as a normalized half.
+ // Convert it to a denormalized value.
+ UINT Shift = 113U - (IValue >> 23U);
+ IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift;
+ }
+ else
+ {
+ // Rebias the exponent to represent the value as a normalized half.
+ IValue += 0xC8000000U;
+ }
+
+ Result = ((IValue + 0x0FFFU + ((IValue >> 13U) & 1U)) >> 13U)&0x7FFFU;
+ }
+ return (HALF)(Result|Sign);
+
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+XMINLINE HALF* XMConvertFloatToHalfStream
+(
+ HALF* pOutputStream,
+ size_t OutputStride,
+ CONST FLOAT* pInputStream,
+ size_t InputStride,
+ size_t FloatCount
+)
+{
+#if defined(_XM_NO_INTRINSICS_) || defined(_XM_SSE_INTRINSICS_)
+
+ size_t i;
+ BYTE* pFloat = (BYTE*)pInputStream;
+ BYTE* pHalf = (BYTE*)pOutputStream;
+
+ XMASSERT(pOutputStream);
+ XMASSERT(pInputStream);
+
+ for (i = 0; i < FloatCount; i++)
+ {
+ *(HALF*)pHalf = XMConvertFloatToHalf(*(FLOAT*)pFloat);
+ pFloat += InputStride;
+ pHalf += OutputStride;
+ }
+ return pOutputStream;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(_XM_NO_INTRINSICS_) || defined(_XM_SSE_INTRINSICS_)
+// For VMX128, these routines are all defines in the main header
+
+#pragma warning(push)
+#pragma warning(disable:4701) // Prevent warnings about 'Result' potentially being used without having been initialized
+
+XMINLINE XMVECTOR XMConvertVectorIntToFloat
+(
+ FXMVECTOR VInt,
+ UINT DivExponent
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ UINT ElementIndex;
+ FLOAT fScale;
+ XMVECTOR Result;
+ XMASSERT(DivExponent<32);
+ fScale = 1.0f / (FLOAT)(1U << DivExponent);
+ ElementIndex = 0;
+ do {
+ INT iTemp = (INT)VInt.vector4_u32[ElementIndex];
+ Result.vector4_f32[ElementIndex] = ((FLOAT)iTemp) * fScale;
+ } while (++ElementIndex<4);
+ return Result;
+#else // _XM_SSE_INTRINSICS_
+ XMASSERT(DivExponent<32);
+ // Convert to floats
+ XMVECTOR vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&VInt)[0]);
+ // Convert DivExponent into 1.0f/(1<<DivExponent)
+ UINT uScale = 0x3F800000U - (DivExponent << 23);
+ // Splat the scalar value
+ __m128i vScale = _mm_set1_epi32(uScale);
+ vResult = _mm_mul_ps(vResult,reinterpret_cast<const __m128 *>(&vScale)[0]);
+ return vResult;
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+XMINLINE XMVECTOR XMConvertVectorFloatToInt
+(
+ FXMVECTOR VFloat,
+ UINT MulExponent
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ UINT ElementIndex;
+ XMVECTOR Result;
+ FLOAT fScale;
+ XMASSERT(MulExponent<32);
+ // Get the scalar factor.
+ fScale = (FLOAT)(1U << MulExponent);
+ ElementIndex = 0;
+ do {
+ INT iResult;
+ FLOAT fTemp = VFloat.vector4_f32[ElementIndex]*fScale;
+ if (fTemp <= -(65536.0f*32768.0f)) {
+ iResult = (-0x7FFFFFFF)-1;
+ } else if (fTemp > (65536.0f*32768.0f)-128.0f) {
+ iResult = 0x7FFFFFFF;
+ } else {
+ iResult = (INT)fTemp;
+ }
+ Result.vector4_u32[ElementIndex] = (UINT)iResult;
+ } while (++ElementIndex<4);
+ return Result;
+#else // _XM_SSE_INTRINSICS_
+ XMASSERT(MulExponent<32);
+ XMVECTOR vResult = _mm_set_ps1((FLOAT)(1U << MulExponent));
+ vResult = _mm_mul_ps(vResult,VFloat);
+ // In case of positive overflow, detect it
+ XMVECTOR vOverflow = _mm_cmpgt_ps(vResult,g_XMMaxInt);
+ // Float to int conversion
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // If there was positive overflow, set to 0x7FFFFFFF
+ vResult = _mm_and_ps(vOverflow,g_XMAbsMask);
+ vOverflow = _mm_andnot_ps(vOverflow,reinterpret_cast<const __m128 *>(&vResulti)[0]);
+ vOverflow = _mm_or_ps(vOverflow,vResult);
+ return vOverflow;
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+XMINLINE XMVECTOR XMConvertVectorUIntToFloat
+(
+ FXMVECTOR VUInt,
+ UINT DivExponent
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ UINT ElementIndex;
+ FLOAT fScale;
+ XMVECTOR Result;
+ XMASSERT(DivExponent<32);
+ fScale = 1.0f / (FLOAT)(1U << DivExponent);
+ ElementIndex = 0;
+ do {
+ Result.vector4_f32[ElementIndex] = (FLOAT)VUInt.vector4_u32[ElementIndex] * fScale;
+ } while (++ElementIndex<4);
+ return Result;
+#else // _XM_SSE_INTRINSICS_
+ XMASSERT(DivExponent<32);
+ // For the values that are higher than 0x7FFFFFFF, a fixup is needed
+ // Determine which ones need the fix.
+ XMVECTOR vMask = _mm_and_ps(VUInt,g_XMNegativeZero);
+ // Force all values positive
+ XMVECTOR vResult = _mm_xor_ps(VUInt,vMask);
+ // Convert to floats
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert 0x80000000 -> 0xFFFFFFFF
+ __m128i iMask = _mm_srai_epi32(reinterpret_cast<const __m128i *>(&vMask)[0],31);
+ // For only the ones that are too big, add the fixup
+ vMask = _mm_and_ps(reinterpret_cast<const __m128 *>(&iMask)[0],g_XMFixUnsigned);
+ vResult = _mm_add_ps(vResult,vMask);
+ // Convert DivExponent into 1.0f/(1<<DivExponent)
+ UINT uScale = 0x3F800000U - (DivExponent << 23);
+ // Splat
+ iMask = _mm_set1_epi32(uScale);
+ vResult = _mm_mul_ps(vResult,reinterpret_cast<const __m128 *>(&iMask)[0]);
+ return vResult;
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+XMINLINE XMVECTOR XMConvertVectorFloatToUInt
+(
+ FXMVECTOR VFloat,
+ UINT MulExponent
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ UINT ElementIndex;
+ XMVECTOR Result;
+ FLOAT fScale;
+ XMASSERT(MulExponent<32);
+ // Get the scalar factor.
+ fScale = (FLOAT)(1U << MulExponent);
+ ElementIndex = 0;
+ do {
+ UINT uResult;
+ FLOAT fTemp = VFloat.vector4_f32[ElementIndex]*fScale;
+ if (fTemp <= 0.0f) {
+ uResult = 0;
+ } else if (fTemp >= (65536.0f*65536.0f)) {
+ uResult = 0xFFFFFFFFU;
+ } else {
+ uResult = (UINT)fTemp;
+ }
+ Result.vector4_u32[ElementIndex] = uResult;
+ } while (++ElementIndex<4);
+ return Result;
+#else // _XM_SSE_INTRINSICS_
+ XMASSERT(MulExponent<32);
+ XMVECTOR vResult = _mm_set_ps1(static_cast<float>(1U << MulExponent));
+ vResult = _mm_mul_ps(vResult,VFloat);
+ // Clamp to >=0
+ vResult = _mm_max_ps(vResult,g_XMZero);
+ // Any numbers that are too big, set to 0xFFFFFFFFU
+ XMVECTOR vOverflow = _mm_cmpgt_ps(vResult,g_XMMaxUInt);
+ XMVECTOR vValue = g_XMUnsignedFix;
+ // Too large for a signed integer?
+ XMVECTOR vMask = _mm_cmpge_ps(vResult,vValue);
+ // Zero for number's lower than 0x80000000, 32768.0f*65536.0f otherwise
+ vValue = _mm_and_ps(vValue,vMask);
+ // Perform fixup only on numbers too large (Keeps low bit precision)
+ vResult = _mm_sub_ps(vResult,vValue);
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Convert from signed to unsigned pnly if greater than 0x80000000
+ vMask = _mm_and_ps(vMask,g_XMNegativeZero);
+ vResult = _mm_xor_ps(reinterpret_cast<const __m128 *>(&vResulti)[0],vMask);
+ // On those that are too large, set to 0xFFFFFFFF
+ vResult = _mm_or_ps(vResult,vOverflow);
+ return vResult;
+#endif
+}
+
+#pragma warning(pop)
+
+#endif // _XM_NO_INTRINSICS_ || _XM_SSE_INTRINSICS_
+
+/****************************************************************************
+ *
+ * Vector and matrix load operations
+ *
+ ****************************************************************************/
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadInt(CONST UINT* pSource)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 3) == 0);
+
+ V.vector4_u32[0] = *pSource;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 3) == 0);
+
+ return _mm_load_ss( (const float*)pSource );
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadFloat(CONST FLOAT* pSource)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 3) == 0);
+
+ V.vector4_f32[0] = *pSource;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 3) == 0);
+
+ return _mm_load_ss( pSource );
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadInt2
+(
+ CONST UINT* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_u32[0] = pSource[0];
+ V.vector4_u32[1] = pSource[1];
+
+ return V;
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pSource);
+
+ __m128 x = _mm_load_ss( (const float*)pSource );
+ __m128 y = _mm_load_ss( (const float*)(pSource+1) );
+ return _mm_unpacklo_ps( x, y );
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadSInt2
+(
+ CONST XMINT2* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (float)pSource->x;
+ V.vector4_f32[1] = (float)pSource->y;
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+
+ __m128 x = _mm_load_ss( (const float*)&pSource->x );
+ __m128 y = _mm_load_ss( (const float*)&pSource->y );
+ __m128 V = _mm_unpacklo_ps( x, y );
+ return _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&V)[0]);
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUInt2
+(
+ CONST XMUINT2* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (float)pSource->x;
+ V.vector4_f32[1] = (float)pSource->y;
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+
+ __m128 x = _mm_load_ss( (const float*)&pSource->x );
+ __m128 y = _mm_load_ss( (const float*)&pSource->y );
+ __m128 V = _mm_unpacklo_ps( x, y );
+ // For the values that are higher than 0x7FFFFFFF, a fixup is needed
+ // Determine which ones need the fix.
+ XMVECTOR vMask = _mm_and_ps(V,g_XMNegativeZero);
+ // Force all values positive
+ XMVECTOR vResult = _mm_xor_ps(V,vMask);
+ // Convert to floats
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert 0x80000000 -> 0xFFFFFFFF
+ __m128i iMask = _mm_srai_epi32(reinterpret_cast<const __m128i *>(&vMask)[0],31);
+ // For only the ones that are too big, add the fixup
+ vMask = _mm_and_ps(reinterpret_cast<const __m128 *>(&iMask)[0],g_XMFixUnsigned);
+ vResult = _mm_add_ps(vResult,vMask);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadInt2A
+(
+ CONST UINT* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ V.vector4_u32[0] = pSource[0];
+ V.vector4_u32[1] = pSource[1];
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ __m128i V = _mm_loadl_epi64( (const __m128i*)pSource );
+ return reinterpret_cast<__m128 *>(&V)[0];
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadFloat2
+(
+ CONST XMFLOAT2* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ XMASSERT(pSource);
+
+ ((UINT *)(&V.vector4_f32[0]))[0] = ((const UINT *)(&pSource->x))[0];
+ ((UINT *)(&V.vector4_f32[1]))[0] = ((const UINT *)(&pSource->y))[0];
+ return V;
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+
+ __m128 x = _mm_load_ss( &pSource->x );
+ __m128 y = _mm_load_ss( &pSource->y );
+ return _mm_unpacklo_ps( x, y );
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadFloat2A
+(
+ CONST XMFLOAT2A* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ V.vector4_f32[0] = pSource->x;
+ V.vector4_f32[1] = pSource->y;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ __m128i V = _mm_loadl_epi64( (const __m128i*)pSource );
+ return reinterpret_cast<__m128 *>(&V)[0];
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadHalf2
+(
+ CONST XMHALF2* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMASSERT(pSource);
+ {
+ XMVECTOR vResult = {
+ XMConvertHalfToFloat(pSource->x),
+ XMConvertHalfToFloat(pSource->y),
+ 0.0f,
+ 0.0f
+ };
+ return vResult;
+ }
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMVECTOR vResult = {
+ XMConvertHalfToFloat(pSource->x),
+ XMConvertHalfToFloat(pSource->y),
+ 0.0f,
+ 0.0f
+ };
+ return vResult;
+
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadShortN2
+(
+ CONST XMSHORTN2* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMASSERT(pSource);
+ {
+ XMVECTOR vResult = {
+ (pSource->x == -32768) ? -1.f : ((FLOAT)pSource->x * (1.0f/32767.0f)),
+ (pSource->y == -32768) ? -1.f : ((FLOAT)pSource->y * (1.0f/32767.0f)),
+ 0.0f,
+ 0.0f
+ };
+ return vResult;
+ }
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Splat the two shorts in all four entries (WORD alignment okay,
+ // DWORD alignment preferred)
+ __m128 vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->x));
+ // Mask x&0xFFFF, y&0xFFFF0000,z&0,w&0
+ vTemp = _mm_and_ps(vTemp,g_XMMaskX16Y16);
+ // x needs to be sign extended
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipX16Y16);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x - 0x8000 to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,g_XMFixX16Y16);
+ // Convert -1.0f - 1.0f
+ vTemp = _mm_mul_ps(vTemp,g_XMNormalizeX16Y16);
+ // Clamp result (for case of -32768)
+ return _mm_max_ps( vTemp, g_XMNegativeOne );
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadShort2
+(
+ CONST XMSHORT2* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)pSource->x;
+ V.vector4_f32[1] = (FLOAT)pSource->y;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Splat the two shorts in all four entries (WORD alignment okay,
+ // DWORD alignment preferred)
+ __m128 vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->x));
+ // Mask x&0xFFFF, y&0xFFFF0000,z&0,w&0
+ vTemp = _mm_and_ps(vTemp,g_XMMaskX16Y16);
+ // x needs to be sign extended
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipX16Y16);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x - 0x8000 to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,g_XMFixX16Y16);
+ // Y is 65536 too large
+ return _mm_mul_ps(vTemp,g_XMFixupY16);
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUShortN2
+(
+ CONST XMUSHORTN2* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)pSource->x / 65535.0f;
+ V.vector4_f32[1] = (FLOAT)pSource->y / 65535.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 FixupY16 = {1.0f/65535.0f,1.0f/(65535.0f*65536.0f),0.0f,0.0f};
+ static const XMVECTORF32 FixaddY16 = {0,32768.0f*65536.0f,0,0};
+ XMASSERT(pSource);
+ // Splat the two shorts in all four entries (WORD alignment okay,
+ // DWORD alignment preferred)
+ __m128 vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->x));
+ // Mask x&0xFFFF, y&0xFFFF0000,z&0,w&0
+ vTemp = _mm_and_ps(vTemp,g_XMMaskX16Y16);
+ // y needs to be sign flipped
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipY);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // y + 0x8000 to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,FixaddY16);
+ // Y is 65536 times too large
+ vTemp = _mm_mul_ps(vTemp,FixupY16);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUShort2
+(
+ CONST XMUSHORT2* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)pSource->x;
+ V.vector4_f32[1] = (FLOAT)pSource->y;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 FixaddY16 = {0,32768.0f,0,0};
+ XMASSERT(pSource);
+ // Splat the two shorts in all four entries (WORD alignment okay,
+ // DWORD alignment preferred)
+ __m128 vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->x));
+ // Mask x&0xFFFF, y&0xFFFF0000,z&0,w&0
+ vTemp = _mm_and_ps(vTemp,g_XMMaskX16Y16);
+ // y needs to be sign flipped
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipY);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // Y is 65536 times too large
+ vTemp = _mm_mul_ps(vTemp,g_XMFixupY16);
+ // y + 0x8000 to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,FixaddY16);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadByteN2
+(
+ CONST XMBYTEN2* pSource
+)
+{
+ XMASSERT(pSource);
+ {
+ XMVECTOR vResult = {
+ (pSource->x == -128) ? -1.f : ((FLOAT)pSource->x * (1.0f/127.0f)),
+ (pSource->y == -128) ? -1.f : ((FLOAT)pSource->y * (1.0f/127.0f)),
+ 0.0f,
+ 0.0f
+ };
+ return vResult;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadByte2
+(
+ CONST XMBYTE2* pSource
+)
+{
+ XMASSERT(pSource);
+ {
+ XMVECTOR vResult = {
+ (FLOAT)pSource->x,
+ (FLOAT)pSource->y,
+ 0.0f,
+ 0.0f
+ };
+ return vResult;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUByteN2
+(
+ CONST XMUBYTEN2* pSource
+)
+{
+ XMASSERT(pSource);
+ {
+ XMVECTOR vResult = {
+ (FLOAT)pSource->x * (1.0f/255.0f),
+ (FLOAT)pSource->y * (1.0f/255.0f),
+ 0.0f,
+ 0.0f
+ };
+ return vResult;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUByte2
+(
+ CONST XMUBYTE2* pSource
+)
+{
+ XMASSERT(pSource);
+ {
+ XMVECTOR vResult = {
+ (FLOAT)pSource->x,
+ (FLOAT)pSource->y,
+ 0.0f,
+ 0.0f
+ };
+ return vResult;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadInt3
+(
+ CONST UINT* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_u32[0] = pSource[0];
+ V.vector4_u32[1] = pSource[1];
+ V.vector4_u32[2] = pSource[2];
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+
+#ifdef _XM_ISVS2005_
+ __m128i V = _mm_set_epi32( 0, *(pSource+2), *(pSource+1), *pSource );
+ return reinterpret_cast<__m128 *>(&V)[0];
+#else
+ __m128 x = _mm_load_ss( (const float*)pSource );
+ __m128 y = _mm_load_ss( (const float*)(pSource+1) );
+ __m128 z = _mm_load_ss( (const float*)(pSource+2) );
+ __m128 xy = _mm_unpacklo_ps( x, y );
+ return _mm_movelh_ps( xy, z );
+#endif // !_XM_ISVS2005_
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadSInt3
+(
+ CONST XMINT3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ XMASSERT(pSource);
+
+#ifdef _XBOX_VER
+ V = XMLoadInt3( (const UINT*)pSource );
+ return XMConvertVectorIntToFloat( V, 0 );
+#else
+ V.vector4_f32[0] = (float)pSource->x;
+ V.vector4_f32[1] = (float)pSource->y;
+ V.vector4_f32[2] = (float)pSource->z;
+ return V;
+#endif
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+
+#ifdef _XM_ISVS2005_
+ __m128i V = _mm_set_epi32( 0, pSource->z, pSource->y, pSource->x );
+ return _mm_cvtepi32_ps(V);
+#else
+ __m128 x = _mm_load_ss( (const float*)&pSource->x );
+ __m128 y = _mm_load_ss( (const float*)&pSource->y );
+ __m128 z = _mm_load_ss( (const float*)&pSource->z );
+ __m128 xy = _mm_unpacklo_ps( x, y );
+ __m128 V = _mm_movelh_ps( xy, z );
+ return _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&V)[0]);
+#endif // !_XM_ISVS2005_
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUInt3
+(
+ CONST XMUINT3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (float)pSource->x;
+ V.vector4_f32[1] = (float)pSource->y;
+ V.vector4_f32[2] = (float)pSource->z;
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+
+#ifdef _XM_ISVS2005_
+ __m128i V = _mm_set_epi32( 0, pSource->z, pSource->y, pSource->x );
+ // For the values that are higher than 0x7FFFFFFF, a fixup is needed
+ // Determine which ones need the fix.
+ XMVECTOR vMask = _mm_and_ps(reinterpret_cast<const __m128 *>(&V)[0],g_XMNegativeZero);
+ // Force all values positive
+ XMVECTOR vResult = _mm_xor_ps(reinterpret_cast<const __m128 *>(&V)[0],vMask);
+#else
+ __m128 x = _mm_load_ss( (const float*)&pSource->x );
+ __m128 y = _mm_load_ss( (const float*)&pSource->y );
+ __m128 z = _mm_load_ss( (const float*)&pSource->z );
+ __m128 xy = _mm_unpacklo_ps( x, y );
+ __m128 V = _mm_movelh_ps( xy, z );
+ // For the values that are higher than 0x7FFFFFFF, a fixup is needed
+ // Determine which ones need the fix.
+ XMVECTOR vMask = _mm_and_ps(V,g_XMNegativeZero);
+ // Force all values positive
+ XMVECTOR vResult = _mm_xor_ps(V,vMask);
+#endif // !_XM_ISVS2005_
+ // Convert to floats
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert 0x80000000 -> 0xFFFFFFFF
+ __m128i iMask = _mm_srai_epi32(reinterpret_cast<const __m128i *>(&vMask)[0],31);
+ // For only the ones that are too big, add the fixup
+ vMask = _mm_and_ps(reinterpret_cast<const __m128 *>(&iMask)[0],g_XMFixUnsigned);
+ vResult = _mm_add_ps(vResult,vMask);
+ return vResult;
+
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadInt3A
+(
+ CONST UINT* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ V.vector4_u32[0] = pSource[0];
+ V.vector4_u32[1] = pSource[1];
+ V.vector4_u32[2] = pSource[2];
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+
+ // Reads an extra integer that is 'undefined'
+
+ __m128i V = _mm_load_si128( (const __m128i*)pSource );
+ return reinterpret_cast<__m128 *>(&V)[0];
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadFloat3
+(
+ CONST XMFLOAT3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ XMASSERT(pSource);
+
+ ((UINT *)(&V.vector4_f32[0]))[0] = ((const UINT *)(&pSource->x))[0];
+ ((UINT *)(&V.vector4_f32[1]))[0] = ((const UINT *)(&pSource->y))[0];
+ ((UINT *)(&V.vector4_f32[2]))[0] = ((const UINT *)(&pSource->z))[0];
+ return V;
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+
+#ifdef _XM_ISVS2005_
+ // This reads 1 floats past the memory that should be ignored.
+ // Need to continue to do this for VS 2005 due to compiler issue but prefer new method
+ // to avoid triggering issues with memory debug tools (like AV)
+ return _mm_loadu_ps( &pSource->x );
+#else
+ __m128 x = _mm_load_ss( &pSource->x );
+ __m128 y = _mm_load_ss( &pSource->y );
+ __m128 z = _mm_load_ss( &pSource->z );
+ __m128 xy = _mm_unpacklo_ps( x, y );
+ return _mm_movelh_ps( xy, z );
+#endif // !_XM_ISVS2005_
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadFloat3A
+(
+ CONST XMFLOAT3A* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ V.vector4_f32[0] = pSource->x;
+ V.vector4_f32[1] = pSource->y;
+ V.vector4_f32[2] = pSource->z;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ // This reads 1 floats past the memory that should be ignored.
+ return _mm_load_ps( &pSource->x );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUHenDN3
+(
+ CONST XMUHENDN3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+
+ XMASSERT(pSource);
+
+ Element = pSource->v & 0x7FF;
+ V.vector4_f32[0] = (FLOAT)Element / 2047.0f;
+ Element = (pSource->v >> 11) & 0x7FF;
+ V.vector4_f32[1] = (FLOAT)Element / 2047.0f;
+ Element = (pSource->v >> 22) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)Element / 1023.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 UHenDN3Mul = {1.0f/2047.0f,1.0f/(2047.0f*2048.0f),1.0f/(1023.0f*2048.0f*2048.0f),0};
+ XMASSERT(pSource);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,g_XMMaskHenD3);
+ // Convert x and y to unsigned
+ vResult = _mm_xor_ps(vResult,g_XMFlipZ);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert x and y back to signed
+ vResult = _mm_add_ps(vResult,g_XMAddUHenD3);
+ // Normalize x,y and z to -1.0f-1.0f
+ vResult = _mm_mul_ps(vResult,UHenDN3Mul);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUHenD3
+(
+ CONST XMUHEND3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+
+ XMASSERT(pSource);
+
+ Element = pSource->v & 0x7FF;
+ V.vector4_f32[0] = (FLOAT)Element;
+ Element = (pSource->v >> 11) & 0x7FF;
+ V.vector4_f32[1] = (FLOAT)Element;
+ Element = (pSource->v >> 22) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)Element;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,g_XMMaskHenD3);
+ // Convert x and y to unsigned
+ vResult = _mm_xor_ps(vResult,g_XMFlipZ);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert x and y back to signed
+ vResult = _mm_add_ps(vResult,g_XMAddUHenD3);
+ // Normalize x and y to -1024-1023.0f and z to -512-511.0f
+ vResult = _mm_mul_ps(vResult,g_XMMulHenD3);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadHenDN3
+(
+ CONST XMHENDN3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtendXY[] = {0x00000000, 0xFFFFF800};
+ static CONST UINT SignExtendZ[] = {0x00000000, 0xFFFFFC00};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 11) & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 22) & 0x3FF) != 0x200);
+
+ Element = pSource->v & 0x7FF;
+ V.vector4_f32[0] = (FLOAT)(SHORT)(Element | SignExtendXY[Element >> 10]) / 1023.0f;
+ Element = (pSource->v >> 11) & 0x7FF;
+ V.vector4_f32[1] = (FLOAT)(SHORT)(Element | SignExtendXY[Element >> 10]) / 1023.0f;
+ Element = (pSource->v >> 22) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)(SHORT)(Element | SignExtendZ[Element >> 9]) / 511.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 HenDN3Mul = {1.0f/1023.0f,1.0f/(1023.0f*2048.0f),1.0f/(511.0f*2048.0f*2048.0f),0};
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 11) & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 22) & 0x3FF) != 0x200);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,g_XMMaskHenD3);
+ // Convert x and y to unsigned
+ vResult = _mm_xor_ps(vResult,g_XMXorHenD3);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert x and y back to signed
+ vResult = _mm_add_ps(vResult,g_XMAddHenD3);
+ // Normalize x,y and z to -1.0f-1.0f
+ vResult = _mm_mul_ps(vResult,HenDN3Mul);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadHenD3
+(
+ CONST XMHEND3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtendXY[] = {0x00000000, 0xFFFFF800};
+ static CONST UINT SignExtendZ[] = {0x00000000, 0xFFFFFC00};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 11) & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 22) & 0x3FF) != 0x200);
+
+ Element = pSource->v & 0x7FF;
+ V.vector4_f32[0] = (FLOAT)(SHORT)(Element | SignExtendXY[Element >> 10]);
+ Element = (pSource->v >> 11) & 0x7FF;
+ V.vector4_f32[1] = (FLOAT)(SHORT)(Element | SignExtendXY[Element >> 10]);
+ Element = (pSource->v >> 22) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)(SHORT)(Element | SignExtendZ[Element >> 9]);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 11) & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 22) & 0x3FF) != 0x200);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,g_XMMaskHenD3);
+ // Convert x and y to unsigned
+ vResult = _mm_xor_ps(vResult,g_XMXorHenD3);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert x and y back to signed
+ vResult = _mm_add_ps(vResult,g_XMAddHenD3);
+ // Normalize x and y to -1024-1023.0f and z to -512-511.0f
+ vResult = _mm_mul_ps(vResult,g_XMMulHenD3);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUDHenN3
+(
+ CONST XMUDHENN3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+
+ XMASSERT(pSource);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)Element / 1023.0f;
+ Element = (pSource->v >> 10) & 0x7FF;
+ V.vector4_f32[1] = (FLOAT)Element / 2047.0f;
+ Element = (pSource->v >> 21) & 0x7FF;
+ V.vector4_f32[2] = (FLOAT)Element / 2047.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 UDHenN3Mul = {1.0f/1023.0f,1.0f/(2047.0f*1024.0f),1.0f/(2047.0f*1024.0f*2048.0f),0};
+ XMASSERT(pSource);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,g_XMMaskDHen3);
+ // Convert x and y to unsigned
+ vResult = _mm_xor_ps(vResult,g_XMFlipZ);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert x and y back to signed
+ vResult = _mm_add_ps(vResult,g_XMAddUHenD3);
+ // Normalize x,y and z to -1.0f-1.0f
+ vResult = _mm_mul_ps(vResult,UDHenN3Mul);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUDHen3
+(
+ CONST XMUDHEN3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+
+ XMASSERT(pSource);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)Element;
+ Element = (pSource->v >> 10) & 0x7FF;
+ V.vector4_f32[1] = (FLOAT)Element;
+ Element = (pSource->v >> 21) & 0x7FF;
+ V.vector4_f32[2] = (FLOAT)Element;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,g_XMMaskDHen3);
+ // Convert x and y to unsigned
+ vResult = _mm_xor_ps(vResult,g_XMFlipZ);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert x and y back to signed
+ vResult = _mm_add_ps(vResult,g_XMAddUHenD3);
+ // Normalize x to 0-1023.0f and y and z to 0-2047.0f
+ vResult = _mm_mul_ps(vResult,g_XMMulDHen3);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadDHenN3
+(
+ CONST XMDHENN3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtendX[] = {0x00000000, 0xFFFFFC00};
+ static CONST UINT SignExtendYZ[] = {0x00000000, 0xFFFFF800};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 21) & 0x7FF) != 0x400);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)(SHORT)(Element | SignExtendX[Element >> 9]) / 511.0f;
+ Element = (pSource->v >> 10) & 0x7FF;
+ V.vector4_f32[1] = (FLOAT)(SHORT)(Element | SignExtendYZ[Element >> 10]) / 1023.0f;
+ Element = (pSource->v >> 21) & 0x7FF;
+ V.vector4_f32[2] = (FLOAT)(SHORT)(Element | SignExtendYZ[Element >> 10]) / 1023.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 DHenN3Mul = {1.0f/511.0f,1.0f/(1023.0f*1024.0f),1.0f/(1023.0f*1024.0f*2048.0f),0};
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 21) & 0x7FF) != 0x400);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,g_XMMaskDHen3);
+ // Convert x and y to unsigned
+ vResult = _mm_xor_ps(vResult,g_XMXorDHen3);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert x and y back to signed
+ vResult = _mm_add_ps(vResult,g_XMAddDHen3);
+ // Normalize x,y and z to -1.0f-1.0f
+ vResult = _mm_mul_ps(vResult,DHenN3Mul);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadDHen3
+(
+ CONST XMDHEN3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtendX[] = {0x00000000, 0xFFFFFC00};
+ static CONST UINT SignExtendYZ[] = {0x00000000, 0xFFFFF800};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 21) & 0x7FF) != 0x400);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)(SHORT)(Element | SignExtendX[Element >> 9]);
+ Element = (pSource->v >> 10) & 0x7FF;
+ V.vector4_f32[1] = (FLOAT)(SHORT)(Element | SignExtendYZ[Element >> 10]);
+ Element = (pSource->v >> 21) & 0x7FF;
+ V.vector4_f32[2] = (FLOAT)(SHORT)(Element | SignExtendYZ[Element >> 10]);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x7FF) != 0x400);
+ XMASSERT(((pSource->v >> 21) & 0x7FF) != 0x400);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,g_XMMaskDHen3);
+ // Convert x and y to unsigned
+ vResult = _mm_xor_ps(vResult,g_XMXorDHen3);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert x and y back to signed
+ vResult = _mm_add_ps(vResult,g_XMAddDHen3);
+ // Normalize x to -210-511.0f and y and z to -1024-1023.0f
+ vResult = _mm_mul_ps(vResult,g_XMMulDHen3);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadU565
+(
+ CONST XMU565* pSource
+)
+{
+#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
+ static const XMVECTORI32 U565And = {0x1F,0x3F<<5,0x1F<<11,0};
+ static const XMVECTORF32 U565Mul = {1.0f,1.0f/32.0f,1.0f/2048.f,0};
+ XMASSERT(pSource);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,U565And);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Normalize x, y, and z
+ vResult = _mm_mul_ps(vResult,U565Mul);
+ return vResult;
+#else
+ XMVECTOR V;
+ UINT Element;
+
+ XMASSERT(pSource);
+
+ Element = pSource->v & 0x1F;
+ V.vector4_f32[0] = (FLOAT)Element;
+ Element = (pSource->v >> 5) & 0x3F;
+ V.vector4_f32[1] = (FLOAT)Element;
+ Element = (pSource->v >> 11) & 0x1F;
+ V.vector4_f32[2] = (FLOAT)Element;
+
+ return V;
+#endif // !_XM_SSE_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadFloat3PK
+(
+ CONST XMFLOAT3PK* pSource
+)
+{
+ _DECLSPEC_ALIGN_16_ UINT Result[4];
+ UINT Mantissa;
+ UINT Exponent;
+
+ XMASSERT(pSource);
+
+ // X Channel (6-bit mantissa)
+ Mantissa = pSource->xm;
+
+ if ( pSource->xe == 0x1f ) // INF or NAN
+ {
+ Result[0] = 0x7f800000 | (pSource->xm << 17);
+ }
+ else
+ {
+ if ( pSource->xe != 0 ) // The value is normalized
+ {
+ Exponent = pSource->xe;
+ }
+ else if (Mantissa != 0) // The value is denormalized
+ {
+ // Normalize the value in the resulting float
+ Exponent = 1;
+
+ do
+ {
+ Exponent--;
+ Mantissa <<= 1;
+ } while ((Mantissa & 0x40) == 0);
+
+ Mantissa &= 0x3F;
+ }
+ else // The value is zero
+ {
+ Exponent = (UINT)-112;
+ }
+
+ Result[0] = ((Exponent + 112) << 23) | (Mantissa << 17);
+ }
+
+ // Y Channel (6-bit mantissa)
+ Mantissa = pSource->ym;
+
+ if ( pSource->ye == 0x1f ) // INF or NAN
+ {
+ Result[1] = 0x7f800000 | (pSource->ym << 17);
+ }
+ else
+ {
+ if ( pSource->ye != 0 ) // The value is normalized
+ {
+ Exponent = pSource->ye;
+ }
+ else if (Mantissa != 0) // The value is denormalized
+ {
+ // Normalize the value in the resulting float
+ Exponent = 1;
+
+ do
+ {
+ Exponent--;
+ Mantissa <<= 1;
+ } while ((Mantissa & 0x40) == 0);
+
+ Mantissa &= 0x3F;
+ }
+ else // The value is zero
+ {
+ Exponent = (UINT)-112;
+ }
+
+ Result[1] = ((Exponent + 112) << 23) | (Mantissa << 17);
+ }
+
+ // Z Channel (5-bit mantissa)
+ Mantissa = pSource->zm;
+
+ if ( pSource->ze == 0x1f ) // INF or NAN
+ {
+ Result[2] = 0x7f800000 | (pSource->zm << 17);
+ }
+ else
+ {
+ if ( pSource->ze != 0 ) // The value is normalized
+ {
+ Exponent = pSource->ze;
+ }
+ else if (Mantissa != 0) // The value is denormalized
+ {
+ // Normalize the value in the resulting float
+ Exponent = 1;
+
+ do
+ {
+ Exponent--;
+ Mantissa <<= 1;
+ } while ((Mantissa & 0x20) == 0);
+
+ Mantissa &= 0x1F;
+ }
+ else // The value is zero
+ {
+ Exponent = (UINT)-112;
+ }
+
+ Result[2] = ((Exponent + 112) << 23) | (Mantissa << 18);
+ }
+
+ return XMLoadFloat3A( (const XMFLOAT3A*)&Result );
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadFloat3SE
+(
+ CONST XMFLOAT3SE* pSource
+)
+{
+ _DECLSPEC_ALIGN_16_ UINT Result[4];
+ UINT Mantissa;
+ UINT Exponent, ExpBits;
+
+ XMASSERT(pSource);
+
+ if ( pSource->e == 0x1f ) // INF or NAN
+ {
+ Result[0] = 0x7f800000 | (pSource->xm << 14);
+ Result[1] = 0x7f800000 | (pSource->ym << 14);
+ Result[2] = 0x7f800000 | (pSource->zm << 14);
+ }
+ else if ( pSource->e != 0 ) // The values are all normalized
+ {
+ Exponent = pSource->e;
+
+ ExpBits = (Exponent + 112) << 23;
+
+ Mantissa = pSource->xm;
+ Result[0] = ExpBits | (Mantissa << 14);
+
+ Mantissa = pSource->ym;
+ Result[1] = ExpBits | (Mantissa << 14);
+
+ Mantissa = pSource->zm;
+ Result[2] = ExpBits | (Mantissa << 14);
+ }
+ else
+ {
+ // X Channel
+ Mantissa = pSource->xm;
+
+ if (Mantissa != 0) // The value is denormalized
+ {
+ // Normalize the value in the resulting float
+ Exponent = 1;
+
+ do
+ {
+ Exponent--;
+ Mantissa <<= 1;
+ } while ((Mantissa & 0x200) == 0);
+
+ Mantissa &= 0x1FF;
+ }
+ else // The value is zero
+ {
+ Exponent = (UINT)-112;
+ }
+
+ Result[0] = ((Exponent + 112) << 23) | (Mantissa << 14);
+
+ // Y Channel
+ Mantissa = pSource->ym;
+
+ if (Mantissa != 0) // The value is denormalized
+ {
+ // Normalize the value in the resulting float
+ Exponent = 1;
+
+ do
+ {
+ Exponent--;
+ Mantissa <<= 1;
+ } while ((Mantissa & 0x200) == 0);
+
+ Mantissa &= 0x1FF;
+ }
+ else // The value is zero
+ {
+ Exponent = (UINT)-112;
+ }
+
+ Result[1] = ((Exponent + 112) << 23) | (Mantissa << 14);
+
+ // Z Channel
+ Mantissa = pSource->zm;
+
+ if (Mantissa != 0) // The value is denormalized
+ {
+ // Normalize the value in the resulting float
+ Exponent = 1;
+
+ do
+ {
+ Exponent--;
+ Mantissa <<= 1;
+ } while ((Mantissa & 0x200) == 0);
+
+ Mantissa &= 0x1FF;
+ }
+ else // The value is zero
+ {
+ Exponent = (UINT)-112;
+ }
+
+ Result[2] = ((Exponent + 112) << 23) | (Mantissa << 14);
+ }
+
+ return XMLoadFloat3A( (const XMFLOAT3A*)&Result );
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadInt4
+(
+ CONST UINT* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_u32[0] = pSource[0];
+ V.vector4_u32[1] = pSource[1];
+ V.vector4_u32[2] = pSource[2];
+ V.vector4_u32[3] = pSource[3];
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pSource);
+
+ __m128i V = _mm_loadu_si128( (const __m128i*)pSource );
+ return reinterpret_cast<__m128 *>(&V)[0];
+
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadSInt4
+(
+ CONST XMINT4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ XMASSERT(pSource);
+
+#ifdef _XBOX_VER
+ V = XMLoadInt4( (const UINT*)pSource );
+ return XMConvertVectorIntToFloat( V, 0 );
+#else
+ V.vector4_f32[0] = (float)pSource->x;
+ V.vector4_f32[1] = (float)pSource->y;
+ V.vector4_f32[2] = (float)pSource->z;
+ V.vector4_f32[3] = (float)pSource->w;
+ return V;
+#endif
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ __m128i V = _mm_loadu_si128( (const __m128i*)pSource );
+ return _mm_cvtepi32_ps(V);
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUInt4
+(
+ CONST XMUINT4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (float)pSource->x;
+ V.vector4_f32[1] = (float)pSource->y;
+ V.vector4_f32[2] = (float)pSource->z;
+ V.vector4_f32[3] = (float)pSource->w;
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ __m128i V = _mm_loadu_si128( (const __m128i*)pSource );
+ // For the values that are higher than 0x7FFFFFFF, a fixup is needed
+ // Determine which ones need the fix.
+ XMVECTOR vMask = _mm_and_ps(reinterpret_cast<const __m128 *>(&V)[0],g_XMNegativeZero);
+ // Force all values positive
+ XMVECTOR vResult = _mm_xor_ps(reinterpret_cast<const __m128 *>(&V)[0],vMask);
+ // Convert to floats
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Convert 0x80000000 -> 0xFFFFFFFF
+ __m128i iMask = _mm_srai_epi32(reinterpret_cast<const __m128i *>(&vMask)[0],31);
+ // For only the ones that are too big, add the fixup
+ vMask = _mm_and_ps(reinterpret_cast<const __m128 *>(&iMask)[0],g_XMFixUnsigned);
+ vResult = _mm_add_ps(vResult,vMask);
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadInt4A
+(
+ CONST UINT* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ V.vector4_u32[0] = pSource[0];
+ V.vector4_u32[1] = pSource[1];
+ V.vector4_u32[2] = pSource[2];
+ V.vector4_u32[3] = pSource[3];
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ __m128i V = _mm_load_si128( (const __m128i*)pSource );
+ return reinterpret_cast<__m128 *>(&V)[0];
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadFloat4
+(
+ CONST XMFLOAT4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ XMASSERT(pSource);
+
+ ((UINT *)(&V.vector4_f32[0]))[0] = ((const UINT *)(&pSource->x))[0];
+ ((UINT *)(&V.vector4_f32[1]))[0] = ((const UINT *)(&pSource->y))[0];
+ ((UINT *)(&V.vector4_f32[2]))[0] = ((const UINT *)(&pSource->z))[0];
+ ((UINT *)(&V.vector4_f32[3]))[0] = ((const UINT *)(&pSource->w))[0];
+ return V;
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+
+ return _mm_loadu_ps( &pSource->x );
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadFloat4A
+(
+ CONST XMFLOAT4A* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ V.vector4_f32[0] = pSource->x;
+ V.vector4_f32[1] = pSource->y;
+ V.vector4_f32[2] = pSource->z;
+ V.vector4_f32[3] = pSource->w;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ return _mm_load_ps( &pSource->x );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadHalf4
+(
+ CONST XMHALF4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMASSERT(pSource);
+ {
+ XMVECTOR vResult = {
+ XMConvertHalfToFloat(pSource->x),
+ XMConvertHalfToFloat(pSource->y),
+ XMConvertHalfToFloat(pSource->z),
+ XMConvertHalfToFloat(pSource->w)
+ };
+ return vResult;
+ }
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMVECTOR vResult = {
+ XMConvertHalfToFloat(pSource->x),
+ XMConvertHalfToFloat(pSource->y),
+ XMConvertHalfToFloat(pSource->z),
+ XMConvertHalfToFloat(pSource->w)
+ };
+ return vResult;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadShortN4
+(
+ CONST XMSHORTN4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMASSERT(pSource);
+ {
+ XMVECTOR vResult = {
+ (pSource->x == -32768) ? -1.f : ((FLOAT)pSource->x * (1.0f/32767.0f)),
+ (pSource->y == -32768) ? -1.f : ((FLOAT)pSource->y * (1.0f/32767.0f)),
+ (pSource->z == -32768) ? -1.f : ((FLOAT)pSource->z * (1.0f/32767.0f)),
+ (pSource->w == -32768) ? -1.f : ((FLOAT)pSource->w * (1.0f/32767.0f))
+ };
+ return vResult;
+ }
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Splat the color in all four entries (x,z,y,w)
+ __m128d vIntd = _mm_load1_pd(reinterpret_cast<const double *>(&pSource->x));
+ // Shift x&0ffff,z&0xffff,y&0xffff0000,w&0xffff0000
+ __m128 vTemp = _mm_and_ps(reinterpret_cast<const __m128 *>(&vIntd)[0],g_XMMaskX16Y16Z16W16);
+ // x and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipX16Y16Z16W16);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x and z - 0x8000 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMFixX16Y16Z16W16);
+ // Convert to -1.0f - 1.0f
+ vTemp = _mm_mul_ps(vTemp,g_XMNormalizeX16Y16Z16W16);
+ // Very important! The entries are x,z,y,w, flip it to x,y,z,w
+ vTemp = _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(3,1,2,0));
+ // Clamp result (for case of -32768)
+ return _mm_max_ps( vTemp, g_XMNegativeOne );
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadShort4
+(
+ CONST XMSHORT4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)pSource->x;
+ V.vector4_f32[1] = (FLOAT)pSource->y;
+ V.vector4_f32[2] = (FLOAT)pSource->z;
+ V.vector4_f32[3] = (FLOAT)pSource->w;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Splat the color in all four entries (x,z,y,w)
+ __m128d vIntd = _mm_load1_pd(reinterpret_cast<const double *>(&pSource->x));
+ // Shift x&0ffff,z&0xffff,y&0xffff0000,w&0xffff0000
+ __m128 vTemp = _mm_and_ps(reinterpret_cast<const __m128 *>(&vIntd)[0],g_XMMaskX16Y16Z16W16);
+ // x and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipX16Y16Z16W16);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x and z - 0x8000 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMFixX16Y16Z16W16);
+ // Fix y and w because they are 65536 too large
+ vTemp = _mm_mul_ps(vTemp,g_XMFixupY16W16);
+ // Very important! The entries are x,z,y,w, flip it to x,y,z,w
+ return _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(3,1,2,0));
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUShortN4
+(
+ CONST XMUSHORTN4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)pSource->x / 65535.0f;
+ V.vector4_f32[1] = (FLOAT)pSource->y / 65535.0f;
+ V.vector4_f32[2] = (FLOAT)pSource->z / 65535.0f;
+ V.vector4_f32[3] = (FLOAT)pSource->w / 65535.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ static const XMVECTORF32 FixupY16W16 = {1.0f/65535.0f,1.0f/65535.0f,1.0f/(65535.0f*65536.0f),1.0f/(65535.0f*65536.0f)};
+ static const XMVECTORF32 FixaddY16W16 = {0,0,32768.0f*65536.0f,32768.0f*65536.0f};
+ XMASSERT(pSource);
+ // Splat the color in all four entries (x,z,y,w)
+ __m128d vIntd = _mm_load1_pd(reinterpret_cast<const double *>(&pSource->x));
+ // Shift x&0ffff,z&0xffff,y&0xffff0000,w&0xffff0000
+ __m128 vTemp = _mm_and_ps(reinterpret_cast<const __m128 *>(&vIntd)[0],g_XMMaskX16Y16Z16W16);
+ // y and w are signed! Flip the bits to convert the order to unsigned
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipZW);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // y and w + 0x8000 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,FixaddY16W16);
+ // Fix y and w because they are 65536 too large
+ vTemp = _mm_mul_ps(vTemp,FixupY16W16);
+ // Very important! The entries are x,z,y,w, flip it to x,y,z,w
+ return _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(3,1,2,0));
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUShort4
+(
+ CONST XMUSHORT4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)pSource->x;
+ V.vector4_f32[1] = (FLOAT)pSource->y;
+ V.vector4_f32[2] = (FLOAT)pSource->z;
+ V.vector4_f32[3] = (FLOAT)pSource->w;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ static const XMVECTORF32 FixaddY16W16 = {0,0,32768.0f,32768.0f};
+ XMASSERT(pSource);
+ // Splat the color in all four entries (x,z,y,w)
+ __m128d vIntd = _mm_load1_pd(reinterpret_cast<const double *>(&pSource->x));
+ // Shift x&0ffff,z&0xffff,y&0xffff0000,w&0xffff0000
+ __m128 vTemp = _mm_and_ps(reinterpret_cast<const __m128 *>(&vIntd)[0],g_XMMaskX16Y16Z16W16);
+ // y and w are signed! Flip the bits to convert the order to unsigned
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipZW);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // Fix y and w because they are 65536 too large
+ vTemp = _mm_mul_ps(vTemp,g_XMFixupY16W16);
+ // y and w + 0x8000 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,FixaddY16W16);
+ // Very important! The entries are x,z,y,w, flip it to x,y,z,w
+ return _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(3,1,2,0));
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadXIcoN4
+(
+ CONST XMXICON4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtend[] = {0x00000000, 0xFFF00000};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0xFFFFFull) != 0x80000ull);
+ XMASSERT(((pSource->v >> 20) & 0xFFFFFull) != 0x80000ull);
+ XMASSERT(((pSource->v >> 40) & 0xFFFFFull) != 0x80000ull);
+
+ Element = (UINT)(pSource->v & 0xFFFFF);
+ V.vector4_f32[0] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]) / 524287.0f;
+ Element = (UINT)((pSource->v >> 20) & 0xFFFFF);
+ V.vector4_f32[1] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]) / 524287.0f;
+ Element = (UINT)((pSource->v >> 40) & 0xFFFFF);
+ V.vector4_f32[2] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]) / 524287.0f;
+ V.vector4_f32[3] = (FLOAT)(pSource->v >> 60) / 15.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT((pSource->v & 0xFFFFFull) != 0x80000ull);
+ XMASSERT(((pSource->v >> 20) & 0xFFFFFull) != 0x80000ull);
+ XMASSERT(((pSource->v >> 40) & 0xFFFFFull) != 0x80000ull);
+ static const XMVECTORF32 LoadXIcoN4Mul = {1.0f/524287.0f,1.0f/(524287.0f*4096.0f),1.0f/524287.0f,1.0f/(15.0f*4096.0f*65536.0f)};
+ XMASSERT(pSource);
+ // Grab the 64 bit structure
+ __m128d vResultd = _mm_load_sd(reinterpret_cast<const double *>(&pSource->v));
+ // By shifting down 8 bits, y and z are in seperate 32 bit elements
+ __m128i vResulti = _mm_srli_si128(reinterpret_cast<const __m128i *>(&vResultd)[0],8/8);
+ // vResultd has x and w, vResulti has y and z, merge into one as x,w,y,z
+ XMVECTOR vTemp = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResultd)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(1,0,1,0));
+ // Fix the entries to x,y,z,w
+ vTemp = _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(1,3,2,0));
+ // Mask x,y,z and w
+ vTemp = _mm_and_ps(vTemp,g_XMMaskIco4);
+ // x and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMXorXIco4);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x and z - 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddXIco4);
+ // Fix y and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,LoadXIcoN4Mul);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadXIco4
+(
+ CONST XMXICO4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtend[] = {0x00000000, 0xFFF00000};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0xFFFFFull) != 0x80000ull);
+ XMASSERT(((pSource->v >> 20) & 0xFFFFFull) != 0x80000ull);
+ XMASSERT(((pSource->v >> 40) & 0xFFFFFull) != 0x80000ull);
+
+ Element = (UINT)(pSource->v & 0xFFFFF);
+ V.vector4_f32[0] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]);
+ Element = (UINT)((pSource->v >> 20) & 0xFFFFF);
+ V.vector4_f32[1] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]);
+ Element = (UINT)((pSource->v >> 40) & 0xFFFFF);
+ V.vector4_f32[2] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]);
+ V.vector4_f32[3] = (FLOAT)(pSource->v >> 60);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT((pSource->v & 0xFFFFFull) != 0x80000ull);
+ XMASSERT(((pSource->v >> 20) & 0xFFFFFull) != 0x80000ull);
+ XMASSERT(((pSource->v >> 40) & 0xFFFFFull) != 0x80000ull);
+ XMASSERT(pSource);
+ // Grab the 64 bit structure
+ __m128d vResultd = _mm_load_sd(reinterpret_cast<const double *>(&pSource->v));
+ // By shifting down 8 bits, y and z are in seperate 32 bit elements
+ __m128i vResulti = _mm_srli_si128(reinterpret_cast<const __m128i *>(&vResultd)[0],8/8);
+ // vResultd has x and w, vResulti has y and z, merge into one as x,w,y,z
+ XMVECTOR vTemp = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResultd)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(1,0,1,0));
+ // Fix the entries to x,y,z,w
+ vTemp = _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(1,3,2,0));
+ // Mask x,y,z and w
+ vTemp = _mm_and_ps(vTemp,g_XMMaskIco4);
+ // x and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMXorXIco4);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x and z - 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddXIco4);
+ // Fix y and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,g_XMMulIco4);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUIcoN4
+(
+ CONST XMUICON4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)(pSource->v & 0xFFFFF) / 1048575.0f;
+ V.vector4_f32[1] = (FLOAT)((pSource->v >> 20) & 0xFFFFF) / 1048575.0f;
+ V.vector4_f32[2] = (FLOAT)((pSource->v >> 40) & 0xFFFFF) / 1048575.0f;
+ V.vector4_f32[3] = (FLOAT)(pSource->v >> 60) / 15.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 LoadUIcoN4Mul = {1.0f/1048575.0f,1.0f/(1048575.0f*4096.0f),1.0f/1048575.0f,1.0f/(15.0f*4096.0f*65536.0f)};
+ XMASSERT(pSource);
+ // Grab the 64 bit structure
+ __m128d vResultd = _mm_load_sd(reinterpret_cast<const double *>(&pSource->v));
+ // By shifting down 8 bits, y and z are in seperate 32 bit elements
+ __m128i vResulti = _mm_srli_si128(reinterpret_cast<const __m128i *>(&vResultd)[0],8/8);
+ // vResultd has x and w, vResulti has y and z, merge into one as x,w,y,z
+ XMVECTOR vTemp = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResultd)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(1,0,1,0));
+ // Fix the entries to x,y,z,w
+ vTemp = _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(1,3,2,0));
+ // Mask x,y,z and w
+ vTemp = _mm_and_ps(vTemp,g_XMMaskIco4);
+ // x and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipYW);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x and z - 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddUIco4);
+ // Fix y and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,LoadUIcoN4Mul);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUIco4
+(
+ CONST XMUICO4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)(pSource->v & 0xFFFFF);
+ V.vector4_f32[1] = (FLOAT)((pSource->v >> 20) & 0xFFFFF);
+ V.vector4_f32[2] = (FLOAT)((pSource->v >> 40) & 0xFFFFF);
+ V.vector4_f32[3] = (FLOAT)(pSource->v >> 60);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Grab the 64 bit structure
+ __m128d vResultd = _mm_load_sd(reinterpret_cast<const double *>(&pSource->v));
+ // By shifting down 8 bits, y and z are in seperate 32 bit elements
+ __m128i vResulti = _mm_srli_si128(reinterpret_cast<const __m128i *>(&vResultd)[0],8/8);
+ // vResultd has x and w, vResulti has y and z, merge into one as x,w,y,z
+ XMVECTOR vTemp = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResultd)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(1,0,1,0));
+ // Fix the entries to x,y,z,w
+ vTemp = _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(1,3,2,0));
+ // Mask x,y,z and w
+ vTemp = _mm_and_ps(vTemp,g_XMMaskIco4);
+ // x and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipYW);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x and z - 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddUIco4);
+ // Fix y and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,g_XMMulIco4);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadIcoN4
+(
+ CONST XMICON4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtend[] = {0x00000000, 0xFFF00000};
+ static CONST UINT SignExtendW[] = {0x00000000, 0xFFFFFFF0};
+
+ XMASSERT(pSource);
+
+ Element = (UINT)(pSource->v & 0xFFFFF);
+ V.vector4_f32[0] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]) / 524287.0f;
+ Element = (UINT)((pSource->v >> 20) & 0xFFFFF);
+ V.vector4_f32[1] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]) / 524287.0f;
+ Element = (UINT)((pSource->v >> 40) & 0xFFFFF);
+ V.vector4_f32[2] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]) / 524287.0f;
+ Element = (UINT)(pSource->v >> 60);
+ V.vector4_f32[3] = (FLOAT)(INT)(Element | SignExtendW[Element >> 3]) / 7.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 LoadIcoN4Mul = {1.0f/524287.0f,1.0f/(524287.0f*4096.0f),1.0f/524287.0f,1.0f/(7.0f*4096.0f*65536.0f)};
+ XMASSERT(pSource);
+ // Grab the 64 bit structure
+ __m128d vResultd = _mm_load_sd(reinterpret_cast<const double *>(&pSource->v));
+ // By shifting down 8 bits, y and z are in seperate 32 bit elements
+ __m128i vResulti = _mm_srli_si128(reinterpret_cast<const __m128i *>(&vResultd)[0],8/8);
+ // vResultd has x and w, vResulti has y and z, merge into one as x,w,y,z
+ XMVECTOR vTemp = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResultd)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(1,0,1,0));
+ // Fix the entries to x,y,z,w
+ vTemp = _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(1,3,2,0));
+ // Mask x,y,z and w
+ vTemp = _mm_and_ps(vTemp,g_XMMaskIco4);
+ // x and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMXorIco4);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x and z - 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddIco4);
+ // Fix y and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,LoadIcoN4Mul);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadIco4
+(
+ CONST XMICO4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtend[] = {0x00000000, 0xFFF00000};
+ static CONST UINT SignExtendW[] = {0x00000000, 0xFFFFFFF0};
+
+ XMASSERT(pSource);
+
+ Element = (UINT)(pSource->v & 0xFFFFF);
+ V.vector4_f32[0] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]);
+ Element = (UINT)((pSource->v >> 20) & 0xFFFFF);
+ V.vector4_f32[1] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]);
+ Element = (UINT)((pSource->v >> 40) & 0xFFFFF);
+ V.vector4_f32[2] = (FLOAT)(INT)(Element | SignExtend[Element >> 19]);
+ Element = (UINT)(pSource->v >> 60);
+ V.vector4_f32[3] = (FLOAT)(INT)(Element | SignExtendW[Element >> 3]);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Grab the 64 bit structure
+ __m128d vResultd = _mm_load_sd(reinterpret_cast<const double *>(&pSource->v));
+ // By shifting down 8 bits, y and z are in seperate 32 bit elements
+ __m128i vResulti = _mm_srli_si128(reinterpret_cast<const __m128i *>(&vResultd)[0],8/8);
+ // vResultd has x and w, vResulti has y and z, merge into one as x,w,y,z
+ XMVECTOR vTemp = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResultd)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(1,0,1,0));
+ // Fix the entries to x,y,z,w
+ vTemp = _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(1,3,2,0));
+ // Mask x,y,z and w
+ vTemp = _mm_and_ps(vTemp,g_XMMaskIco4);
+ // x and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMXorIco4);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x and z - 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddIco4);
+ // Fix y and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,g_XMMulIco4);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadXDecN4
+(
+ CONST XMXDECN4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtend[] = {0x00000000, 0xFFFFFC00};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 20) & 0x3FF) != 0x200);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]) / 511.0f;
+ Element = (pSource->v >> 10) & 0x3FF;
+ V.vector4_f32[1] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]) / 511.0f;
+ Element = (pSource->v >> 20) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]) / 511.0f;
+ V.vector4_f32[3] = (FLOAT)(pSource->v >> 30) / 3.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Splat the color in all four entries
+ __m128 vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Shift R&0xFF0000, G&0xFF00, B&0xFF, A&0xFF000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskA2B10G10R10);
+ // a is unsigned! Flip the bit to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipA2B10G10R10);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // RGB + 0, A + 0x80000000.f to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,g_XMFixAA2B10G10R10);
+ // Convert 0-255 to 0.0f-1.0f
+ return _mm_mul_ps(vTemp,g_XMNormalizeA2B10G10R10);
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadXDec4
+(
+ CONST XMXDEC4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtend[] = {0x00000000, 0xFFFFFC00};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 20) & 0x3FF) != 0x200);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]);
+ Element = (pSource->v >> 10) & 0x3FF;
+ V.vector4_f32[1] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]);
+ Element = (pSource->v >> 20) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]);
+ V.vector4_f32[3] = (FLOAT)(pSource->v >> 30);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 20) & 0x3FF) != 0x200);
+ static const XMVECTORI32 XDec4Xor = {0x200, 0x200<<10, 0x200<<20, 0x80000000};
+ static const XMVECTORF32 XDec4Add = {-512.0f,-512.0f*1024.0f,-512.0f*1024.0f*1024.0f,32768*65536.0f};
+ XMASSERT(pSource);
+ // Splat the color in all four entries
+ XMVECTOR vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Shift R&0xFF0000, G&0xFF00, B&0xFF, A&0xFF000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskDec4);
+ // a is unsigned! Flip the bit to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,XDec4Xor);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // RGB + 0, A + 0x80000000.f to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,XDec4Add);
+ // Convert 0-255 to 0.0f-1.0f
+ vTemp = _mm_mul_ps(vTemp,g_XMMulDec4);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUDecN4
+(
+ CONST XMUDECN4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+
+ XMASSERT(pSource);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)Element / 1023.0f;
+ Element = (pSource->v >> 10) & 0x3FF;
+ V.vector4_f32[1] = (FLOAT)Element / 1023.0f;
+ Element = (pSource->v >> 20) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)Element / 1023.0f;
+ V.vector4_f32[3] = (FLOAT)(pSource->v >> 30) / 3.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ static const XMVECTORF32 UDecN4Mul = {1.0f/1023.0f,1.0f/(1023.0f*1024.0f),1.0f/(1023.0f*1024.0f*1024.0f),1.0f/(3.0f*1024.0f*1024.0f*1024.0f)};
+ // Splat the color in all four entries
+ XMVECTOR vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Shift R&0xFF0000, G&0xFF00, B&0xFF, A&0xFF000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskDec4);
+ // a is unsigned! Flip the bit to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipW);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // RGB + 0, A + 0x80000000.f to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,g_XMAddUDec4);
+ // Convert 0-255 to 0.0f-1.0f
+ vTemp = _mm_mul_ps(vTemp,UDecN4Mul);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUDec4
+(
+ CONST XMUDEC4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+
+ XMASSERT(pSource);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)Element;
+ Element = (pSource->v >> 10) & 0x3FF;
+ V.vector4_f32[1] = (FLOAT)Element;
+ Element = (pSource->v >> 20) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)Element;
+ V.vector4_f32[3] = (FLOAT)(pSource->v >> 30);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Splat the color in all four entries
+ XMVECTOR vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Shift R&0xFF0000, G&0xFF00, B&0xFF, A&0xFF000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskDec4);
+ // a is unsigned! Flip the bit to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipW);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // RGB + 0, A + 0x80000000.f to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,g_XMAddUDec4);
+ // Convert 0-255 to 0.0f-1.0f
+ vTemp = _mm_mul_ps(vTemp,g_XMMulDec4);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadDecN4
+(
+ CONST XMDECN4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtend[] = {0x00000000, 0xFFFFFC00};
+ static CONST UINT SignExtendW[] = {0x00000000, 0xFFFFFFFC};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 20) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 30) & 0x3) != 0x2);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]) / 511.0f;
+ Element = (pSource->v >> 10) & 0x3FF;
+ V.vector4_f32[1] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]) / 511.0f;
+ Element = (pSource->v >> 20) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]) / 511.0f;
+ Element = pSource->v >> 30;
+ V.vector4_f32[3] = (FLOAT)(SHORT)(Element | SignExtendW[Element >> 1]);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 20) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 30) & 0x3) != 0x2);
+ static const XMVECTORF32 DecN4Mul = {1.0f/511.0f,1.0f/(511.0f*1024.0f),1.0f/(511.0f*1024.0f*1024.0f),1.0f/(1024.0f*1024.0f*1024.0f)};
+ // Splat the color in all four entries
+ XMVECTOR vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Shift R&0xFF0000, G&0xFF00, B&0xFF, A&0xFF000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskDec4);
+ // a is unsigned! Flip the bit to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMXorDec4);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // RGB + 0, A + 0x80000000.f to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,g_XMAddDec4);
+ // Convert 0-255 to 0.0f-1.0f
+ vTemp = _mm_mul_ps(vTemp,DecN4Mul);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadDec4
+(
+ CONST XMDEC4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+ UINT Element;
+ static CONST UINT SignExtend[] = {0x00000000, 0xFFFFFC00};
+ static CONST UINT SignExtendW[] = {0x00000000, 0xFFFFFFFC};
+
+ XMASSERT(pSource);
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 20) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 30) & 0x3) != 0x2);
+
+ Element = pSource->v & 0x3FF;
+ V.vector4_f32[0] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]);
+ Element = (pSource->v >> 10) & 0x3FF;
+ V.vector4_f32[1] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]);
+ Element = (pSource->v >> 20) & 0x3FF;
+ V.vector4_f32[2] = (FLOAT)(SHORT)(Element | SignExtend[Element >> 9]);
+ Element = pSource->v >> 30;
+ V.vector4_f32[3] = (FLOAT)(SHORT)(Element | SignExtendW[Element >> 1]);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT((pSource->v & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 10) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 20) & 0x3FF) != 0x200);
+ XMASSERT(((pSource->v >> 30) & 0x3) != 0x2);
+ XMASSERT(pSource);
+ // Splat the color in all four entries
+ XMVECTOR vTemp = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Shift R&0xFF0000, G&0xFF00, B&0xFF, A&0xFF000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskDec4);
+ // a is unsigned! Flip the bit to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMXorDec4);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // RGB + 0, A + 0x80000000.f to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,g_XMAddDec4);
+ // Convert 0-255 to 0.0f-1.0f
+ vTemp = _mm_mul_ps(vTemp,g_XMMulDec4);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUByteN4
+(
+ CONST XMUBYTEN4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)pSource->x / 255.0f;
+ V.vector4_f32[1] = (FLOAT)pSource->y / 255.0f;
+ V.vector4_f32[2] = (FLOAT)pSource->z / 255.0f;
+ V.vector4_f32[3] = (FLOAT)pSource->w / 255.0f;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 LoadUByteN4Mul = {1.0f/255.0f,1.0f/(255.0f*256.0f),1.0f/(255.0f*65536.0f),1.0f/(255.0f*65536.0f*256.0f)};
+ XMASSERT(pSource);
+ // Splat the color in all four entries (x,z,y,w)
+ XMVECTOR vTemp = _mm_load1_ps(reinterpret_cast<const float *>(&pSource->x));
+ // Mask x&0ff,y&0xff00,z&0xff0000,w&0xff000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskByte4);
+ // w is signed! Flip the bits to convert the order to unsigned
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipW);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // w + 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddUDec4);
+ // Fix y, z and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,LoadUByteN4Mul);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUByte4
+(
+ CONST XMUBYTE4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)pSource->x;
+ V.vector4_f32[1] = (FLOAT)pSource->y;
+ V.vector4_f32[2] = (FLOAT)pSource->z;
+ V.vector4_f32[3] = (FLOAT)pSource->w;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 LoadUByte4Mul = {1.0f,1.0f/256.0f,1.0f/65536.0f,1.0f/(65536.0f*256.0f)};
+ XMASSERT(pSource);
+ // Splat the color in all four entries (x,z,y,w)
+ XMVECTOR vTemp = _mm_load1_ps(reinterpret_cast<const float *>(&pSource->x));
+ // Mask x&0ff,y&0xff00,z&0xff0000,w&0xff000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskByte4);
+ // w is signed! Flip the bits to convert the order to unsigned
+ vTemp = _mm_xor_ps(vTemp,g_XMFlipW);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // w + 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddUDec4);
+ // Fix y, z and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,LoadUByte4Mul);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadByteN4
+(
+ CONST XMBYTEN4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (pSource->x == -128) ? -1.f : ((FLOAT)pSource->x / 127.0f);
+ V.vector4_f32[1] = (pSource->y == -128) ? -1.f : ((FLOAT)pSource->y / 127.0f);
+ V.vector4_f32[2] = (pSource->z == -128) ? -1.f : ((FLOAT)pSource->z / 127.0f);
+ V.vector4_f32[3] = (pSource->w == -128) ? -1.f : ((FLOAT)pSource->w / 127.0f);
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 LoadByteN4Mul = {1.0f/127.0f,1.0f/(127.0f*256.0f),1.0f/(127.0f*65536.0f),1.0f/(127.0f*65536.0f*256.0f)};
+ XMASSERT(pSource);
+ // Splat the color in all four entries (x,z,y,w)
+ XMVECTOR vTemp = _mm_load1_ps(reinterpret_cast<const float *>(&pSource->x));
+ // Mask x&0ff,y&0xff00,z&0xff0000,w&0xff000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskByte4);
+ // x,y and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMXorByte4);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x, y and z - 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddByte4);
+ // Fix y, z and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,LoadByteN4Mul);
+ // Clamp result (for case of -128)
+ return _mm_max_ps( vTemp, g_XMNegativeOne );
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadByte4
+(
+ CONST XMBYTE4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR V;
+
+ XMASSERT(pSource);
+
+ V.vector4_f32[0] = (FLOAT)pSource->x;
+ V.vector4_f32[1] = (FLOAT)pSource->y;
+ V.vector4_f32[2] = (FLOAT)pSource->z;
+ V.vector4_f32[3] = (FLOAT)pSource->w;
+
+ return V;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 LoadByte4Mul = {1.0f,1.0f/256.0f,1.0f/65536.0f,1.0f/(65536.0f*256.0f)};
+ XMASSERT(pSource);
+ // Splat the color in all four entries (x,z,y,w)
+ XMVECTOR vTemp = _mm_load1_ps(reinterpret_cast<const float *>(&pSource->x));
+ // Mask x&0ff,y&0xff00,z&0xff0000,w&0xff000000
+ vTemp = _mm_and_ps(vTemp,g_XMMaskByte4);
+ // x,y and z are unsigned! Flip the bits to convert the order to signed
+ vTemp = _mm_xor_ps(vTemp,g_XMXorByte4);
+ // Convert to floating point numbers
+ vTemp = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vTemp)[0]);
+ // x, y and z - 0x80 to complete the conversion
+ vTemp = _mm_add_ps(vTemp,g_XMAddByte4);
+ // Fix y, z and w because they are too large
+ vTemp = _mm_mul_ps(vTemp,LoadByte4Mul);
+ return vTemp;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadUNibble4
+(
+ CONST XMUNIBBLE4* pSource
+)
+{
+#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
+ static const XMVECTORI32 UNibble4And = {0xF,0xF0,0xF00,0xF000};
+ static const XMVECTORF32 UNibble4Mul = {1.0f,1.0f/16.f,1.0f/256.f,1.0f/4096.f};
+ XMASSERT(pSource);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,UNibble4And);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Normalize x, y, and z
+ vResult = _mm_mul_ps(vResult,UNibble4Mul);
+ return vResult;
+#else
+ XMVECTOR V;
+ UINT Element;
+
+ XMASSERT(pSource);
+
+ Element = pSource->v & 0xF;
+ V.vector4_f32[0] = (FLOAT)Element;
+ Element = (pSource->v >> 4) & 0xF;
+ V.vector4_f32[1] = (FLOAT)Element;
+ Element = (pSource->v >> 8) & 0xF;
+ V.vector4_f32[2] = (FLOAT)Element;
+ Element = (pSource->v >> 12) & 0xF;
+ V.vector4_f32[3] = (FLOAT)Element;
+
+ return V;
+#endif // !_XM_SSE_INTRISICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadU555
+(
+ CONST XMU555* pSource
+)
+{
+#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
+ static const XMVECTORI32 U555And = {0x1F,0x1F<<5,0x1F<<10,0x8000};
+ static const XMVECTORF32 U555Mul = {1.0f,1.0f/32.f,1.0f/1024.f,1.0f/32768.f};
+ XMASSERT(pSource);
+ // Get the 32 bit value and splat it
+ XMVECTOR vResult = _mm_load_ps1(reinterpret_cast<const float *>(&pSource->v));
+ // Mask off x, y and z
+ vResult = _mm_and_ps(vResult,U555And);
+ // Convert to float
+ vResult = _mm_cvtepi32_ps(reinterpret_cast<const __m128i *>(&vResult)[0]);
+ // Normalize x, y, and z
+ vResult = _mm_mul_ps(vResult,U555Mul);
+ return vResult;
+#else
+ XMVECTOR V;
+ UINT Element;
+
+ XMASSERT(pSource);
+
+ Element = pSource->v & 0x1F;
+ V.vector4_f32[0] = (FLOAT)Element;
+ Element = (pSource->v >> 5) & 0x1F;
+ V.vector4_f32[1] = (FLOAT)Element;
+ Element = (pSource->v >> 10) & 0x1F;
+ V.vector4_f32[2] = (FLOAT)Element;
+ Element = (pSource->v >> 15) & 0x1;
+ V.vector4_f32[3] = (FLOAT)Element;
+
+ return V;
+#endif // !_XM_SSE_INTRISICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMVECTOR XMLoadColor
+(
+ CONST XMCOLOR* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMASSERT(pSource);
+ {
+ // INT -> Float conversions are done in one instruction.
+ // UINT -> Float calls a runtime function. Keep in INT
+ INT iColor = (INT)(pSource->c);
+ XMVECTOR vColor = {
+ (FLOAT)((iColor >> 16) & 0xFF) * (1.0f/255.0f),
+ (FLOAT)((iColor >> 8) & 0xFF) * (1.0f/255.0f),
+ (FLOAT)(iColor & 0xFF) * (1.0f/255.0f),
+ (FLOAT)((iColor >> 24) & 0xFF) * (1.0f/255.0f)
+ };
+ return vColor;
+ }
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Splat the color in all four entries
+ __m128i vInt = _mm_set1_epi32(pSource->c);
+ // Shift R&0xFF0000, G&0xFF00, B&0xFF, A&0xFF000000
+ vInt = _mm_and_si128(vInt,g_XMMaskA8R8G8B8);
+ // a is unsigned! Flip the bit to convert the order to signed
+ vInt = _mm_xor_si128(vInt,g_XMFlipA8R8G8B8);
+ // Convert to floating point numbers
+ XMVECTOR vTemp = _mm_cvtepi32_ps(vInt);
+ // RGB + 0, A + 0x80000000.f to undo the signed order.
+ vTemp = _mm_add_ps(vTemp,g_XMFixAA8R8G8B8);
+ // Convert 0-255 to 0.0f-1.0f
+ return _mm_mul_ps(vTemp,g_XMNormalizeA8R8G8B8);
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMMATRIX XMLoadFloat3x3
+(
+ CONST XMFLOAT3X3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMMATRIX M;
+
+ XMASSERT(pSource);
+
+ M.r[0].vector4_f32[0] = pSource->m[0][0];
+ M.r[0].vector4_f32[1] = pSource->m[0][1];
+ M.r[0].vector4_f32[2] = pSource->m[0][2];
+ M.r[0].vector4_f32[3] = 0.0f;
+
+ M.r[1].vector4_f32[0] = pSource->m[1][0];
+ M.r[1].vector4_f32[1] = pSource->m[1][1];
+ M.r[1].vector4_f32[2] = pSource->m[1][2];
+ M.r[1].vector4_f32[3] = 0.0f;
+
+ M.r[2].vector4_f32[0] = pSource->m[2][0];
+ M.r[2].vector4_f32[1] = pSource->m[2][1];
+ M.r[2].vector4_f32[2] = pSource->m[2][2];
+ M.r[2].vector4_f32[3] = 0.0f;
+
+ M.r[3].vector4_f32[0] = 0.0f;
+ M.r[3].vector4_f32[1] = 0.0f;
+ M.r[3].vector4_f32[2] = 0.0f;
+ M.r[3].vector4_f32[3] = 1.0f;
+
+ return M;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMMATRIX M;
+ XMVECTOR V1, V2, V3, Z, T1, T2, T3, T4, T5;
+
+ Z = _mm_setzero_ps();
+
+ XMASSERT(pSource);
+
+ V1 = _mm_loadu_ps( &pSource->m[0][0] );
+ V2 = _mm_loadu_ps( &pSource->m[1][1] );
+ V3 = _mm_load_ss( &pSource->m[2][2] );
+
+ T1 = _mm_unpackhi_ps( V1, Z );
+ T2 = _mm_unpacklo_ps( V2, Z );
+ T3 = _mm_shuffle_ps( V3, T2, _MM_SHUFFLE( 0, 1, 0, 0 ) );
+ T4 = _mm_movehl_ps( T2, T3 );
+ T5 = _mm_movehl_ps( Z, T1 );
+
+ M.r[0] = _mm_movelh_ps( V1, T1 );
+ M.r[1] = _mm_add_ps( T4, T5 );
+ M.r[2] = _mm_shuffle_ps( V2, V3, _MM_SHUFFLE(1, 0, 3, 2) );
+ M.r[3] = g_XMIdentityR3;
+
+ return M;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMMATRIX XMLoadFloat4x3
+(
+ CONST XMFLOAT4X3* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMMATRIX M;
+ XMASSERT(pSource);
+
+ ((UINT *)(&M.r[0].vector4_f32[0]))[0] = ((const UINT *)(&pSource->m[0][0]))[0];
+ ((UINT *)(&M.r[0].vector4_f32[1]))[0] = ((const UINT *)(&pSource->m[0][1]))[0];
+ ((UINT *)(&M.r[0].vector4_f32[2]))[0] = ((const UINT *)(&pSource->m[0][2]))[0];
+ M.r[0].vector4_f32[3] = 0.0f;
+
+ ((UINT *)(&M.r[1].vector4_f32[0]))[0] = ((const UINT *)(&pSource->m[1][0]))[0];
+ ((UINT *)(&M.r[1].vector4_f32[1]))[0] = ((const UINT *)(&pSource->m[1][1]))[0];
+ ((UINT *)(&M.r[1].vector4_f32[2]))[0] = ((const UINT *)(&pSource->m[1][2]))[0];
+ M.r[1].vector4_f32[3] = 0.0f;
+
+ ((UINT *)(&M.r[2].vector4_f32[0]))[0] = ((const UINT *)(&pSource->m[2][0]))[0];
+ ((UINT *)(&M.r[2].vector4_f32[1]))[0] = ((const UINT *)(&pSource->m[2][1]))[0];
+ ((UINT *)(&M.r[2].vector4_f32[2]))[0] = ((const UINT *)(&pSource->m[2][2]))[0];
+ M.r[2].vector4_f32[3] = 0.0f;
+
+ ((UINT *)(&M.r[3].vector4_f32[0]))[0] = ((const UINT *)(&pSource->m[3][0]))[0];
+ ((UINT *)(&M.r[3].vector4_f32[1]))[0] = ((const UINT *)(&pSource->m[3][1]))[0];
+ ((UINT *)(&M.r[3].vector4_f32[2]))[0] = ((const UINT *)(&pSource->m[3][2]))[0];
+ M.r[3].vector4_f32[3] = 1.0f;
+
+ return M;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Use unaligned load instructions to
+ // load the 12 floats
+ // vTemp1 = x1,y1,z1,x2
+ XMVECTOR vTemp1 = _mm_loadu_ps(&pSource->m[0][0]);
+ // vTemp2 = y2,z2,x3,y3
+ XMVECTOR vTemp2 = _mm_loadu_ps(&pSource->m[1][1]);
+ // vTemp4 = z3,x4,y4,z4
+ XMVECTOR vTemp4 = _mm_loadu_ps(&pSource->m[2][2]);
+ // vTemp3 = x3,y3,z3,z3
+ XMVECTOR vTemp3 = _mm_shuffle_ps(vTemp2,vTemp4,_MM_SHUFFLE(0,0,3,2));
+ // vTemp2 = y2,z2,x2,x2
+ vTemp2 = _mm_shuffle_ps(vTemp2,vTemp1,_MM_SHUFFLE(3,3,1,0));
+ // vTemp2 = x2,y2,z2,z2
+ vTemp2 = _mm_shuffle_ps(vTemp2,vTemp2,_MM_SHUFFLE(1,1,0,2));
+ // vTemp1 = x1,y1,z1,0
+ vTemp1 = _mm_and_ps(vTemp1,g_XMMask3);
+ // vTemp2 = x2,y2,z2,0
+ vTemp2 = _mm_and_ps(vTemp2,g_XMMask3);
+ // vTemp3 = x3,y3,z3,0
+ vTemp3 = _mm_and_ps(vTemp3,g_XMMask3);
+ // vTemp4i = x4,y4,z4,0
+ __m128i vTemp4i = _mm_srli_si128(reinterpret_cast<const __m128i *>(&vTemp4)[0],32/8);
+ // vTemp4i = x4,y4,z4,1.0f
+ vTemp4i = _mm_or_si128(vTemp4i,g_XMIdentityR3);
+ XMMATRIX M(vTemp1,
+ vTemp2,
+ vTemp3,
+ reinterpret_cast<const __m128 *>(&vTemp4i)[0]);
+ return M;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMMATRIX XMLoadFloat4x3A
+(
+ CONST XMFLOAT4X3A* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMMATRIX M;
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ M.r[0].vector4_f32[0] = pSource->m[0][0];
+ M.r[0].vector4_f32[1] = pSource->m[0][1];
+ M.r[0].vector4_f32[2] = pSource->m[0][2];
+ M.r[0].vector4_f32[3] = 0.0f;
+
+ M.r[1].vector4_f32[0] = pSource->m[1][0];
+ M.r[1].vector4_f32[1] = pSource->m[1][1];
+ M.r[1].vector4_f32[2] = pSource->m[1][2];
+ M.r[1].vector4_f32[3] = 0.0f;
+
+ M.r[2].vector4_f32[0] = pSource->m[2][0];
+ M.r[2].vector4_f32[1] = pSource->m[2][1];
+ M.r[2].vector4_f32[2] = pSource->m[2][2];
+ M.r[2].vector4_f32[3] = 0.0f;
+
+ M.r[3].vector4_f32[0] = pSource->m[3][0];
+ M.r[3].vector4_f32[1] = pSource->m[3][1];
+ M.r[3].vector4_f32[2] = pSource->m[3][2];
+ M.r[3].vector4_f32[3] = 1.0f;
+
+ return M;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ // Use aligned load instructions to
+ // load the 12 floats
+ // vTemp1 = x1,y1,z1,x2
+ XMVECTOR vTemp1 = _mm_load_ps(&pSource->m[0][0]);
+ // vTemp2 = y2,z2,x3,y3
+ XMVECTOR vTemp2 = _mm_load_ps(&pSource->m[1][1]);
+ // vTemp4 = z3,x4,y4,z4
+ XMVECTOR vTemp4 = _mm_load_ps(&pSource->m[2][2]);
+ // vTemp3 = x3,y3,z3,z3
+ XMVECTOR vTemp3 = _mm_shuffle_ps(vTemp2,vTemp4,_MM_SHUFFLE(0,0,3,2));
+ // vTemp2 = y2,z2,x2,x2
+ vTemp2 = _mm_shuffle_ps(vTemp2,vTemp1,_MM_SHUFFLE(3,3,1,0));
+ // vTemp2 = x2,y2,z2,z2
+ vTemp2 = _mm_shuffle_ps(vTemp2,vTemp2,_MM_SHUFFLE(1,1,0,2));
+ // vTemp1 = x1,y1,z1,0
+ vTemp1 = _mm_and_ps(vTemp1,g_XMMask3);
+ // vTemp2 = x2,y2,z2,0
+ vTemp2 = _mm_and_ps(vTemp2,g_XMMask3);
+ // vTemp3 = x3,y3,z3,0
+ vTemp3 = _mm_and_ps(vTemp3,g_XMMask3);
+ // vTemp4i = x4,y4,z4,0
+ __m128i vTemp4i = _mm_srli_si128(reinterpret_cast<const __m128i *>(&vTemp4)[0],32/8);
+ // vTemp4i = x4,y4,z4,1.0f
+ vTemp4i = _mm_or_si128(vTemp4i,g_XMIdentityR3);
+ XMMATRIX M(vTemp1,
+ vTemp2,
+ vTemp3,
+ reinterpret_cast<const __m128 *>(&vTemp4i)[0]);
+ return M;
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMMATRIX XMLoadFloat4x4
+(
+ CONST XMFLOAT4X4* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+ XMMATRIX M;
+ XMASSERT(pSource);
+
+ ((UINT *)(&M.r[0].vector4_f32[0]))[0] = ((const UINT *)(&pSource->m[0][0]))[0];
+ ((UINT *)(&M.r[0].vector4_f32[1]))[0] = ((const UINT *)(&pSource->m[0][1]))[0];
+ ((UINT *)(&M.r[0].vector4_f32[2]))[0] = ((const UINT *)(&pSource->m[0][2]))[0];
+ ((UINT *)(&M.r[0].vector4_f32[3]))[0] = ((const UINT *)(&pSource->m[0][3]))[0];
+
+ ((UINT *)(&M.r[1].vector4_f32[0]))[0] = ((const UINT *)(&pSource->m[1][0]))[0];
+ ((UINT *)(&M.r[1].vector4_f32[1]))[0] = ((const UINT *)(&pSource->m[1][1]))[0];
+ ((UINT *)(&M.r[1].vector4_f32[2]))[0] = ((const UINT *)(&pSource->m[1][2]))[0];
+ ((UINT *)(&M.r[1].vector4_f32[3]))[0] = ((const UINT *)(&pSource->m[1][3]))[0];
+
+ ((UINT *)(&M.r[2].vector4_f32[0]))[0] = ((const UINT *)(&pSource->m[2][0]))[0];
+ ((UINT *)(&M.r[2].vector4_f32[1]))[0] = ((const UINT *)(&pSource->m[2][1]))[0];
+ ((UINT *)(&M.r[2].vector4_f32[2]))[0] = ((const UINT *)(&pSource->m[2][2]))[0];
+ ((UINT *)(&M.r[2].vector4_f32[3]))[0] = ((const UINT *)(&pSource->m[2][3]))[0];
+
+ ((UINT *)(&M.r[3].vector4_f32[0]))[0] = ((const UINT *)(&pSource->m[3][0]))[0];
+ ((UINT *)(&M.r[3].vector4_f32[1]))[0] = ((const UINT *)(&pSource->m[3][1]))[0];
+ ((UINT *)(&M.r[3].vector4_f32[2]))[0] = ((const UINT *)(&pSource->m[3][2]))[0];
+ ((UINT *)(&M.r[3].vector4_f32[3]))[0] = ((const UINT *)(&pSource->m[3][3]))[0];
+
+ return M;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pSource);
+ XMMATRIX M;
+
+ M.r[0] = _mm_loadu_ps( &pSource->_11 );
+ M.r[1] = _mm_loadu_ps( &pSource->_21 );
+ M.r[2] = _mm_loadu_ps( &pSource->_31 );
+ M.r[3] = _mm_loadu_ps( &pSource->_41 );
+
+ return M;
+#elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE XMMATRIX XMLoadFloat4x4A
+(
+ CONST XMFLOAT4X4A* pSource
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMMATRIX M;
+
+ XMASSERT(pSource);
+ XMASSERT(((UINT_PTR)pSource & 0xF) == 0);
+
+ M.r[0].vector4_f32[0] = pSource->m[0][0];
+ M.r[0].vector4_f32[1] = pSource->m[0][1];
+ M.r[0].vector4_f32[2] = pSource->m[0][2];
+ M.r[0].vector4_f32[3] = pSource->m[0][3];
+
+ M.r[1].vector4_f32[0] = pSource->m[1][0];
+ M.r[1].vector4_f32[1] = pSource->m[1][1];
+ M.r[1].vector4_f32[2] = pSource->m[1][2];
+ M.r[1].vector4_f32[3] = pSource->m[1][3];
+
+ M.r[2].vector4_f32[0] = pSource->m[2][0];
+ M.r[2].vector4_f32[1] = pSource->m[2][1];
+ M.r[2].vector4_f32[2] = pSource->m[2][2];
+ M.r[2].vector4_f32[3] = pSource->m[2][3];
+
+ M.r[3].vector4_f32[0] = pSource->m[3][0];
+ M.r[3].vector4_f32[1] = pSource->m[3][1];
+ M.r[3].vector4_f32[2] = pSource->m[3][2];
+ M.r[3].vector4_f32[3] = pSource->m[3][3];
+
+ return M;
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMMATRIX M;
+
+ XMASSERT(pSource);
+
+ M.r[0] = _mm_load_ps( &pSource->_11 );
+ M.r[1] = _mm_load_ps( &pSource->_21 );
+ M.r[2] = _mm_load_ps( &pSource->_31 );
+ M.r[3] = _mm_load_ps( &pSource->_41 );
+
+ return M;
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+/****************************************************************************
+ *
+ * Vector and matrix store operations
+ *
+ ****************************************************************************/
+
+XMFINLINE VOID XMStoreInt
+(
+ UINT* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ *pDestination = XMVectorGetIntX( V );
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ _mm_store_ss( (float*)pDestination, V );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat
+(
+ FLOAT* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ *pDestination = XMVectorGetX( V );
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ _mm_store_ss( pDestination, V );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreInt2
+(
+ UINT* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination[0] = V.vector4_u32[0];
+ pDestination[1] = V.vector4_u32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ XMVECTOR T = _mm_shuffle_ps( V, V, _MM_SHUFFLE( 1, 1, 1, 1 ) );
+ _mm_store_ss( (float*)&pDestination[0], V );
+ _mm_store_ss( (float*)&pDestination[1], T );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreSInt2
+(
+ XMINT2* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination->x = (INT)V.vector4_f32[0];
+ pDestination->y = (INT)V.vector4_f32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ // In case of positive overflow, detect it
+ XMVECTOR vOverflow = _mm_cmpgt_ps(V,g_XMMaxInt);
+ // Float to int conversion
+ __m128i vResulti = _mm_cvttps_epi32(V);
+ // If there was positive overflow, set to 0x7FFFFFFF
+ XMVECTOR vResult = _mm_and_ps(vOverflow,g_XMAbsMask);
+ vOverflow = _mm_andnot_ps(vOverflow,reinterpret_cast<const __m128 *>(&vResulti)[0]);
+ vOverflow = _mm_or_ps(vOverflow,vResult);
+ // Write two ints
+ XMVECTOR T = _mm_shuffle_ps( vOverflow, vOverflow, _MM_SHUFFLE( 1, 1, 1, 1 ) );
+ _mm_store_ss( (float*)&pDestination->x, vOverflow );
+ _mm_store_ss( (float*)&pDestination->y, T );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUInt2
+(
+ XMUINT2* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination->x = (UINT)V.vector4_f32[0];
+ pDestination->y = (UINT)V.vector4_f32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ // Clamp to >=0
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ // Any numbers that are too big, set to 0xFFFFFFFFU
+ XMVECTOR vOverflow = _mm_cmpgt_ps(vResult,g_XMMaxUInt);
+ XMVECTOR vValue = g_XMUnsignedFix;
+ // Too large for a signed integer?
+ XMVECTOR vMask = _mm_cmpge_ps(vResult,vValue);
+ // Zero for number's lower than 0x80000000, 32768.0f*65536.0f otherwise
+ vValue = _mm_and_ps(vValue,vMask);
+ // Perform fixup only on numbers too large (Keeps low bit precision)
+ vResult = _mm_sub_ps(vResult,vValue);
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Convert from signed to unsigned pnly if greater than 0x80000000
+ vMask = _mm_and_ps(vMask,g_XMNegativeZero);
+ vResult = _mm_xor_ps(reinterpret_cast<const __m128 *>(&vResulti)[0],vMask);
+ // On those that are too large, set to 0xFFFFFFFF
+ vResult = _mm_or_ps(vResult,vOverflow);
+ // Write two uints
+ XMVECTOR T = _mm_shuffle_ps( vResult, vResult, _MM_SHUFFLE( 1, 1, 1, 1 ) );
+ _mm_store_ss( (float*)&pDestination->x, vResult );
+ _mm_store_ss( (float*)&pDestination->y, T );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreInt2A
+(
+ UINT* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ pDestination[0] = V.vector4_u32[0];
+ pDestination[1] = V.vector4_u32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ _mm_storel_epi64( (__m128i*)pDestination, reinterpret_cast<const __m128i *>(&V)[0] );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat2
+(
+ XMFLOAT2* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination->x = V.vector4_f32[0];
+ pDestination->y = V.vector4_f32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ XMVECTOR T = _mm_shuffle_ps( V, V, _MM_SHUFFLE( 1, 1, 1, 1 ) );
+ _mm_store_ss( &pDestination->x, V );
+ _mm_store_ss( &pDestination->y, T );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat2A
+(
+ XMFLOAT2A* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ pDestination->x = V.vector4_f32[0];
+ pDestination->y = V.vector4_f32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ _mm_storel_epi64( (__m128i*)pDestination, reinterpret_cast<const __m128i *>(&V)[0] );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreHalf2
+(
+ XMHALF2* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+
+ pDestination->x = XMConvertFloatToHalf(V.vector4_f32[0]);
+ pDestination->y = XMConvertFloatToHalf(V.vector4_f32[1]);
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ pDestination->x = XMConvertFloatToHalf(XMVectorGetX(V));
+ pDestination->y = XMConvertFloatToHalf(XMVectorGetY(V));
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreShortN2
+(
+ XMSHORTN2* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {32767.0f, 32767.0f, 32767.0f, 32767.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, g_XMNegativeOne.v, g_XMOne.v);
+ N = XMVectorMultiply(N, Scale.v);
+ N = XMVectorRound(N);
+
+ pDestination->x = (SHORT)N.vector4_f32[0];
+ pDestination->y = (SHORT)N.vector4_f32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Scale = {32767.0f, 32767.0f, 32767.0f, 32767.0f};
+
+ XMVECTOR vResult = _mm_max_ps(V,g_XMNegativeOne);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ vResult = _mm_mul_ps(vResult,Scale);
+ __m128i vResulti = _mm_cvtps_epi32(vResult);
+ vResulti = _mm_packs_epi32(vResulti,vResulti);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->x),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreShort2
+(
+ XMSHORT2* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Min = {-32767.0f, -32767.0f, -32767.0f, -32767.0f};
+ static CONST XMVECTOR Max = {32767.0f, 32767.0f, 32767.0f, 32767.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min, Max);
+ N = XMVectorRound(N);
+
+ pDestination->x = (SHORT)N.vector4_f32[0];
+ pDestination->y = (SHORT)N.vector4_f32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Min = {-32767.0f, -32767.0f, -32767.0f, -32767.0f};
+ static CONST XMVECTORF32 Max = {32767.0f, 32767.0f, 32767.0f, 32767.0f};
+ // Bounds check
+ XMVECTOR vResult = _mm_max_ps(V,Min);
+ vResult = _mm_min_ps(vResult,Max);
+ // Convert to int with rounding
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // Pack the ints into shorts
+ vInt = _mm_packs_epi32(vInt,vInt);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->x),reinterpret_cast<const __m128 *>(&vInt)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUShortN2
+(
+ XMUSHORTN2* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {65535.0f, 65535.0f, 65535.0f, 65535.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorSaturate(V);
+ N = XMVectorMultiplyAdd(N, Scale.v, g_XMOneHalf.v);
+ N = XMVectorTruncate(N);
+
+ pDestination->x = (SHORT)N.vector4_f32[0];
+ pDestination->y = (SHORT)N.vector4_f32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Scale = {65535.0f, 65535.0f, 65535.0f, 65535.0f};
+ // Bounds check
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ vResult = _mm_mul_ps(vResult,Scale);
+ // Convert to int with rounding
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // Since the SSE pack instruction clamps using signed rules,
+ // manually extract the values to store them to memory
+ pDestination->x = static_cast<SHORT>(_mm_extract_epi16(vInt,0));
+ pDestination->y = static_cast<SHORT>(_mm_extract_epi16(vInt,2));
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUShort2
+(
+ XMUSHORT2* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Max = {65535.0f, 65535.0f, 65535.0f, 65535.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max);
+ N = XMVectorRound(N);
+
+ pDestination->x = (SHORT)N.vector4_f32[0];
+ pDestination->y = (SHORT)N.vector4_f32[1];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Max = {65535.0f, 65535.0f, 65535.0f, 65535.0f};
+ // Bounds check
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,Max);
+ // Convert to int with rounding
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // Since the SSE pack instruction clamps using signed rules,
+ // manually extract the values to store them to memory
+ pDestination->x = static_cast<SHORT>(_mm_extract_epi16(vInt,0));
+ pDestination->y = static_cast<SHORT>(_mm_extract_epi16(vInt,2));
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreByteN2
+(
+ XMBYTEN2* pDestination,
+ FXMVECTOR V
+)
+{
+ XMVECTOR N;
+ XMFLOAT4A tmp;
+ static CONST XMVECTORF32 Scale = {127.0f, 127.0f, 127.0f, 127.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, g_XMNegativeOne.v, g_XMOne.v);
+ N = XMVectorMultiply(N, Scale.v);
+ N = XMVectorRound(N);
+
+ XMStoreFloat4A( &tmp, N );
+
+ pDestination->x = (CHAR)tmp.x;
+ pDestination->y = (CHAR)tmp.y;
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreByte2
+(
+ XMBYTE2* pDestination,
+ FXMVECTOR V
+)
+{
+ XMVECTOR N;
+ XMFLOAT4A tmp;
+ static CONST XMVECTOR Min = {-127.0f, -127.0f, -127.0f, -127.0f};
+ static CONST XMVECTOR Max = {127.0f, 127.0f, 127.0f, 127.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min, Max);
+ N = XMVectorRound(N);
+
+ XMStoreFloat4A( &tmp, N );
+
+ pDestination->x = (CHAR)tmp.x;
+ pDestination->y = (CHAR)tmp.y;
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUByteN2
+(
+ XMUBYTEN2* pDestination,
+ FXMVECTOR V
+)
+{
+ XMVECTOR N;
+ XMFLOAT4A tmp;
+ static CONST XMVECTORF32 Scale = {255.0f, 255.0f, 255.0f, 255.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorSaturate(V);
+ N = XMVectorMultiplyAdd(N, Scale.v, g_XMOneHalf.v);
+ N = XMVectorTruncate(N);
+
+ XMStoreFloat4A( &tmp, N );
+
+ pDestination->x = (BYTE)tmp.x;
+ pDestination->y = (BYTE)tmp.y;
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUByte2
+(
+ XMUBYTE2* pDestination,
+ FXMVECTOR V
+)
+{
+ XMVECTOR N;
+ static CONST XMVECTOR Max = {255.0f, 255.0f, 255.0f, 255.0f};
+ XMFLOAT4A tmp;
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max);
+ N = XMVectorRound(N);
+
+ XMStoreFloat4A( &tmp, N );
+
+ pDestination->x = (BYTE)tmp.x;
+ pDestination->y = (BYTE)tmp.y;
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreInt3
+(
+ UINT* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination[0] = V.vector4_u32[0];
+ pDestination[1] = V.vector4_u32[1];
+ pDestination[2] = V.vector4_u32[2];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ XMVECTOR T1 = _mm_shuffle_ps(V,V,_MM_SHUFFLE(1,1,1,1));
+ XMVECTOR T2 = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,2,2,2));
+ _mm_store_ss( (float*)pDestination, V );
+ _mm_store_ss( (float*)&pDestination[1], T1 );
+ _mm_store_ss( (float*)&pDestination[2], T2 );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreSInt3
+(
+ XMINT3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination->x = (INT)V.vector4_f32[0];
+ pDestination->y = (INT)V.vector4_f32[1];
+ pDestination->z = (INT)V.vector4_f32[2];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ // In case of positive overflow, detect it
+ XMVECTOR vOverflow = _mm_cmpgt_ps(V,g_XMMaxInt);
+ // Float to int conversion
+ __m128i vResulti = _mm_cvttps_epi32(V);
+ // If there was positive overflow, set to 0x7FFFFFFF
+ XMVECTOR vResult = _mm_and_ps(vOverflow,g_XMAbsMask);
+ vOverflow = _mm_andnot_ps(vOverflow,reinterpret_cast<const __m128 *>(&vResulti)[0]);
+ vOverflow = _mm_or_ps(vOverflow,vResult);
+ // Write 3 uints
+ XMVECTOR T1 = _mm_shuffle_ps(vOverflow,vOverflow,_MM_SHUFFLE(1,1,1,1));
+ XMVECTOR T2 = _mm_shuffle_ps(vOverflow,vOverflow,_MM_SHUFFLE(2,2,2,2));
+ _mm_store_ss( (float*)&pDestination->x, vOverflow );
+ _mm_store_ss( (float*)&pDestination->y, T1 );
+ _mm_store_ss( (float*)&pDestination->z, T2 );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUInt3
+(
+ XMUINT3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination->x = (UINT)V.vector4_f32[0];
+ pDestination->y = (UINT)V.vector4_f32[1];
+ pDestination->z = (UINT)V.vector4_f32[2];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ // Clamp to >=0
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ // Any numbers that are too big, set to 0xFFFFFFFFU
+ XMVECTOR vOverflow = _mm_cmpgt_ps(vResult,g_XMMaxUInt);
+ XMVECTOR vValue = g_XMUnsignedFix;
+ // Too large for a signed integer?
+ XMVECTOR vMask = _mm_cmpge_ps(vResult,vValue);
+ // Zero for number's lower than 0x80000000, 32768.0f*65536.0f otherwise
+ vValue = _mm_and_ps(vValue,vMask);
+ // Perform fixup only on numbers too large (Keeps low bit precision)
+ vResult = _mm_sub_ps(vResult,vValue);
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Convert from signed to unsigned pnly if greater than 0x80000000
+ vMask = _mm_and_ps(vMask,g_XMNegativeZero);
+ vResult = _mm_xor_ps(reinterpret_cast<const __m128 *>(&vResulti)[0],vMask);
+ // On those that are too large, set to 0xFFFFFFFF
+ vResult = _mm_or_ps(vResult,vOverflow);
+ // Write 3 uints
+ XMVECTOR T1 = _mm_shuffle_ps(vResult,vResult,_MM_SHUFFLE(1,1,1,1));
+ XMVECTOR T2 = _mm_shuffle_ps(vResult,vResult,_MM_SHUFFLE(2,2,2,2));
+ _mm_store_ss( (float*)&pDestination->x, vResult );
+ _mm_store_ss( (float*)&pDestination->y, T1 );
+ _mm_store_ss( (float*)&pDestination->z, T2 );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreInt3A
+(
+ UINT* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ pDestination[0] = V.vector4_u32[0];
+ pDestination[1] = V.vector4_u32[1];
+ pDestination[2] = V.vector4_u32[2];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ XMVECTOR T = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,2,2,2));
+ _mm_storel_epi64( (__m128i*)pDestination, reinterpret_cast<const __m128i *>(&V)[0] );
+ _mm_store_ss( (float*)&pDestination[2], T );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat3
+(
+ XMFLOAT3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination->x = V.vector4_f32[0];
+ pDestination->y = V.vector4_f32[1];
+ pDestination->z = V.vector4_f32[2];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ XMVECTOR T1 = _mm_shuffle_ps(V,V,_MM_SHUFFLE(1,1,1,1));
+ XMVECTOR T2 = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,2,2,2));
+ _mm_store_ss( &pDestination->x, V );
+ _mm_store_ss( &pDestination->y, T1 );
+ _mm_store_ss( &pDestination->z, T2 );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat3A
+(
+ XMFLOAT3A* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ pDestination->x = V.vector4_f32[0];
+ pDestination->y = V.vector4_f32[1];
+ pDestination->z = V.vector4_f32[2];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ XMVECTOR T = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,2,2,2));
+ _mm_storel_epi64( (__m128i*)pDestination, reinterpret_cast<const __m128i *>(&V)[0] );
+ _mm_store_ss( &pDestination->z, T );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUHenDN3
+(
+ XMUHENDN3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {2047.0f, 2047.0f, 1023.0f, 0.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorSaturate(V);
+ N = XMVectorMultiply(N, Scale.v);
+
+ pDestination->v = (((UINT)N.vector4_f32[2] & 0x3FF) << 22) |
+ (((UINT)N.vector4_f32[1] & 0x7FF) << 11) |
+ (((UINT)N.vector4_f32[0] & 0x7FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 ScaleUHenDN3 = {2047.0f, 2047.0f*2048.0f,1023.0f*(2048.0f*2048.0f)/2.0f,1.0f};
+ static const XMVECTORI32 MaskUHenDN3 = {0x7FF,0x7FF<<11,0x3FF<<(22-1),0};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUHenDN3);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUHenDN3);
+ // Do a horizontal or of 3 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(0,3,2,1));
+ // i = x|y
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti2,_MM_SHUFFLE(0,3,2,1));
+ // Add Z to itself to perform a single bit left shift
+ vResulti2 = _mm_add_epi32(vResulti2,vResulti2);
+ // i = x|y|z
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUHenD3
+(
+ XMUHEND3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Max = {2047.0f, 2047.0f, 1023.0f, 0.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max);
+
+ pDestination->v = (((UINT)N.vector4_f32[2] & 0x3FF) << 22) |
+ (((UINT)N.vector4_f32[1] & 0x7FF) << 11) |
+ (((UINT)N.vector4_f32[0] & 0x7FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 MaxUHenD3 = { 2047.0f, 2047.0f, 1023.0f, 1.0f};
+ static const XMVECTORF32 ScaleUHenD3 = {1.0f, 2048.0f,(2048.0f*2048.0f)/2.0f,1.0f};
+ static const XMVECTORI32 MaskUHenD3 = {0x7FF,0x7FF<<11,0x3FF<<(22-1),0};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,MaxUHenD3);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUHenD3);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUHenD3);
+ // Do a horizontal or of 3 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(0,3,2,1));
+ // i = x|y
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti2,_MM_SHUFFLE(0,3,2,1));
+ // Add Z to itself to perform a single bit left shift
+ vResulti2 = _mm_add_epi32(vResulti2,vResulti2);
+ // i = x|y|z
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreHenDN3
+(
+ XMHENDN3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {1023.0f, 1023.0f, 511.0f, 1.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, g_XMNegativeOne.v, g_XMOne.v);
+ N = XMVectorMultiply(N, Scale.v);
+
+ pDestination->v = (((INT)N.vector4_f32[2] & 0x3FF) << 22) |
+ (((INT)N.vector4_f32[1] & 0x7FF) << 11) |
+ (((INT)N.vector4_f32[0] & 0x7FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 ScaleHenDN3 = {1023.0f, 1023.0f*2048.0f,511.0f*(2048.0f*2048.0f),1.0f};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMNegativeOne);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleHenDN3);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,g_XMMaskHenD3);
+ // Do a horizontal or of all 4 entries
+ vResult = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResulti)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ vResult = _mm_shuffle_ps(vResult,vResult,_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreHenD3
+(
+ XMHEND3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Min = {-1023.0f, -1023.0f, -511.0f, -1.0f};
+ static CONST XMVECTOR Max = {1023.0f, 1023.0f, 511.0f, 1.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min, Max);
+
+ pDestination->v = (((INT)N.vector4_f32[2] & 0x3FF) << 22) |
+ (((INT)N.vector4_f32[1] & 0x7FF) << 11) |
+ (((INT)N.vector4_f32[0] & 0x7FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 MinHenD3 = {-1023.0f,-1023.0f,-511.0f,-1.0f};
+ static const XMVECTORF32 MaxHenD3 = { 1023.0f, 1023.0f, 511.0f, 1.0f};
+ static const XMVECTORF32 ScaleHenD3 = {1.0f, 2048.0f,(2048.0f*2048.0f),1.0f};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,MinHenD3);
+ vResult = _mm_min_ps(vResult,MaxHenD3);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleHenD3);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,g_XMMaskHenD3);
+ // Do a horizontal or of all 4 entries
+ vResult = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResulti)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ vResult = _mm_shuffle_ps(vResult,vResult,_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUDHenN3
+(
+ XMUDHENN3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {1023.0f, 2047.0f, 2047.0f, 0.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorSaturate(V);
+ N = XMVectorMultiply(N, Scale.v);
+
+ pDestination->v = (((UINT)N.vector4_f32[2] & 0x7FF) << 21) |
+ (((UINT)N.vector4_f32[1] & 0x7FF) << 10) |
+ (((UINT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 ScaleUDHenN3 = {1023.0f,2047.0f*1024.0f,2047.0f*(1024.0f*2048.0f)/2.0f,1.0f};
+ static const XMVECTORI32 MaskUDHenN3 = {0x3FF,0x7FF<<10,0x7FF<<(21-1),0};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUDHenN3);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUDHenN3);
+ // Do a horizontal or of 3 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(0,3,2,1));
+ // i = x|y
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti2,_MM_SHUFFLE(0,3,2,1));
+ // Add Z to itself to perform a single bit left shift
+ vResulti2 = _mm_add_epi32(vResulti2,vResulti2);
+ // i = x|y|z
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUDHen3
+(
+ XMUDHEN3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Max = {1023.0f, 2047.0f, 2047.0f, 0.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max);
+
+ pDestination->v = (((UINT)N.vector4_f32[2] & 0x7FF) << 21) |
+ (((UINT)N.vector4_f32[1] & 0x7FF) << 10) |
+ (((UINT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 MaxUDHen3 = { 1023.0f, 2047.0f, 2047.0f, 1.0f};
+ static const XMVECTORF32 ScaleUDHen3 = {1.0f, 1024.0f,(1024.0f*2048.0f)/2.0f,1.0f};
+ static const XMVECTORI32 MaskUDHen3 = {0x3FF,0x7FF<<10,0x7FF<<(21-1),0};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,MaxUDHen3);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUDHen3);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUDHen3);
+ // Do a horizontal or of 3 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(0,3,2,1));
+ // i = x|y
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti2,_MM_SHUFFLE(0,3,2,1));
+ // Add Z to itself to perform a single bit left shift
+ vResulti2 = _mm_add_epi32(vResulti2,vResulti2);
+ // i = x|y|z
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreDHenN3
+(
+ XMDHENN3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {511.0f, 1023.0f, 1023.0f, 1.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, g_XMNegativeOne.v, g_XMOne.v);
+ N = XMVectorMultiply(N, Scale.v);
+
+ pDestination->v = (((INT)N.vector4_f32[2] & 0x7FF) << 21) |
+ (((INT)N.vector4_f32[1] & 0x7FF) << 10) |
+ (((INT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 ScaleDHenN3 = {511.0f, 1023.0f*1024.0f,1023.0f*(1024.0f*2048.0f),1.0f};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMNegativeOne);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleDHenN3);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,g_XMMaskDHen3);
+ // Do a horizontal or of all 4 entries
+ vResult = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResulti)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ vResult = _mm_shuffle_ps(vResult,vResult,_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreDHen3
+(
+ XMDHEN3* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Min = {-511.0f, -1023.0f, -1023.0f, -1.0f};
+ static CONST XMVECTOR Max = {511.0f, 1023.0f, 1023.0f, 1.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min, Max);
+
+ pDestination->v = (((INT)N.vector4_f32[2] & 0x7FF) << 21) |
+ (((INT)N.vector4_f32[1] & 0x7FF) << 10) |
+ (((INT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 MinDHen3 = {-511.0f,-1023.0f,-1023.0f,-1.0f};
+ static const XMVECTORF32 MaxDHen3 = { 511.0f, 1023.0f, 1023.0f, 1.0f};
+ static const XMVECTORF32 ScaleDHen3 = {1.0f, 1024.0f,(1024.0f*2048.0f),1.0f};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,MinDHen3);
+ vResult = _mm_min_ps(vResult,MaxDHen3);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleDHen3);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,g_XMMaskDHen3);
+ // Do a horizontal or of all 4 entries
+ vResult = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResulti)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ vResult = _mm_shuffle_ps(vResult,vResult,_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreU565
+(
+ XMU565* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Max = {31.0f, 63.0f, 31.0f, 0.0f};
+ // Bounds check
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,Max);
+ // Convert to int with rounding
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // No SSE operations will write to 16-bit values, so we have to extract them manually
+ USHORT x = static_cast<USHORT>(_mm_extract_epi16(vInt,0));
+ USHORT y = static_cast<USHORT>(_mm_extract_epi16(vInt,2));
+ USHORT z = static_cast<USHORT>(_mm_extract_epi16(vInt,4));
+ pDestination->v = ((z & 0x1F) << 11) |
+ ((y & 0x3F) << 5) |
+ ((x & 0x1F));
+#else
+ XMVECTOR N;
+ static CONST XMVECTORF32 Max = {31.0f, 63.0f, 31.0f, 0.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max.v);
+ N = XMVectorRound(N);
+
+ pDestination->v = (((USHORT)N.vector4_f32[2] & 0x1F) << 11) |
+ (((USHORT)N.vector4_f32[1] & 0x3F) << 5) |
+ (((USHORT)N.vector4_f32[0] & 0x1F));
+#endif !_XM_SSE_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat3PK
+(
+ XMFLOAT3PK* pDestination,
+ FXMVECTOR V
+)
+{
+ _DECLSPEC_ALIGN_16_ UINT IValue[4];
+ UINT I, Sign, j;
+ UINT Result[3];
+
+ XMASSERT(pDestination);
+
+ XMStoreFloat3A( (XMFLOAT3A*)&IValue, V );
+
+ // X & Y Channels (5-bit exponent, 6-bit mantissa)
+ for(j=0; j < 2; ++j)
+ {
+ Sign = IValue[j] & 0x80000000;
+ I = IValue[j] & 0x7FFFFFFF;
+
+ if ((I & 0x7F800000) == 0x7F800000)
+ {
+ // INF or NAN
+ Result[j] = 0x7c0;
+ if (( I & 0x7FFFFF ) != 0)
+ {
+ Result[j] = 0x7c0 | (((I>>17)|(I>11)|(I>>6)|(I))&0x3f);
+ }
+ else if ( Sign )
+ {
+ // -INF is clamped to 0 since 3PK is positive only
+ Result[j] = 0;
+ }
+ }
+ else if ( Sign )
+ {
+ // 3PK is positive only, so clamp to zero
+ Result[j] = 0;
+ }
+ else if (I > 0x477E0000U)
+ {
+ // The number is too large to be represented as a float11, set to max
+ Result[j] = 0x7BF;
+ }
+ else
+ {
+ if (I < 0x38800000U)
+ {
+ // The number is too small to be represented as a normalized float11
+ // Convert it to a denormalized value.
+ UINT Shift = 113U - (I >> 23U);
+ I = (0x800000U | (I & 0x7FFFFFU)) >> Shift;
+ }
+ else
+ {
+ // Rebias the exponent to represent the value as a normalized float11
+ I += 0xC8000000U;
+ }
+
+ Result[j] = ((I + 0xFFFFU + ((I >> 17U) & 1U)) >> 17U)&0x7ffU;
+ }
+ }
+
+ // Z Channel (5-bit exponent, 5-bit mantissa)
+ Sign = IValue[2] & 0x80000000;
+ I = IValue[2] & 0x7FFFFFFF;
+
+ if ((I & 0x7F800000) == 0x7F800000)
+ {
+ // INF or NAN
+ Result[2] = 0x3e0;
+ if ( I & 0x7FFFFF )
+ {
+ Result[2] = 0x3e0 | (((I>>18)|(I>13)|(I>>3)|(I))&0x1f);
+ }
+ else if ( Sign )
+ {
+ // -INF is clamped to 0 since 3PK is positive only
+ Result[2] = 0;
+ }
+ }
+ else if ( Sign )
+ {
+ // 3PK is positive only, so clamp to zero
+ Result[2] = 0;
+ }
+ else if (I > 0x477C0000U)
+ {
+ // The number is too large to be represented as a float10, set to max
+ Result[2] = 0x3df;
+ }
+ else
+ {
+ if (I < 0x38800000U)
+ {
+ // The number is too small to be represented as a normalized float10
+ // Convert it to a denormalized value.
+ UINT Shift = 113U - (I >> 23U);
+ I = (0x800000U | (I & 0x7FFFFFU)) >> Shift;
+ }
+ else
+ {
+ // Rebias the exponent to represent the value as a normalized float10
+ I += 0xC8000000U;
+ }
+
+ Result[2] = ((I + 0x1FFFFU + ((I >> 18U) & 1U)) >> 18U)&0x3ffU;
+ }
+
+ // Pack Result into memory
+ pDestination->v = (Result[0] & 0x7ff)
+ | ( (Result[1] & 0x7ff) << 11 )
+ | ( (Result[2] & 0x3ff) << 22 );
+}
+
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat3SE
+(
+ XMFLOAT3SE* pDestination,
+ FXMVECTOR V
+)
+{
+ _DECLSPEC_ALIGN_16_ UINT IValue[4];
+ UINT I, Sign, j, T;
+ UINT Frac[3];
+ UINT Exp[3];
+
+
+ XMASSERT(pDestination);
+
+ XMStoreFloat3A( (XMFLOAT3A*)&IValue, V );
+
+ // X, Y, Z Channels (5-bit exponent, 9-bit mantissa)
+ for(j=0; j < 3; ++j)
+ {
+ Sign = IValue[j] & 0x80000000;
+ I = IValue[j] & 0x7FFFFFFF;
+
+ if ((I & 0x7F800000) == 0x7F800000)
+ {
+ // INF or NAN
+ Exp[j] = 0x1f;
+ if (( I & 0x7FFFFF ) != 0)
+ {
+ Frac[j] = ((I>>14)|(I>5)|(I))&0x1ff;
+ }
+ else if ( Sign )
+ {
+ // -INF is clamped to 0 since 3SE is positive only
+ Exp[j] = Frac[j] = 0;
+ }
+ }
+ else if ( Sign )
+ {
+ // 3SE is positive only, so clamp to zero
+ Exp[j] = Frac[j] = 0;
+ }
+ else if (I > 0x477FC000U)
+ {
+ // The number is too large, set to max
+ Exp[j] = 0x1e;
+ Frac[j] = 0x1ff;
+ }
+ else
+ {
+ if (I < 0x38800000U)
+ {
+ // The number is too small to be represented as a normalized float11
+ // Convert it to a denormalized value.
+ UINT Shift = 113U - (I >> 23U);
+ I = (0x800000U | (I & 0x7FFFFFU)) >> Shift;
+ }
+ else
+ {
+ // Rebias the exponent to represent the value as a normalized float11
+ I += 0xC8000000U;
+ }
+
+ T = ((I + 0x1FFFU + ((I >> 14U) & 1U)) >> 14U)&0x3fffU;
+
+ Exp[j] = (T & 0x3E00) >> 9;
+ Frac[j] = T & 0x1ff;
+ }
+ }
+
+ // Adjust to a shared exponent
+ T = XMMax( Exp[0], XMMax( Exp[1], Exp[2] ) );
+
+ Frac[0] = Frac[0] >> (T - Exp[0]);
+ Frac[1] = Frac[1] >> (T - Exp[1]);
+ Frac[2] = Frac[2] >> (T - Exp[2]);
+
+ // Store packed into memory
+ pDestination->xm = Frac[0];
+ pDestination->ym = Frac[1];
+ pDestination->zm = Frac[2];
+ pDestination->e = T;
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreInt4
+(
+ UINT* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+
+ pDestination[0] = V.vector4_u32[0];
+ pDestination[1] = V.vector4_u32[1];
+ pDestination[2] = V.vector4_u32[2];
+ pDestination[3] = V.vector4_u32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+
+ _mm_storeu_si128( (__m128i*)pDestination, reinterpret_cast<const __m128i *>(&V)[0] );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreInt4A
+(
+ UINT* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ pDestination[0] = V.vector4_u32[0];
+ pDestination[1] = V.vector4_u32[1];
+ pDestination[2] = V.vector4_u32[2];
+ pDestination[3] = V.vector4_u32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ _mm_store_si128( (__m128i*)pDestination, reinterpret_cast<const __m128i *>(&V)[0] );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreSInt4
+(
+ XMINT4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+
+ pDestination->x = (INT)V.vector4_f32[0];
+ pDestination->y = (INT)V.vector4_f32[1];
+ pDestination->z = (INT)V.vector4_f32[2];
+ pDestination->w = (INT)V.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+
+ // In case of positive overflow, detect it
+ XMVECTOR vOverflow = _mm_cmpgt_ps(V,g_XMMaxInt);
+ // Float to int conversion
+ __m128i vResulti = _mm_cvttps_epi32(V);
+ // If there was positive overflow, set to 0x7FFFFFFF
+ XMVECTOR vResult = _mm_and_ps(vOverflow,g_XMAbsMask);
+ vOverflow = _mm_andnot_ps(vOverflow,reinterpret_cast<const __m128 *>(&vResulti)[0]);
+ vOverflow = _mm_or_ps(vOverflow,vResult);
+ _mm_storeu_si128( (__m128i*)pDestination, reinterpret_cast<const __m128i *>(&vOverflow)[0] );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUInt4
+(
+ XMUINT4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+
+ pDestination->x = (UINT)V.vector4_f32[0];
+ pDestination->y = (UINT)V.vector4_f32[1];
+ pDestination->z = (UINT)V.vector4_f32[2];
+ pDestination->w = (UINT)V.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+
+ // Clamp to >=0
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ // Any numbers that are too big, set to 0xFFFFFFFFU
+ XMVECTOR vOverflow = _mm_cmpgt_ps(vResult,g_XMMaxUInt);
+ XMVECTOR vValue = g_XMUnsignedFix;
+ // Too large for a signed integer?
+ XMVECTOR vMask = _mm_cmpge_ps(vResult,vValue);
+ // Zero for number's lower than 0x80000000, 32768.0f*65536.0f otherwise
+ vValue = _mm_and_ps(vValue,vMask);
+ // Perform fixup only on numbers too large (Keeps low bit precision)
+ vResult = _mm_sub_ps(vResult,vValue);
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Convert from signed to unsigned pnly if greater than 0x80000000
+ vMask = _mm_and_ps(vMask,g_XMNegativeZero);
+ vResult = _mm_xor_ps(reinterpret_cast<const __m128 *>(&vResulti)[0],vMask);
+ // On those that are too large, set to 0xFFFFFFFF
+ vResult = _mm_or_ps(vResult,vOverflow);
+ _mm_storeu_si128( (__m128i*)pDestination, reinterpret_cast<const __m128i *>(&vResult)[0] );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreInt4NC
+(
+ UINT* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination[0] = V.vector4_u32[0];
+ pDestination[1] = V.vector4_u32[1];
+ pDestination[2] = V.vector4_u32[2];
+ pDestination[3] = V.vector4_u32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ _mm_storeu_si128( (__m128i*)pDestination, reinterpret_cast<const __m128i *>(&V)[0] );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat4
+(
+ XMFLOAT4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+
+ pDestination->x = V.vector4_f32[0];
+ pDestination->y = V.vector4_f32[1];
+ pDestination->z = V.vector4_f32[2];
+ pDestination->w = V.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+
+ _mm_storeu_ps( &pDestination->x, V );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat4A
+(
+ XMFLOAT4A* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ pDestination->x = V.vector4_f32[0];
+ pDestination->y = V.vector4_f32[1];
+ pDestination->z = V.vector4_f32[2];
+ pDestination->w = V.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ _mm_store_ps( &pDestination->x, V );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat4NC
+(
+ XMFLOAT4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ pDestination->x = V.vector4_f32[0];
+ pDestination->y = V.vector4_f32[1];
+ pDestination->z = V.vector4_f32[2];
+ pDestination->w = V.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 3) == 0);
+
+ _mm_storeu_ps( &pDestination->x, V );
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreHalf4
+(
+ XMHALF4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+
+ pDestination->x = XMConvertFloatToHalf(V.vector4_f32[0]);
+ pDestination->y = XMConvertFloatToHalf(V.vector4_f32[1]);
+ pDestination->z = XMConvertFloatToHalf(V.vector4_f32[2]);
+ pDestination->w = XMConvertFloatToHalf(V.vector4_f32[3]);
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ pDestination->x = XMConvertFloatToHalf(XMVectorGetX(V));
+ pDestination->y = XMConvertFloatToHalf(XMVectorGetY(V));
+ pDestination->z = XMConvertFloatToHalf(XMVectorGetZ(V));
+ pDestination->w = XMConvertFloatToHalf(XMVectorGetW(V));
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreShortN4
+(
+ XMSHORTN4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {32767.0f, 32767.0f, 32767.0f, 32767.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, g_XMNegativeOne.v, g_XMOne.v);
+ N = XMVectorMultiply(N, Scale.v);
+ N = XMVectorRound(N);
+
+ pDestination->x = (SHORT)N.vector4_f32[0];
+ pDestination->y = (SHORT)N.vector4_f32[1];
+ pDestination->z = (SHORT)N.vector4_f32[2];
+ pDestination->w = (SHORT)N.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Scale = {32767.0f, 32767.0f, 32767.0f, 32767.0f};
+
+ XMVECTOR vResult = _mm_max_ps(V,g_XMNegativeOne);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ vResult = _mm_mul_ps(vResult,Scale);
+ __m128i vResulti = _mm_cvtps_epi32(vResult);
+ vResulti = _mm_packs_epi32(vResulti,vResulti);
+ _mm_store_sd(reinterpret_cast<double *>(&pDestination->x),reinterpret_cast<const __m128d *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreShort4
+(
+ XMSHORT4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Min = {-32767.0f, -32767.0f, -32767.0f, -32767.0f};
+ static CONST XMVECTOR Max = {32767.0f, 32767.0f, 32767.0f, 32767.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min, Max);
+ N = XMVectorRound(N);
+
+ pDestination->x = (SHORT)N.vector4_f32[0];
+ pDestination->y = (SHORT)N.vector4_f32[1];
+ pDestination->z = (SHORT)N.vector4_f32[2];
+ pDestination->w = (SHORT)N.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Min = {-32767.0f, -32767.0f, -32767.0f, -32767.0f};
+ static CONST XMVECTORF32 Max = {32767.0f, 32767.0f, 32767.0f, 32767.0f};
+ // Bounds check
+ XMVECTOR vResult = _mm_max_ps(V,Min);
+ vResult = _mm_min_ps(vResult,Max);
+ // Convert to int with rounding
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // Pack the ints into shorts
+ vInt = _mm_packs_epi32(vInt,vInt);
+ _mm_store_sd(reinterpret_cast<double *>(&pDestination->x),reinterpret_cast<const __m128d *>(&vInt)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUShortN4
+(
+ XMUSHORTN4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {65535.0f, 65535.0f, 65535.0f, 65535.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorSaturate(V);
+ N = XMVectorMultiplyAdd(N, Scale.v, g_XMOneHalf.v);
+ N = XMVectorTruncate(N);
+
+ pDestination->x = (SHORT)N.vector4_f32[0];
+ pDestination->y = (SHORT)N.vector4_f32[1];
+ pDestination->z = (SHORT)N.vector4_f32[2];
+ pDestination->w = (SHORT)N.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Scale = {65535.0f, 65535.0f, 65535.0f, 65535.0f};
+ // Bounds check
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ vResult = _mm_mul_ps(vResult,Scale);
+ // Convert to int with rounding
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // Since the SSE pack instruction clamps using signed rules,
+ // manually extract the values to store them to memory
+ pDestination->x = static_cast<SHORT>(_mm_extract_epi16(vInt,0));
+ pDestination->y = static_cast<SHORT>(_mm_extract_epi16(vInt,2));
+ pDestination->z = static_cast<SHORT>(_mm_extract_epi16(vInt,4));
+ pDestination->w = static_cast<SHORT>(_mm_extract_epi16(vInt,6));
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUShort4
+(
+ XMUSHORT4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Max = {65535.0f, 65535.0f, 65535.0f, 65535.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max);
+ N = XMVectorRound(N);
+
+ pDestination->x = (SHORT)N.vector4_f32[0];
+ pDestination->y = (SHORT)N.vector4_f32[1];
+ pDestination->z = (SHORT)N.vector4_f32[2];
+ pDestination->w = (SHORT)N.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Max = {65535.0f, 65535.0f, 65535.0f, 65535.0f};
+ // Bounds check
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,Max);
+ // Convert to int with rounding
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // Since the SSE pack instruction clamps using signed rules,
+ // manually extract the values to store them to memory
+ pDestination->x = static_cast<SHORT>(_mm_extract_epi16(vInt,0));
+ pDestination->y = static_cast<SHORT>(_mm_extract_epi16(vInt,2));
+ pDestination->z = static_cast<SHORT>(_mm_extract_epi16(vInt,4));
+ pDestination->w = static_cast<SHORT>(_mm_extract_epi16(vInt,6));
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreXIcoN4
+(
+ XMXICON4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Min = {-1.0f, -1.0f, -1.0f, 0.0f};
+ static CONST XMVECTORF32 Scale = {524287.0f, 524287.0f, 524287.0f, 15.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min.v, g_XMOne.v);
+ N = XMVectorMultiply(N, Scale.v);
+ N = XMVectorRound(N);
+
+ pDestination->v = ((UINT64)N.vector4_f32[3] << 60) |
+ (((INT64)N.vector4_f32[2] & 0xFFFFF) << 40) |
+ (((INT64)N.vector4_f32[1] & 0xFFFFF) << 20) |
+ (((INT64)N.vector4_f32[0] & 0xFFFFF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ // Note: Masks are x,w,y and z
+ static const XMVECTORF32 MinXIcoN4 = {-1.0f, 0.0f,-1.0f,-1.0f};
+ static const XMVECTORF32 ScaleXIcoN4 = {524287.0f,15.0f*4096.0f*65536.0f*0.5f,524287.0f*4096.0f,524287.0f};
+ static const XMVECTORI32 MaskXIcoN4 = {0xFFFFF,0xF<<((60-32)-1),0xFFFFF000,0xFFFFF};
+
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,1,3,0));
+ vResult = _mm_max_ps(vResult,MinXIcoN4);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleXIcoN4);
+ // Convert to integer (w is unsigned)
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off unused bits
+ vResulti = _mm_and_si128(vResulti,MaskXIcoN4);
+ // Isolate Y
+ __m128i vResulti2 = _mm_and_si128(vResulti,g_XMMaskY);
+ // Double Y (Really W) to fixup for unsigned conversion
+ vResulti = _mm_add_epi32(vResulti,vResulti2);
+ // Shift y and z to straddle the 32-bit boundary
+ vResulti2 = _mm_srli_si128(vResulti,(64+12)/8);
+ // Shift it into place
+ vResulti2 = _mm_slli_si128(vResulti2,20/8);
+ // i = x|y<<20|z<<40|w<<60
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_sd(reinterpret_cast<double *>(&pDestination->v),reinterpret_cast<const __m128d *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreXIco4
+(
+ XMXICO4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Min = {-524287.0f, -524287.0f, -524287.0f, 0.0f};
+ static CONST XMVECTORF32 Max = {524287.0f, 524287.0f, 524287.0f, 15.0f};
+
+ XMASSERT(pDestination);
+ N = XMVectorClamp(V, Min.v, Max.v);
+ pDestination->v = ((UINT64)N.vector4_f32[3] << 60) |
+ (((INT64)N.vector4_f32[2] & 0xFFFFF) << 40) |
+ (((INT64)N.vector4_f32[1] & 0xFFFFF) << 20) |
+ (((INT64)N.vector4_f32[0] & 0xFFFFF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ // Note: Masks are x,w,y and z
+ static const XMVECTORF32 MinXIco4 = {-524287.0f, 0.0f,-524287.0f,-524287.0f};
+ static const XMVECTORF32 MaxXIco4 = { 524287.0f,15.0f, 524287.0f, 524287.0f};
+ static const XMVECTORF32 ScaleXIco4 = {1.0f,4096.0f*65536.0f*0.5f,4096.0f,1.0f};
+ static const XMVECTORI32 MaskXIco4 = {0xFFFFF,0xF<<((60-1)-32),0xFFFFF000,0xFFFFF};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,1,3,0));
+ vResult = _mm_max_ps(vResult,MinXIco4);
+ vResult = _mm_min_ps(vResult,MaxXIco4);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleXIco4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskXIco4);
+ // Isolate Y
+ __m128i vResulti2 = _mm_and_si128(vResulti,g_XMMaskY);
+ // Double Y (Really W) to fixup for unsigned conversion
+ vResulti = _mm_add_epi32(vResulti,vResulti2);
+ // Shift y and z to straddle the 32-bit boundary
+ vResulti2 = _mm_srli_si128(vResulti,(64+12)/8);
+ // Shift it into place
+ vResulti2 = _mm_slli_si128(vResulti2,20/8);
+ // i = x|y<<20|z<<40|w<<60
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_sd(reinterpret_cast<double *>(&pDestination->v),reinterpret_cast<const __m128d *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUIcoN4
+(
+ XMUICON4* pDestination,
+ FXMVECTOR V
+)
+{
+ #define XM_URange ((FLOAT)(1 << 20))
+ #define XM_URangeDiv2 ((FLOAT)(1 << 19))
+ #define XM_UMaxXYZ ((FLOAT)((1 << 20) - 1))
+ #define XM_UMaxW ((FLOAT)((1 << 4) - 1))
+ #define XM_ScaleXYZ (-(FLOAT)((1 << 20) - 1) / XM_PACK_FACTOR)
+ #define XM_ScaleW (-(FLOAT)((1 << 4) - 1) / XM_PACK_FACTOR)
+ #define XM_Scale (-1.0f / XM_PACK_FACTOR)
+ #define XM_Offset (3.0f)
+
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {1048575.0f, 1048575.0f, 1048575.0f, 15.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorSaturate(V);
+ N = XMVectorMultiplyAdd(N, Scale.v, g_XMOneHalf.v);
+
+ pDestination->v = ((UINT64)N.vector4_f32[3] << 60) |
+ (((UINT64)N.vector4_f32[2] & 0xFFFFF) << 40) |
+ (((UINT64)N.vector4_f32[1] & 0xFFFFF) << 20) |
+ (((UINT64)N.vector4_f32[0] & 0xFFFFF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ // Note: Masks are x,w,y and z
+ static const XMVECTORF32 ScaleUIcoN4 = {1048575.0f,15.0f*4096.0f*65536.0f,1048575.0f*4096.0f,1048575.0f};
+ static const XMVECTORI32 MaskUIcoN4 = {0xFFFFF,0xF<<(60-32),0xFFFFF000,0xFFFFF};
+ static const XMVECTORF32 AddUIcoN4 = {0.0f,-32768.0f*65536.0f,-32768.0f*65536.0f,0.0f};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,1,3,0));
+ vResult = _mm_max_ps(vResult,g_XMZero);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUIcoN4);
+ // Adjust for unsigned entries
+ vResult = _mm_add_ps(vResult,AddUIcoN4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Fix the signs on the unsigned entries
+ vResulti = _mm_xor_si128(vResulti,g_XMFlipYZ);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUIcoN4);
+ // Shift y and z to straddle the 32-bit boundary
+ __m128i vResulti2 = _mm_srli_si128(vResulti,(64+12)/8);
+ // Shift it into place
+ vResulti2 = _mm_slli_si128(vResulti2,20/8);
+ // i = x|y<<20|z<<40|w<<60
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_sd(reinterpret_cast<double *>(&pDestination->v),reinterpret_cast<const __m128d *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+
+ #undef XM_URange
+ #undef XM_URangeDiv2
+ #undef XM_UMaxXYZ
+ #undef XM_UMaxW
+ #undef XM_ScaleXYZ
+ #undef XM_ScaleW
+ #undef XM_Scale
+ #undef XM_Offset
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUIco4
+(
+ XMUICO4* pDestination,
+ FXMVECTOR V
+)
+{
+ #define XM_Scale (-1.0f / XM_PACK_FACTOR)
+ #define XM_URange ((FLOAT)(1 << 20))
+ #define XM_URangeDiv2 ((FLOAT)(1 << 19))
+
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Max = {1048575.0f, 1048575.0f, 1048575.0f, 15.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max);
+ N = XMVectorRound(N);
+
+ pDestination->v = ((UINT64)N.vector4_f32[3] << 60) |
+ (((UINT64)N.vector4_f32[2] & 0xFFFFF) << 40) |
+ (((UINT64)N.vector4_f32[1] & 0xFFFFF) << 20) |
+ (((UINT64)N.vector4_f32[0] & 0xFFFFF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ // Note: Masks are x,w,y and z
+ static const XMVECTORF32 MaxUIco4 = { 1048575.0f, 15.0f, 1048575.0f, 1048575.0f};
+ static const XMVECTORF32 ScaleUIco4 = {1.0f,4096.0f*65536.0f,4096.0f,1.0f};
+ static const XMVECTORI32 MaskUIco4 = {0xFFFFF,0xF<<(60-32),0xFFFFF000,0xFFFFF};
+ static const XMVECTORF32 AddUIco4 = {0.0f,-32768.0f*65536.0f,-32768.0f*65536.0f,0.0f};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,1,3,0));
+ vResult = _mm_max_ps(vResult,g_XMZero);
+ vResult = _mm_min_ps(vResult,MaxUIco4);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUIco4);
+ vResult = _mm_add_ps(vResult,AddUIco4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ vResulti = _mm_xor_si128(vResulti,g_XMFlipYZ);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUIco4);
+ // Shift y and z to straddle the 32-bit boundary
+ __m128i vResulti2 = _mm_srli_si128(vResulti,(64+12)/8);
+ // Shift it into place
+ vResulti2 = _mm_slli_si128(vResulti2,20/8);
+ // i = x|y<<20|z<<40|w<<60
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_sd(reinterpret_cast<double *>(&pDestination->v),reinterpret_cast<const __m128d *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+
+ #undef XM_Scale
+ #undef XM_URange
+ #undef XM_URangeDiv2
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreIcoN4
+(
+ XMICON4* pDestination,
+ FXMVECTOR V
+)
+{
+ #define XM_Scale (-1.0f / XM_PACK_FACTOR)
+ #define XM_URange ((FLOAT)(1 << 4))
+ #define XM_Offset (3.0f)
+ #define XM_UMaxXYZ ((FLOAT)((1 << (20 - 1)) - 1))
+ #define XM_UMaxW ((FLOAT)((1 << (4 - 1)) - 1))
+
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {524287.0f, 524287.0f, 524287.0f, 7.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, g_XMNegativeOne.v, g_XMOne.v);
+ N = XMVectorMultiplyAdd(N, Scale.v, g_XMNegativeZero.v);
+ N = XMVectorRound(N);
+
+ pDestination->v = ((UINT64)N.vector4_f32[3] << 60) |
+ (((UINT64)N.vector4_f32[2] & 0xFFFFF) << 40) |
+ (((UINT64)N.vector4_f32[1] & 0xFFFFF) << 20) |
+ (((UINT64)N.vector4_f32[0] & 0xFFFFF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ // Note: Masks are x,w,y and z
+ static const XMVECTORF32 ScaleIcoN4 = {524287.0f,7.0f*4096.0f*65536.0f,524287.0f*4096.0f,524287.0f};
+ static const XMVECTORI32 MaskIcoN4 = {0xFFFFF,0xF<<(60-32),0xFFFFF000,0xFFFFF};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,1,3,0));
+ vResult = _mm_max_ps(vResult,g_XMNegativeOne);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleIcoN4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskIcoN4);
+ // Shift y and z to straddle the 32-bit boundary
+ __m128i vResulti2 = _mm_srli_si128(vResulti,(64+12)/8);
+ // Shift it into place
+ vResulti2 = _mm_slli_si128(vResulti2,20/8);
+ // i = x|y<<20|z<<40|w<<60
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_sd(reinterpret_cast<double *>(&pDestination->v),reinterpret_cast<const __m128d *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+
+ #undef XM_Scale
+ #undef XM_URange
+ #undef XM_Offset
+ #undef XM_UMaxXYZ
+ #undef XM_UMaxW
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreIco4
+(
+ XMICO4* pDestination,
+ FXMVECTOR V
+)
+{
+ #define XM_Scale (-1.0f / XM_PACK_FACTOR)
+ #define XM_URange ((FLOAT)(1 << 4))
+ #define XM_Offset (3.0f)
+
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Min = {-524287.0f, -524287.0f, -524287.0f, -7.0f};
+ static CONST XMVECTOR Max = {524287.0f, 524287.0f, 524287.0f, 7.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min, Max);
+ N = XMVectorRound(N);
+
+ pDestination->v = ((INT64)N.vector4_f32[3] << 60) |
+ (((INT64)N.vector4_f32[2] & 0xFFFFF) << 40) |
+ (((INT64)N.vector4_f32[1] & 0xFFFFF) << 20) |
+ (((INT64)N.vector4_f32[0] & 0xFFFFF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ // Note: Masks are x,w,y and z
+ static const XMVECTORF32 MinIco4 = {-524287.0f,-7.0f,-524287.0f,-524287.0f};
+ static const XMVECTORF32 MaxIco4 = { 524287.0f, 7.0f, 524287.0f, 524287.0f};
+ static const XMVECTORF32 ScaleIco4 = {1.0f,4096.0f*65536.0f,4096.0f,1.0f};
+ static const XMVECTORI32 MaskIco4 = {0xFFFFF,0xF<<(60-32),0xFFFFF000,0xFFFFF};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_shuffle_ps(V,V,_MM_SHUFFLE(2,1,3,0));
+ vResult = _mm_max_ps(vResult,MinIco4);
+ vResult = _mm_min_ps(vResult,MaxIco4);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleIco4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskIco4);
+ // Shift y and z to straddle the 32-bit boundary
+ __m128i vResulti2 = _mm_srli_si128(vResulti,(64+12)/8);
+ // Shift it into place
+ vResulti2 = _mm_slli_si128(vResulti2,20/8);
+ // i = x|y<<20|z<<40|w<<60
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_sd(reinterpret_cast<double *>(&pDestination->v),reinterpret_cast<const __m128d *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+
+ #undef XM_Scale
+ #undef XM_URange
+ #undef XM_Offset
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreXDecN4
+(
+ XMXDECN4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Min = {-1.0f, -1.0f, -1.0f, 0.0f};
+ static CONST XMVECTORF32 Scale = {511.0f, 511.0f, 511.0f, 3.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min.v, g_XMOne.v);
+ N = XMVectorMultiply(N, Scale.v);
+ N = XMVectorRound(N);
+
+ pDestination->v = ((UINT)N.vector4_f32[3] << 30) |
+ (((INT)N.vector4_f32[2] & 0x3FF) << 20) |
+ (((INT)N.vector4_f32[1] & 0x3FF) << 10) |
+ (((INT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ static const XMVECTORF32 Min = {-1.0f, -1.0f, -1.0f, 0.0f};
+ static const XMVECTORF32 Scale = {511.0f, 511.0f*1024.0f, 511.0f*1048576.0f,3.0f*536870912.0f};
+ static const XMVECTORI32 ScaleMask = {0x3FF,0x3FF<<10,0x3FF<<20,0x3<<29};
+ XMASSERT(pDestination);
+ XMVECTOR vResult = _mm_max_ps(V,Min);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,Scale);
+ // Convert to int (W is unsigned)
+ __m128i vResulti = _mm_cvtps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,ScaleMask);
+ // To fix W, add itself to shift it up to <<30 instead of <<29
+ __m128i vResultw = _mm_and_si128(vResulti,g_XMMaskW);
+ vResulti = _mm_add_epi32(vResulti,vResultw);
+ // Do a horizontal or of all 4 entries
+ vResult = _mm_shuffle_ps(reinterpret_cast<const __m128 *>(&vResulti)[0],reinterpret_cast<const __m128 *>(&vResulti)[0],_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ vResult = _mm_shuffle_ps(vResult,vResult,_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ vResult = _mm_shuffle_ps(vResult,vResult,_MM_SHUFFLE(0,3,2,1));
+ vResulti = _mm_or_si128(vResulti,reinterpret_cast<const __m128i *>(&vResult)[0]);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreXDec4
+(
+ XMXDEC4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Min = {-511.0f, -511.0f, -511.0f, 0.0f};
+ static CONST XMVECTOR Max = {511.0f, 511.0f, 511.0f, 3.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min, Max);
+
+ pDestination->v = ((UINT)N.vector4_f32[3] << 30) |
+ (((INT)N.vector4_f32[2] & 0x3FF) << 20) |
+ (((INT)N.vector4_f32[1] & 0x3FF) << 10) |
+ (((INT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 MinXDec4 = {-511.0f,-511.0f,-511.0f, 0.0f};
+ static const XMVECTORF32 MaxXDec4 = { 511.0f, 511.0f, 511.0f, 3.0f};
+ static const XMVECTORF32 ScaleXDec4 = {1.0f,1024.0f/2.0f,1024.0f*1024.0f,1024.0f*1024.0f*1024.0f/2.0f};
+ static const XMVECTORI32 MaskXDec4= {0x3FF,0x3FF<<(10-1),0x3FF<<20,0x3<<(30-1)};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,MinXDec4);
+ vResult = _mm_min_ps(vResult,MaxXDec4);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleXDec4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskXDec4);
+ // Do a horizontal or of 4 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(3,2,3,2));
+ // x = x|z, y = y|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(1,1,1,1));
+ // Perform a single bit left shift on y|w
+ vResulti2 = _mm_add_epi32(vResulti2,vResulti2);
+ // i = x|y|z|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUDecN4
+(
+ XMUDECN4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {1023.0f, 1023.0f, 1023.0f, 3.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorSaturate(V);
+ N = XMVectorMultiply(N, Scale.v);
+
+ pDestination->v = ((UINT)N.vector4_f32[3] << 30) |
+ (((UINT)N.vector4_f32[2] & 0x3FF) << 20) |
+ (((UINT)N.vector4_f32[1] & 0x3FF) << 10) |
+ (((UINT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 ScaleUDecN4 = {1023.0f,1023.0f*1024.0f*0.5f,1023.0f*1024.0f*1024.0f,3.0f*1024.0f*1024.0f*1024.0f*0.5f};
+ static const XMVECTORI32 MaskUDecN4= {0x3FF,0x3FF<<(10-1),0x3FF<<20,0x3<<(30-1)};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUDecN4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUDecN4);
+ // Do a horizontal or of 4 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(3,2,3,2));
+ // x = x|z, y = y|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(1,1,1,1));
+ // Perform a left shift by one bit on y|w
+ vResulti2 = _mm_add_epi32(vResulti2,vResulti2);
+ // i = x|y|z|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUDec4
+(
+ XMUDEC4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Max = {1023.0f, 1023.0f, 1023.0f, 3.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max);
+
+ pDestination->v = ((UINT)N.vector4_f32[3] << 30) |
+ (((UINT)N.vector4_f32[2] & 0x3FF) << 20) |
+ (((UINT)N.vector4_f32[1] & 0x3FF) << 10) |
+ (((UINT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 MaxUDec4 = { 1023.0f, 1023.0f, 1023.0f, 3.0f};
+ static const XMVECTORF32 ScaleUDec4 = {1.0f,1024.0f/2.0f,1024.0f*1024.0f,1024.0f*1024.0f*1024.0f/2.0f};
+ static const XMVECTORI32 MaskUDec4= {0x3FF,0x3FF<<(10-1),0x3FF<<20,0x3<<(30-1)};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,MaxUDec4);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUDec4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUDec4);
+ // Do a horizontal or of 4 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(3,2,3,2));
+ // x = x|z, y = y|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(1,1,1,1));
+ // Perform a left shift by one bit on y|w
+ vResulti2 = _mm_add_epi32(vResulti2,vResulti2);
+ // i = x|y|z|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreDecN4
+(
+ XMDECN4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {511.0f, 511.0f, 511.0f, 1.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, g_XMNegativeOne.v, g_XMOne.v);
+ N = XMVectorMultiply(N, Scale.v);
+
+ pDestination->v = ((INT)N.vector4_f32[3] << 30) |
+ (((INT)N.vector4_f32[2] & 0x3FF) << 20) |
+ (((INT)N.vector4_f32[1] & 0x3FF) << 10) |
+ (((INT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 ScaleDecN4 = {511.0f,511.0f*1024.0f,511.0f*1024.0f*1024.0f,1.0f*1024.0f*1024.0f*1024.0f};
+ static const XMVECTORI32 MaskDecN4= {0x3FF,0x3FF<<10,0x3FF<<20,0x3<<30};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMNegativeOne);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleDecN4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskDecN4);
+ // Do a horizontal or of 4 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(3,2,3,2));
+ // x = x|z, y = y|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(1,1,1,1));
+ // i = x|y|z|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreDec4
+(
+ XMDEC4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Min = {-511.0f, -511.0f, -511.0f, -1.0f};
+ static CONST XMVECTOR Max = {511.0f, 511.0f, 511.0f, 1.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min, Max);
+
+ pDestination->v = ((INT)N.vector4_f32[3] << 30) |
+ (((INT)N.vector4_f32[2] & 0x3FF) << 20) |
+ (((INT)N.vector4_f32[1] & 0x3FF) << 10) |
+ (((INT)N.vector4_f32[0] & 0x3FF));
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 MinDec4 = {-511.0f,-511.0f,-511.0f,-1.0f};
+ static const XMVECTORF32 MaxDec4 = { 511.0f, 511.0f, 511.0f, 1.0f};
+ static const XMVECTORF32 ScaleDec4 = {1.0f,1024.0f,1024.0f*1024.0f,1024.0f*1024.0f*1024.0f};
+ static const XMVECTORI32 MaskDec4= {0x3FF,0x3FF<<10,0x3FF<<20,0x3<<30};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,MinDec4);
+ vResult = _mm_min_ps(vResult,MaxDec4);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleDec4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskDec4);
+ // Do a horizontal or of 4 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(3,2,3,2));
+ // x = x|z, y = y|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(1,1,1,1));
+ // i = x|y|z|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUByteN4
+(
+ XMUBYTEN4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {255.0f, 255.0f, 255.0f, 255.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorSaturate(V);
+ N = XMVectorMultiply(N, Scale.v);
+ N = XMVectorRound(N);
+
+ pDestination->x = (BYTE)N.vector4_f32[0];
+ pDestination->y = (BYTE)N.vector4_f32[1];
+ pDestination->z = (BYTE)N.vector4_f32[2];
+ pDestination->w = (BYTE)N.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 ScaleUByteN4 = {255.0f,255.0f*256.0f*0.5f,255.0f*256.0f*256.0f,255.0f*256.0f*256.0f*256.0f*0.5f};
+ static const XMVECTORI32 MaskUByteN4 = {0xFF,0xFF<<(8-1),0xFF<<16,0xFF<<(24-1)};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUByteN4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUByteN4);
+ // Do a horizontal or of 4 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(3,2,3,2));
+ // x = x|z, y = y|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(1,1,1,1));
+ // Perform a single bit left shift to fix y|w
+ vResulti2 = _mm_add_epi32(vResulti2,vResulti2);
+ // i = x|y|z|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUByte4
+(
+ XMUBYTE4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Max = {255.0f, 255.0f, 255.0f, 255.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max);
+ N = XMVectorRound(N);
+
+ pDestination->x = (BYTE)N.vector4_f32[0];
+ pDestination->y = (BYTE)N.vector4_f32[1];
+ pDestination->z = (BYTE)N.vector4_f32[2];
+ pDestination->w = (BYTE)N.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 MaxUByte4 = { 255.0f, 255.0f, 255.0f, 255.0f};
+ static const XMVECTORF32 ScaleUByte4 = {1.0f,256.0f*0.5f,256.0f*256.0f,256.0f*256.0f*256.0f*0.5f};
+ static const XMVECTORI32 MaskUByte4 = {0xFF,0xFF<<(8-1),0xFF<<16,0xFF<<(24-1)};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,MaxUByte4);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleUByte4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskUByte4);
+ // Do a horizontal or of 4 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(3,2,3,2));
+ // x = x|z, y = y|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(1,1,1,1));
+ // Perform a single bit left shift to fix y|w
+ vResulti2 = _mm_add_epi32(vResulti2,vResulti2);
+ // i = x|y|z|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreByteN4
+(
+ XMBYTEN4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {127.0f, 127.0f, 127.0f, 127.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, g_XMNegativeOne.v, g_XMOne.v);
+ N = XMVectorMultiply(V, Scale.v);
+ N = XMVectorRound(N);
+
+ pDestination->x = (CHAR)N.vector4_f32[0];
+ pDestination->y = (CHAR)N.vector4_f32[1];
+ pDestination->z = (CHAR)N.vector4_f32[2];
+ pDestination->w = (CHAR)N.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 ScaleByteN4 = {127.0f,127.0f*256.0f,127.0f*256.0f*256.0f,127.0f*256.0f*256.0f*256.0f};
+ static const XMVECTORI32 MaskByteN4 = {0xFF,0xFF<<8,0xFF<<16,0xFF<<24};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,g_XMNegativeOne);
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleByteN4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskByteN4);
+ // Do a horizontal or of 4 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(3,2,3,2));
+ // x = x|z, y = y|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(1,1,1,1));
+ // i = x|y|z|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreByte4
+(
+ XMBYTE4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTOR Min = {-127.0f, -127.0f, -127.0f, -127.0f};
+ static CONST XMVECTOR Max = {127.0f, 127.0f, 127.0f, 127.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, Min, Max);
+ N = XMVectorRound(N);
+
+ pDestination->x = (CHAR)N.vector4_f32[0];
+ pDestination->y = (CHAR)N.vector4_f32[1];
+ pDestination->z = (CHAR)N.vector4_f32[2];
+ pDestination->w = (CHAR)N.vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static const XMVECTORF32 MinByte4 = {-127.0f,-127.0f,-127.0f,-127.0f};
+ static const XMVECTORF32 MaxByte4 = { 127.0f, 127.0f, 127.0f, 127.0f};
+ static const XMVECTORF32 ScaleByte4 = {1.0f,256.0f,256.0f*256.0f,256.0f*256.0f*256.0f};
+ static const XMVECTORI32 MaskByte4 = {0xFF,0xFF<<8,0xFF<<16,0xFF<<24};
+ // Clamp to bounds
+ XMVECTOR vResult = _mm_max_ps(V,MinByte4);
+ vResult = _mm_min_ps(vResult,MaxByte4);
+ // Scale by multiplication
+ vResult = _mm_mul_ps(vResult,ScaleByte4);
+ // Convert to int
+ __m128i vResulti = _mm_cvttps_epi32(vResult);
+ // Mask off any fraction
+ vResulti = _mm_and_si128(vResulti,MaskByte4);
+ // Do a horizontal or of 4 entries
+ __m128i vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(3,2,3,2));
+ // x = x|z, y = y|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ // Move Z to the x position
+ vResulti2 = _mm_shuffle_epi32(vResulti,_MM_SHUFFLE(1,1,1,1));
+ // i = x|y|z|w
+ vResulti = _mm_or_si128(vResulti,vResulti2);
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->v),reinterpret_cast<const __m128 *>(&vResulti)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreUNibble4
+(
+ XMUNIBBLE4* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Max = {15.0f,15.0f,15.0f,15.0f};
+ // Bounds check
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,Max);
+ // Convert to int with rounding
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // No SSE operations will write to 16-bit values, so we have to extract them manually
+ USHORT x = static_cast<USHORT>(_mm_extract_epi16(vInt,0));
+ USHORT y = static_cast<USHORT>(_mm_extract_epi16(vInt,2));
+ USHORT z = static_cast<USHORT>(_mm_extract_epi16(vInt,4));
+ USHORT w = static_cast<USHORT>(_mm_extract_epi16(vInt,6));
+ pDestination->v = ((w & 0xF) << 12) |
+ ((z & 0xF) << 8) |
+ ((y & 0xF) << 4) |
+ ((x & 0xF));
+#else
+ XMVECTOR N;
+ static CONST XMVECTORF32 Max = {15.0f,15.0f,15.0f,15.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max.v);
+ N = XMVectorRound(N);
+
+ pDestination->v = (((USHORT)N.vector4_f32[3] & 0xF) << 12) |
+ (((USHORT)N.vector4_f32[2] & 0xF) << 8) |
+ (((USHORT)N.vector4_f32[1] & 0xF) << 4) |
+ (((USHORT)N.vector4_f32[0] & 0xF));
+#endif !_XM_SSE_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreU555(
+ XMU555* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Max = {31.0f, 31.0f, 31.0f, 1.0f};
+ // Bounds check
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ vResult = _mm_min_ps(vResult,Max);
+ // Convert to int with rounding
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // No SSE operations will write to 16-bit values, so we have to extract them manually
+ USHORT x = static_cast<USHORT>(_mm_extract_epi16(vInt,0));
+ USHORT y = static_cast<USHORT>(_mm_extract_epi16(vInt,2));
+ USHORT z = static_cast<USHORT>(_mm_extract_epi16(vInt,4));
+ USHORT w = static_cast<USHORT>(_mm_extract_epi16(vInt,6));
+ pDestination->v = ((w) ? 0x8000 : 0) |
+ ((z & 0x1F) << 10) |
+ ((y & 0x1F) << 5) |
+ ((x & 0x1F));
+#else
+ XMVECTOR N;
+ static CONST XMVECTORF32 Max = {31.0f, 31.0f, 31.0f, 1.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorClamp(V, XMVectorZero(), Max.v);
+ N = XMVectorRound(N);
+
+ pDestination->v = ((N.vector4_f32[3] > 0.f) ? 0x8000 : 0) |
+ (((USHORT)N.vector4_f32[2] & 0x1F) << 10) |
+ (((USHORT)N.vector4_f32[1] & 0x1F) << 5) |
+ (((USHORT)N.vector4_f32[0] & 0x1F));
+#endif !_XM_SSE_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreColor
+(
+ XMCOLOR* pDestination,
+ FXMVECTOR V
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMVECTOR N;
+ static CONST XMVECTORF32 Scale = {255.0f, 255.0f, 255.0f, 255.0f};
+
+ XMASSERT(pDestination);
+
+ N = XMVectorSaturate(V);
+ N = XMVectorMultiply(N, Scale.v);
+ N = XMVectorRound(N);
+
+ pDestination->c = ((UINT)N.vector4_f32[3] << 24) |
+ ((UINT)N.vector4_f32[0] << 16) |
+ ((UINT)N.vector4_f32[1] << 8) |
+ ((UINT)N.vector4_f32[2]);
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ static CONST XMVECTORF32 Scale = {255.0f,255.0f,255.0f,255.0f};
+ // Set <0 to 0
+ XMVECTOR vResult = _mm_max_ps(V,g_XMZero);
+ // Set>1 to 1
+ vResult = _mm_min_ps(vResult,g_XMOne);
+ // Convert to 0-255
+ vResult = _mm_mul_ps(vResult,Scale);
+ // Shuffle RGBA to ARGB
+ vResult = _mm_shuffle_ps(vResult,vResult,_MM_SHUFFLE(3,0,1,2));
+ // Convert to int
+ __m128i vInt = _mm_cvtps_epi32(vResult);
+ // Mash to shorts
+ vInt = _mm_packs_epi32(vInt,vInt);
+ // Mash to bytes
+ vInt = _mm_packus_epi16(vInt,vInt);
+ // Store the color
+ _mm_store_ss(reinterpret_cast<float *>(&pDestination->c),reinterpret_cast<__m128 *>(&vInt)[0]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat3x3
+(
+ XMFLOAT3X3* pDestination,
+ CXMMATRIX M
+)
+{
+#if defined(_XM_NO_INTRINSICS_) || defined(XM_NO_MISALIGNED_VECTOR_ACCESS) || defined(_XM_SSE_INTRINSICS_)
+
+ XMStoreFloat3x3NC(pDestination, M);
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat3x3NC
+(
+ XMFLOAT3X3* pDestination,
+ CXMMATRIX M
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+
+ pDestination->m[0][0] = M.r[0].vector4_f32[0];
+ pDestination->m[0][1] = M.r[0].vector4_f32[1];
+ pDestination->m[0][2] = M.r[0].vector4_f32[2];
+
+ pDestination->m[1][0] = M.r[1].vector4_f32[0];
+ pDestination->m[1][1] = M.r[1].vector4_f32[1];
+ pDestination->m[1][2] = M.r[1].vector4_f32[2];
+
+ pDestination->m[2][0] = M.r[2].vector4_f32[0];
+ pDestination->m[2][1] = M.r[2].vector4_f32[1];
+ pDestination->m[2][2] = M.r[2].vector4_f32[2];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMVECTOR vTemp1 = M.r[0];
+ XMVECTOR vTemp2 = M.r[1];
+ XMVECTOR vTemp3 = M.r[2];
+ XMVECTOR vWork = _mm_shuffle_ps(vTemp1,vTemp2,_MM_SHUFFLE(0,0,2,2));
+ vTemp1 = _mm_shuffle_ps(vTemp1,vWork,_MM_SHUFFLE(2,0,1,0));
+ _mm_storeu_ps(&pDestination->m[0][0],vTemp1);
+ vTemp2 = _mm_shuffle_ps(vTemp2,vTemp3,_MM_SHUFFLE(1,0,2,1));
+ _mm_storeu_ps(&pDestination->m[1][1],vTemp2);
+ vTemp3 = _mm_shuffle_ps(vTemp3,vTemp3,_MM_SHUFFLE(2,2,2,2));
+ _mm_store_ss(&pDestination->m[2][2],vTemp3);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat4x3
+(
+ XMFLOAT4X3* pDestination,
+ CXMMATRIX M
+)
+{
+#if defined(_XM_NO_INTRINSICS_) || defined(XM_NO_MISALIGNED_VECTOR_ACCESS) || defined(_XM_SSE_INTRINSICS_)
+
+ XMStoreFloat4x3NC(pDestination, M);
+
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat4x3A
+(
+ XMFLOAT4X3A* pDestination,
+ CXMMATRIX M
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ pDestination->m[0][0] = M.r[0].vector4_f32[0];
+ pDestination->m[0][1] = M.r[0].vector4_f32[1];
+ pDestination->m[0][2] = M.r[0].vector4_f32[2];
+
+ pDestination->m[1][0] = M.r[1].vector4_f32[0];
+ pDestination->m[1][1] = M.r[1].vector4_f32[1];
+ pDestination->m[1][2] = M.r[1].vector4_f32[2];
+
+ pDestination->m[2][0] = M.r[2].vector4_f32[0];
+ pDestination->m[2][1] = M.r[2].vector4_f32[1];
+ pDestination->m[2][2] = M.r[2].vector4_f32[2];
+
+ pDestination->m[3][0] = M.r[3].vector4_f32[0];
+ pDestination->m[3][1] = M.r[3].vector4_f32[1];
+ pDestination->m[3][2] = M.r[3].vector4_f32[2];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+ // x1,y1,z1,w1
+ XMVECTOR vTemp1 = M.r[0];
+ // x2,y2,z2,w2
+ XMVECTOR vTemp2 = M.r[1];
+ // x3,y3,z3,w3
+ XMVECTOR vTemp3 = M.r[2];
+ // x4,y4,z4,w4
+ XMVECTOR vTemp4 = M.r[3];
+ // z1,z1,x2,y2
+ XMVECTOR vTemp = _mm_shuffle_ps(vTemp1,vTemp2,_MM_SHUFFLE(1,0,2,2));
+ // y2,z2,x3,y3 (Final)
+ vTemp2 = _mm_shuffle_ps(vTemp2,vTemp3,_MM_SHUFFLE(1,0,2,1));
+ // x1,y1,z1,x2 (Final)
+ vTemp1 = _mm_shuffle_ps(vTemp1,vTemp,_MM_SHUFFLE(2,0,1,0));
+ // z3,z3,x4,x4
+ vTemp3 = _mm_shuffle_ps(vTemp3,vTemp4,_MM_SHUFFLE(0,0,2,2));
+ // z3,x4,y4,z4 (Final)
+ vTemp3 = _mm_shuffle_ps(vTemp3,vTemp4,_MM_SHUFFLE(2,1,2,0));
+ // Store in 3 operations
+ _mm_store_ps(&pDestination->m[0][0],vTemp1);
+ _mm_store_ps(&pDestination->m[1][1],vTemp2);
+ _mm_store_ps(&pDestination->m[2][2],vTemp3);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat4x3NC
+(
+ XMFLOAT4X3* pDestination,
+ CXMMATRIX M
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+
+ pDestination->m[0][0] = M.r[0].vector4_f32[0];
+ pDestination->m[0][1] = M.r[0].vector4_f32[1];
+ pDestination->m[0][2] = M.r[0].vector4_f32[2];
+
+ pDestination->m[1][0] = M.r[1].vector4_f32[0];
+ pDestination->m[1][1] = M.r[1].vector4_f32[1];
+ pDestination->m[1][2] = M.r[1].vector4_f32[2];
+
+ pDestination->m[2][0] = M.r[2].vector4_f32[0];
+ pDestination->m[2][1] = M.r[2].vector4_f32[1];
+ pDestination->m[2][2] = M.r[2].vector4_f32[2];
+
+ pDestination->m[3][0] = M.r[3].vector4_f32[0];
+ pDestination->m[3][1] = M.r[3].vector4_f32[1];
+ pDestination->m[3][2] = M.r[3].vector4_f32[2];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ XMVECTOR vTemp1 = M.r[0];
+ XMVECTOR vTemp2 = M.r[1];
+ XMVECTOR vTemp3 = M.r[2];
+ XMVECTOR vTemp4 = M.r[3];
+ XMVECTOR vTemp2x = _mm_shuffle_ps(vTemp2,vTemp3,_MM_SHUFFLE(1,0,2,1));
+ vTemp2 = _mm_shuffle_ps(vTemp2,vTemp1,_MM_SHUFFLE(2,2,0,0));
+ vTemp1 = _mm_shuffle_ps(vTemp1,vTemp2,_MM_SHUFFLE(0,2,1,0));
+ vTemp3 = _mm_shuffle_ps(vTemp3,vTemp4,_MM_SHUFFLE(0,0,2,2));
+ vTemp3 = _mm_shuffle_ps(vTemp3,vTemp4,_MM_SHUFFLE(2,1,2,0));
+ _mm_storeu_ps(&pDestination->m[0][0],vTemp1);
+ _mm_storeu_ps(&pDestination->m[1][1],vTemp2x);
+ _mm_storeu_ps(&pDestination->m[2][2],vTemp3);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat4x4
+(
+ XMFLOAT4X4* pDestination,
+ CXMMATRIX M
+)
+{
+#if defined(_XM_NO_INTRINSICS_) || defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
+
+ XMStoreFloat4x4NC(pDestination, M);
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+
+ _mm_storeu_ps( &pDestination->_11, M.r[0] );
+ _mm_storeu_ps( &pDestination->_21, M.r[1] );
+ _mm_storeu_ps( &pDestination->_31, M.r[2] );
+ _mm_storeu_ps( &pDestination->_41, M.r[3] );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat4x4A
+(
+ XMFLOAT4X4A* pDestination,
+ CXMMATRIX M
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+ XMASSERT(((UINT_PTR)pDestination & 0xF) == 0);
+
+ pDestination->m[0][0] = M.r[0].vector4_f32[0];
+ pDestination->m[0][1] = M.r[0].vector4_f32[1];
+ pDestination->m[0][2] = M.r[0].vector4_f32[2];
+ pDestination->m[0][3] = M.r[0].vector4_f32[3];
+
+ pDestination->m[1][0] = M.r[1].vector4_f32[0];
+ pDestination->m[1][1] = M.r[1].vector4_f32[1];
+ pDestination->m[1][2] = M.r[1].vector4_f32[2];
+ pDestination->m[1][3] = M.r[1].vector4_f32[3];
+
+ pDestination->m[2][0] = M.r[2].vector4_f32[0];
+ pDestination->m[2][1] = M.r[2].vector4_f32[1];
+ pDestination->m[2][2] = M.r[2].vector4_f32[2];
+ pDestination->m[2][3] = M.r[2].vector4_f32[3];
+
+ pDestination->m[3][0] = M.r[3].vector4_f32[0];
+ pDestination->m[3][1] = M.r[3].vector4_f32[1];
+ pDestination->m[3][2] = M.r[3].vector4_f32[2];
+ pDestination->m[3][3] = M.r[3].vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+
+ _mm_store_ps( &pDestination->_11, M.r[0] );
+ _mm_store_ps( &pDestination->_21, M.r[1] );
+ _mm_store_ps( &pDestination->_31, M.r[2] );
+ _mm_store_ps( &pDestination->_41, M.r[3] );
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+//------------------------------------------------------------------------------
+
+XMFINLINE VOID XMStoreFloat4x4NC
+(
+ XMFLOAT4X4* pDestination,
+ CXMMATRIX M
+)
+{
+#if defined(_XM_NO_INTRINSICS_)
+
+ XMASSERT(pDestination);
+
+ pDestination->m[0][0] = M.r[0].vector4_f32[0];
+ pDestination->m[0][1] = M.r[0].vector4_f32[1];
+ pDestination->m[0][2] = M.r[0].vector4_f32[2];
+ pDestination->m[0][3] = M.r[0].vector4_f32[3];
+
+ pDestination->m[1][0] = M.r[1].vector4_f32[0];
+ pDestination->m[1][1] = M.r[1].vector4_f32[1];
+ pDestination->m[1][2] = M.r[1].vector4_f32[2];
+ pDestination->m[1][3] = M.r[1].vector4_f32[3];
+
+ pDestination->m[2][0] = M.r[2].vector4_f32[0];
+ pDestination->m[2][1] = M.r[2].vector4_f32[1];
+ pDestination->m[2][2] = M.r[2].vector4_f32[2];
+ pDestination->m[2][3] = M.r[2].vector4_f32[3];
+
+ pDestination->m[3][0] = M.r[3].vector4_f32[0];
+ pDestination->m[3][1] = M.r[3].vector4_f32[1];
+ pDestination->m[3][2] = M.r[3].vector4_f32[2];
+ pDestination->m[3][3] = M.r[3].vector4_f32[3];
+
+#elif defined(_XM_SSE_INTRINSICS_)
+ XMASSERT(pDestination);
+ _mm_storeu_ps(&pDestination->m[0][0],M.r[0]);
+ _mm_storeu_ps(&pDestination->m[1][0],M.r[1]);
+ _mm_storeu_ps(&pDestination->m[2][0],M.r[2]);
+ _mm_storeu_ps(&pDestination->m[3][0],M.r[3]);
+#else // _XM_VMX128_INTRINSICS_
+#endif // _XM_VMX128_INTRINSICS_
+}
+
+#endif // __XNAMATHCONVERT_INL__
+