Improve the codegen of the vector accelerated `System.Numerics.*` types (#81335)
authorTanner Gooding <tagoo@outlook.com>
Thu, 2 Feb 2023 06:21:11 +0000 (22:21 -0800)
committerGitHub <noreply@github.com>
Thu, 2 Feb 2023 06:21:11 +0000 (22:21 -0800)
* Allow Quaternion and Plane to be imported as TYP_SIMD16

* Add some minimal intrinsification of Quaternion and Plane

* Ensure Vector indexers are marked readonly

* Ensure the vector constant properties are intrinsic

* Ensure that the vector GetElement and WithElement APIs are intrinsic

* Ensure vector division by scalar is intrinsic

* Minor cleanup to vector files

* Ensure vector arithmetic functions are consistently intrinsic

* Ensure creating a plane from a vector4 is intrinsic

* Ensure accessing the Normal field of a Plane is efficient

* Ensure Quaternion and Plane return the correct SimdAsHWIntrinsicClassId

* Specially optimize Create(Dot(..., ...)) and Create(Sqrt(Dot(..., ...)))

* Ensure vector clamp is intrinsic

* Ensure vector lerp is intrinsic

* Ensure vector length is intrinsic

* Ensure vector normalize is intrinsic

* Ensure vector distance is intrinsic

* Optimize the vector transform by matrix methods

* Ensure quaternion conjugate and inverse are intrinsic

* Fixing assert, formatting, and build failure

* Ensure Quaternion.Inverse uses LengthSquared not Length

* Ensure Create APIs are correctly imported as intrinsic

* Ensure we don't assert for AltJit

* Ensure lowering DotProd doesn't break CSE for scalar vs vector results

* Minimally fixup Mono for the new intrinsics

* Ensure SN_GetElement doesn't raise an assert

* Ensure get_UnitW is ordered correctly for Mono

* Try to fix SN_GetElement

* Fix SN_WithElement for Mono

* Resolving mono formatting feedback

25 files changed:
src/coreclr/jit/compiler.h
src/coreclr/jit/gentree.cpp
src/coreclr/jit/lclmorph.cpp
src/coreclr/jit/lowerarmarch.cpp
src/coreclr/jit/lowerxarch.cpp
src/coreclr/jit/morph.cpp
src/coreclr/jit/simd.cpp
src/coreclr/jit/simdashwintrinsic.cpp
src/coreclr/jit/simdashwintrinsic.h
src/coreclr/jit/simdashwintrinsiclistarm64.h
src/coreclr/jit/simdashwintrinsiclistxarch.h
src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs
src/mono/mono/mini/simd-intrinsics.c
src/mono/mono/mini/simd-methods.h

index 2632ab5..74cf4e3 100644 (file)
@@ -8417,6 +8417,8 @@ private:
         CORINFO_CLASS_HANDLE SIMDNIntHandle;
         CORINFO_CLASS_HANDLE SIMDNUIntHandle;
 
+        CORINFO_CLASS_HANDLE SIMDPlaneHandle;
+        CORINFO_CLASS_HANDLE SIMDQuaternionHandle;
         CORINFO_CLASS_HANDLE SIMDVector2Handle;
         CORINFO_CLASS_HANDLE SIMDVector3Handle;
         CORINFO_CLASS_HANDLE SIMDVector4Handle;
@@ -8494,23 +8496,54 @@ private:
             switch (simdType)
             {
                 case TYP_SIMD8:
+                {
                     return m_simdHandleCache->SIMDVector2Handle;
+                }
+
                 case TYP_SIMD12:
+                {
                     return m_simdHandleCache->SIMDVector3Handle;
+                }
+
                 case TYP_SIMD16:
-                    if ((getSIMDVectorType() == TYP_SIMD32) ||
-                        (m_simdHandleCache->SIMDVector4Handle != NO_CLASS_HANDLE))
+                {
+                    // We order the checks roughly by expected hit count so early exits are possible
+
+                    if (simdBaseJitType != CORINFO_TYPE_FLOAT)
+                    {
+                        // We could be Vector<T>, so handle below
+                        assert(getSIMDVectorType() == TYP_SIMD16);
+                        break;
+                    }
+
+                    if (m_simdHandleCache->SIMDVector4Handle != NO_CLASS_HANDLE)
                     {
                         return m_simdHandleCache->SIMDVector4Handle;
                     }
-                    break;
+
+                    if (m_simdHandleCache->SIMDQuaternionHandle != NO_CLASS_HANDLE)
+                    {
+                        return m_simdHandleCache->SIMDQuaternionHandle;
+                    }
+
+                    if (m_simdHandleCache->SIMDPlaneHandle != NO_CLASS_HANDLE)
+                    {
+                        return m_simdHandleCache->SIMDPlaneHandle;
+                    }
+
+                    return NO_CLASS_HANDLE;
+                }
+
                 case TYP_SIMD32:
                     break;
+
                 default:
                     unreached();
             }
         }
+
         assert(emitTypeSize(simdType) <= largestEnregisterableStructSize());
+
         switch (simdBaseJitType)
         {
             case CORINFO_TYPE_FLOAT:
@@ -8540,6 +8573,7 @@ private:
             default:
                 assert(!"Didn't find a class handle for simdType");
         }
+
         return NO_CLASS_HANDLE;
     }
 
@@ -8617,9 +8651,39 @@ private:
     // actually be declared as having fields.
     bool isOpaqueSIMDType(CORINFO_CLASS_HANDLE structHandle) const
     {
-        return ((m_simdHandleCache != nullptr) && (structHandle != m_simdHandleCache->SIMDVector2Handle) &&
-                (structHandle != m_simdHandleCache->SIMDVector3Handle) &&
-                (structHandle != m_simdHandleCache->SIMDVector4Handle));
+        // We order the checks roughly by expected hit count so early exits are possible
+
+        if (m_simdHandleCache == nullptr)
+        {
+            return false;
+        }
+
+        if (structHandle == m_simdHandleCache->SIMDVector4Handle)
+        {
+            return false;
+        }
+
+        if (structHandle == m_simdHandleCache->SIMDVector3Handle)
+        {
+            return false;
+        }
+
+        if (structHandle == m_simdHandleCache->SIMDVector2Handle)
+        {
+            return false;
+        }
+
+        if (structHandle == m_simdHandleCache->SIMDQuaternionHandle)
+        {
+            return false;
+        }
+
+        if (structHandle == m_simdHandleCache->SIMDPlaneHandle)
+        {
+            return false;
+        }
+
+        return true;
     }
 
     // Returns true if the lclVar is an opaque SIMD type.
index 0a51c1c..f386a63 100644 (file)
@@ -21407,7 +21407,6 @@ GenTree* Compiler::gtNewSimdDotProdNode(var_types   type,
                                         bool        isSimdAsHWIntrinsic)
 {
     assert(IsBaselineSimdIsaSupportedDebugOnly());
-    assert(varTypeIsArithmetic(type));
 
     var_types simdType = getSIMDTypeForSize(simdSize);
     assert(varTypeIsSIMD(simdType));
@@ -21419,7 +21418,9 @@ GenTree* Compiler::gtNewSimdDotProdNode(var_types   type,
     assert(op2->TypeIs(simdType));
 
     var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType);
-    assert(JITtype2varType(simdBaseJitType) == type);
+
+    // We support the return type being a SIMD for floating-point as a special optimization
+    assert(varTypeIsArithmetic(type) || (varTypeIsSIMD(type) && varTypeIsFloating(simdBaseType)));
 
     NamedIntrinsic intrinsic = NI_Illegal;
 
index ce52720..0e610eb 100644 (file)
@@ -1156,16 +1156,32 @@ private:
                 break;
 
 #ifdef FEATURE_HW_INTRINSICS
+            // We have two cases we want to handle:
+            // 1. Vector2/3/4 and Quaternion where we have 4x float fields
+            // 2. Plane where we have 1x Vector3 and 1x float field
+
             case IndirTransform::GetElement:
             {
+                GenTree*  hwiNode     = nullptr;
                 var_types elementType = indir->TypeGet();
-                assert(elementType == TYP_FLOAT);
+                lclNode               = BashToLclVar(indir->gtGetOp1(), lclNum);
+
+                if (elementType == TYP_FLOAT)
+                {
+                    GenTree* indexNode = m_compiler->gtNewIconNode(val.Offset() / genTypeSize(elementType));
+                    hwiNode = m_compiler->gtNewSimdGetElementNode(elementType, lclNode, indexNode, CORINFO_TYPE_FLOAT,
+                                                                  genTypeSize(varDsc),
+                                                                  /* isSimdAsHWIntrinsic */ true);
+                }
+                else
+                {
+                    assert(elementType == TYP_SIMD12);
+                    assert(genTypeSize(varDsc) == 16);
+                    hwiNode =
+                        m_compiler->gtNewSimdHWIntrinsicNode(elementType, lclNode, NI_Vector128_AsVector3,
+                                                             CORINFO_TYPE_FLOAT, 16, /* isSimdAsHWIntrinsic */ true);
+                }
 
-                lclNode            = BashToLclVar(indir->gtGetOp1(), lclNum);
-                GenTree* indexNode = m_compiler->gtNewIconNode(val.Offset() / genTypeSize(elementType));
-                GenTree* hwiNode   = m_compiler->gtNewSimdGetElementNode(elementType, lclNode, indexNode,
-                                                                       CORINFO_TYPE_FLOAT, genTypeSize(varDsc),
-                                                                       /* isSimdAsHWIntrinsic */ false);
                 indir      = hwiNode;
                 *val.Use() = hwiNode;
             }
@@ -1174,17 +1190,35 @@ private:
             case IndirTransform::WithElement:
             {
                 assert(user->OperIs(GT_ASG) && (user->gtGetOp1() == indir));
+
+                GenTree*  hwiNode     = nullptr;
                 var_types elementType = indir->TypeGet();
-                assert(elementType == TYP_FLOAT);
-
-                lclNode              = BashToLclVar(indir, lclNum);
-                GenTree* simdLclNode = m_compiler->gtNewLclvNode(lclNum, varDsc->TypeGet());
-                GenTree* indexNode   = m_compiler->gtNewIconNode(val.Offset() / genTypeSize(elementType));
-                GenTree* elementNode = user->gtGetOp2();
-                user->AsOp()->gtOp2 =
-                    m_compiler->gtNewSimdWithElementNode(varDsc->TypeGet(), simdLclNode, indexNode, elementNode,
-                                                         CORINFO_TYPE_FLOAT, genTypeSize(varDsc),
-                                                         /* isSimdAsHWIntrinsic */ false);
+                lclNode               = BashToLclVar(indir, lclNum);
+                GenTree* simdLclNode  = m_compiler->gtNewLclvNode(lclNum, varDsc->TypeGet());
+                GenTree* elementNode  = user->gtGetOp2();
+
+                if (elementType == TYP_FLOAT)
+                {
+                    GenTree* indexNode = m_compiler->gtNewIconNode(val.Offset() / genTypeSize(elementType));
+                    hwiNode            = m_compiler->gtNewSimdWithElementNode(varDsc->TypeGet(), simdLclNode, indexNode,
+                                                                   elementNode, CORINFO_TYPE_FLOAT, genTypeSize(varDsc),
+                                                                   /* isSimdAsHWIntrinsic */ true);
+                }
+                else
+                {
+                    assert(elementType == TYP_SIMD12);
+                    assert(varDsc->TypeGet() == TYP_SIMD16);
+
+                    // We inverse the operands here and take elementNode as the main value and simdLclNode[3] as the
+                    // new value. This gives us a new TYP_SIMD16 with all elements in the right spots
+
+                    GenTree* indexNode = m_compiler->gtNewIconNode(3, TYP_INT);
+                    hwiNode =
+                        m_compiler->gtNewSimdWithElementNode(TYP_SIMD16, elementNode, indexNode, simdLclNode,
+                                                             CORINFO_TYPE_FLOAT, 16, /* isSimdAsHWIntrinsic */ true);
+                }
+
+                user->AsOp()->gtOp2 = hwiNode;
                 user->ChangeType(varDsc->TypeGet());
             }
             break;
@@ -1300,10 +1334,26 @@ private:
             }
 
 #ifdef FEATURE_HW_INTRINSICS
-            if (varTypeIsSIMD(varDsc) && indir->TypeIs(TYP_FLOAT) && ((val.Offset() % genTypeSize(TYP_FLOAT)) == 0) &&
-                m_compiler->IsBaselineSimdIsaSupported())
+            if (varTypeIsSIMD(varDsc))
             {
-                return isDef ? IndirTransform::WithElement : IndirTransform::GetElement;
+                // We have two cases we want to handle:
+                // 1. Vector2/3/4 and Quaternion where we have 4x float fields
+                // 2. Plane where we have 1x Vector3 and 1x float field
+
+                if (indir->TypeIs(TYP_FLOAT))
+                {
+                    if (((val.Offset() % genTypeSize(TYP_FLOAT)) == 0) && m_compiler->IsBaselineSimdIsaSupported())
+                    {
+                        return isDef ? IndirTransform::WithElement : IndirTransform::GetElement;
+                    }
+                }
+                else if (indir->TypeIs(TYP_SIMD12))
+                {
+                    if ((val.Offset() == 0) && m_compiler->IsBaselineSimdIsaSupported())
+                    {
+                        return isDef ? IndirTransform::WithElement : IndirTransform::GetElement;
+                    }
+                }
             }
 #endif // FEATURE_HW_INTRINSICS
 
index 70bb2b2..a9c981e 100644 (file)
@@ -1604,6 +1604,9 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
     assert(varTypeIsArithmetic(simdBaseType));
     assert(simdSize != 0);
 
+    // We support the return type being a SIMD for floating-point as a special optimization
+    assert(varTypeIsArithmetic(node) || (varTypeIsSIMD(node) && varTypeIsFloating(simdBaseType)));
+
     GenTree* op1 = node->Op(1);
     GenTree* op2 = node->Op(2);
 
@@ -1859,19 +1862,34 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
         }
     }
 
-    // We will be constructing the following parts:
-    //   ...
-    //          /--*  tmp2 simd16
-    //   node = *  HWINTRINSIC   simd16 T ToScalar
+    if (varTypeIsSIMD(node->gtType))
+    {
+        // We're producing a vector result, so just return the result directly
 
-    // This is roughly the following managed code:
-    //   ...
-    //   return tmp2.ToScalar();
+        LIR::Use use;
 
-    node->ResetHWIntrinsicId((simdSize == 8) ? NI_Vector64_ToScalar : NI_Vector128_ToScalar, tmp2);
+        if (BlockRange().TryGetUse(node, &use))
+        {
+            use.ReplaceWith(tmp2);
+        }
 
-    LowerNode(node);
-    return node->gtNext;
+        BlockRange().Remove(node);
+        return tmp2->gtNext;
+    }
+    else
+    {
+        // We will be constructing the following parts:
+        //   ...
+        //          /--*  tmp2 simd16
+        //   node = *  HWINTRINSIC   simd16 T ToScalar
+
+        // This is roughly the following managed code:
+        //   ...
+        //   return tmp2.ToScalar();
+
+        node->ResetHWIntrinsicId((simdSize == 8) ? NI_Vector64_ToScalar : NI_Vector128_ToScalar, tmp2);
+        return LowerNode(node);
+    }
 }
 #endif // FEATURE_HW_INTRINSICS
 
index 81940f9..5586eb2 100644 (file)
@@ -3590,6 +3590,9 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
     assert(varTypeIsArithmetic(simdBaseType));
     assert(simdSize != 0);
 
+    // We support the return type being a SIMD for floating-point as a special optimization
+    assert(varTypeIsArithmetic(node) || (varTypeIsSIMD(node) && varTypeIsFloating(simdBaseType)));
+
     GenTree* op1 = node->Op(1);
     GenTree* op2 = node->Op(2);
 
@@ -3753,25 +3756,38 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
 
                     if (simdSize == 8)
                     {
-                        idx = comp->gtNewIconNode(0x31, TYP_INT);
+                        idx = comp->gtNewIconNode(0x3F, TYP_INT);
                     }
                     else if (simdSize == 12)
                     {
-                        idx = comp->gtNewIconNode(0x71, TYP_INT);
+                        idx = comp->gtNewIconNode(0x7F, TYP_INT);
                     }
                     else
                     {
                         assert(simdSize == 16);
-                        idx = comp->gtNewIconNode(0xF1, TYP_INT);
+                        idx = comp->gtNewIconNode(0xFF, TYP_INT);
                     }
                     BlockRange().InsertBefore(node, idx);
 
-                    tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct, simdBaseJitType,
-                                                          simdSize);
-                    BlockRange().InsertAfter(idx, tmp3);
-                    LowerNode(tmp3);
+                    if (varTypeIsSIMD(node->gtType))
+                    {
+                        // We're producing a vector result, so just emit DotProduct directly
+                        node->ResetHWIntrinsicId(NI_SSE41_DotProduct, comp, op1, op2, idx);
+                    }
+                    else
+                    {
+                        // We're producing a scalar result, so we only need the result in element 0
+                        //
+                        // However, doing that would break/limit CSE and requires a partial write so
+                        // it's better to just broadcast the value to the entire vector
 
-                    node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp3);
+                        tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct,
+                                                              simdBaseJitType, simdSize);
+                        BlockRange().InsertAfter(idx, tmp3);
+                        LowerNode(tmp3);
+
+                        node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp3);
+                    }
 
                     return LowerNode(node);
                 }
@@ -3804,15 +3820,28 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
                     //   var tmp3 = Avx.DotProduct(op1, op2, 0x31);
                     //   return tmp3.ToScalar();
 
-                    idx = comp->gtNewIconNode(0x31, TYP_INT);
+                    idx = comp->gtNewIconNode(0x33, TYP_INT);
                     BlockRange().InsertBefore(node, idx);
 
-                    tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct, simdBaseJitType,
-                                                          simdSize);
-                    BlockRange().InsertAfter(idx, tmp3);
-                    LowerNode(tmp3);
+                    if (varTypeIsSIMD(node->gtType))
+                    {
+                        // We're producing a vector result, so just emit DotProduct directly
+                        node->ResetHWIntrinsicId(NI_SSE41_DotProduct, comp, op1, op2, idx);
+                    }
+                    else
+                    {
+                        // We're producing a scalar result, so we only need the result in element 0
+                        //
+                        // However, doing that would break/limit CSE and requires a partial write so
+                        // it's better to just broadcast the value to the entire vector
 
-                    node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp3);
+                        tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct,
+                                                              simdBaseJitType, simdSize);
+                        BlockRange().InsertAfter(idx, tmp3);
+                        LowerNode(tmp3);
+
+                        node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp3);
+                    }
 
                     return LowerNode(node);
                 }
@@ -4191,18 +4220,34 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
         node->SetSimdSize(16);
     }
 
-    // We will be constructing the following parts:
-    //   ...
-    //          /--*  tmp1 simd16
-    //   node = *  HWINTRINSIC   simd16 T ToScalar
+    if (varTypeIsSIMD(node->gtType))
+    {
+        // We're producing a vector result, so just return the result directly
 
-    // This is roughly the following managed code:
-    //   ...
-    //   return tmp1.ToScalar();
+        LIR::Use use;
 
-    node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp1);
+        if (BlockRange().TryGetUse(node, &use))
+        {
+            use.ReplaceWith(tmp1);
+        }
 
-    return LowerNode(node);
+        BlockRange().Remove(node);
+        return tmp1->gtNext;
+    }
+    else
+    {
+        // We will be constructing the following parts:
+        //   ...
+        //          /--*  tmp1 simd16
+        //   node = *  HWINTRINSIC   simd16 T ToScalar
+
+        // This is roughly the following managed code:
+        //   ...
+        //   return tmp1.ToScalar();
+
+        node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp1);
+        return LowerNode(node);
+    }
 }
 
 //----------------------------------------------------------------------------------------------
index 77453e0..f3db2e8 100644 (file)
@@ -10795,6 +10795,100 @@ GenTree* Compiler::fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node)
         return vecCon;
     }
 
+    NamedIntrinsic intrinsicId = node->GetHWIntrinsicId();
+
+    switch (intrinsicId)
+    {
+#if defined(TARGET_ARM64)
+        case NI_Vector64_Create:
+#endif // TARGET_ARM64
+        case NI_Vector128_Create:
+        {
+            // The `Dot` API returns a scalar. However, many common usages require it to
+            // be then immediately broadcast back to a vector so that it can be used in
+            // a subsequent operation. One of the most common is normalizing a vector
+            // which is effectively `value / value.Length` where `Length` is
+            // `Sqrt(Dot(value, value))`
+            //
+            // In order to ensure that developers can still utilize this efficiently, we
+            // will look for two common patterns:
+            //  * Create(Dot(..., ...))
+            //  * Create(Sqrt(Dot(..., ...)))
+            //
+            // When these exist, we'll avoid converting to a scalar at all and just
+            // keep everything as a vector. However, we only do this for Vector64/Vector128
+            // and only for float/double.
+            //
+            // We don't do this for Vector256 since that is xarch only and doesn't trivially
+            // support operations which cross the upper and lower 128-bit lanes
+
+            if (node->GetOperandCount() != 1)
+            {
+                break;
+            }
+
+            if (!varTypeIsFloating(node->GetSimdBaseType()))
+            {
+                break;
+            }
+
+            GenTree* op1  = node->Op(1);
+            GenTree* sqrt = nullptr;
+
+            if (op1->OperIs(GT_INTRINSIC))
+            {
+                if (op1->AsIntrinsic()->gtIntrinsicName != NI_System_Math_Sqrt)
+                {
+                    break;
+                }
+
+                sqrt = op1;
+                op1  = op1->gtGetOp1();
+            }
+
+            if (!op1->OperIs(GT_HWINTRINSIC))
+            {
+                break;
+            }
+
+            GenTreeHWIntrinsic* hwop1 = op1->AsHWIntrinsic();
+
+#if defined(TARGET_ARM64)
+            if ((hwop1->GetHWIntrinsicId() != NI_Vector64_Dot) && (hwop1->GetHWIntrinsicId() != NI_Vector128_Dot))
+#else
+            if (hwop1->GetHWIntrinsicId() != NI_Vector128_Dot)
+#endif
+            {
+                break;
+            }
+
+            unsigned  simdSize = node->GetSimdSize();
+            var_types simdType = getSIMDTypeForSize(simdSize);
+
+            hwop1->gtType = simdType;
+
+            if (sqrt != nullptr)
+            {
+                CorInfoType simdBaseJitType = node->GetSimdBaseJitType();
+                node = gtNewSimdSqrtNode(simdType, hwop1, simdBaseJitType, simdSize, node->IsSimdAsHWIntrinsic())
+                           ->AsHWIntrinsic();
+                DEBUG_DESTROY_NODE(sqrt);
+            }
+            else
+            {
+                node = hwop1;
+            }
+
+            INDEBUG(node->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
+            return node;
+        }
+
+        default:
+        {
+            break;
+        }
+    }
+
     return node;
 }
 
index d73d4d7..323300a 100644 (file)
@@ -284,6 +284,20 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH
             size            = getSIMDVectorRegisterByteLength();
             JITDUMP("  Known type SIMD Vector<nuint>\n");
         }
+        else if (typeHnd == m_simdHandleCache->SIMDQuaternionHandle)
+        {
+            simdBaseJitType = CORINFO_TYPE_FLOAT;
+            size            = 4 * genTypeSize(TYP_FLOAT);
+            assert(size == roundUp(info.compCompHnd->getClassSize(typeHnd), TARGET_POINTER_SIZE));
+            JITDUMP("  Known type Quaternion\n");
+        }
+        else if (typeHnd == m_simdHandleCache->SIMDPlaneHandle)
+        {
+            simdBaseJitType = CORINFO_TYPE_FLOAT;
+            size            = 4 * genTypeSize(TYP_FLOAT);
+            assert(size == roundUp(info.compCompHnd->getClassSize(typeHnd), TARGET_POINTER_SIZE));
+            JITDUMP("  Known type Plane\n");
+        }
 
         // slow path search
         if (simdBaseJitType == CORINFO_TYPE_UNDEF)
@@ -382,6 +396,24 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH
                 size                                = getSIMDVectorRegisterByteLength();
                 JITDUMP(" Found type Vector\n");
             }
+            else if (strcmp(className, "Quaternion") == 0)
+            {
+                m_simdHandleCache->SIMDQuaternionHandle = typeHnd;
+
+                simdBaseJitType = CORINFO_TYPE_FLOAT;
+                size            = 4 * genTypeSize(TYP_FLOAT);
+                assert(size == roundUp(info.compCompHnd->getClassSize(typeHnd), TARGET_POINTER_SIZE));
+                JITDUMP(" Found Quaternion\n");
+            }
+            else if (strcmp(className, "Plane") == 0)
+            {
+                m_simdHandleCache->SIMDPlaneHandle = typeHnd;
+
+                simdBaseJitType = CORINFO_TYPE_FLOAT;
+                size            = 4 * genTypeSize(TYP_FLOAT);
+                assert(size == roundUp(info.compCompHnd->getClassSize(typeHnd), TARGET_POINTER_SIZE));
+                JITDUMP(" Found Plane\n");
+            }
         }
     }
 #ifdef FEATURE_HW_INTRINSICS
index 6d36289..3e0a768 100644 (file)
@@ -125,33 +125,71 @@ SimdAsHWIntrinsicClassId SimdAsHWIntrinsicInfo::lookupClassId(const char* classN
 {
     assert(className != nullptr);
 
-    if ((enclosingClassName != nullptr) || (className[0] != 'V'))
+    if (enclosingClassName != nullptr)
     {
         return SimdAsHWIntrinsicClassId::Unknown;
     }
-    if (strcmp(className, "Vector2") == 0)
-    {
-        return SimdAsHWIntrinsicClassId::Vector2;
-    }
-    if (strcmp(className, "Vector3") == 0)
-    {
-        return SimdAsHWIntrinsicClassId::Vector3;
-    }
-    if (strcmp(className, "Vector4") == 0)
-    {
-        return SimdAsHWIntrinsicClassId::Vector4;
-    }
-    if ((strcmp(className, "Vector") == 0) || (strcmp(className, "Vector`1") == 0))
+
+    switch (className[0])
     {
-#if defined(TARGET_XARCH)
-        if (sizeOfVectorT == 32)
+        case 'P':
         {
-            return SimdAsHWIntrinsicClassId::VectorT256;
+            if (strcmp(className, "Plane") == 0)
+            {
+                return SimdAsHWIntrinsicClassId::Plane;
+            }
+            break;
         }
+
+        case 'Q':
+        {
+            if (strcmp(className, "Quaternion") == 0)
+            {
+                return SimdAsHWIntrinsicClassId::Quaternion;
+            }
+            break;
+        }
+
+        case 'V':
+        {
+            if (strncmp(className, "Vector", 6) != 0)
+            {
+                break;
+            }
+
+            className += 6;
+
+            if (strcmp(className, "2") == 0)
+            {
+                return SimdAsHWIntrinsicClassId::Vector2;
+            }
+            else if (strcmp(className, "3") == 0)
+            {
+                return SimdAsHWIntrinsicClassId::Vector3;
+            }
+            else if (strcmp(className, "4") == 0)
+            {
+                return SimdAsHWIntrinsicClassId::Vector4;
+            }
+            else if ((className[0] == '\0') || (strcmp(className, "`1") == 0))
+            {
+#if defined(TARGET_XARCH)
+                if (sizeOfVectorT == 32)
+                {
+                    return SimdAsHWIntrinsicClassId::VectorT256;
+                }
 #endif // TARGET_XARCH
 
-        assert(sizeOfVectorT == 16);
-        return SimdAsHWIntrinsicClassId::VectorT128;
+                assert(sizeOfVectorT == 16);
+                return SimdAsHWIntrinsicClassId::VectorT128;
+            }
+            break;
+        }
+
+        default:
+        {
+            break;
+        }
     }
 
     return SimdAsHWIntrinsicClassId::Unknown;
@@ -244,7 +282,7 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic        intrinsic,
 
         if (SimdAsHWIntrinsicInfo::BaseTypeFromThisArg(intrinsic))
         {
-            assert(simdBaseJitType == CORINFO_TYPE_UNDEF);
+            assert((simdBaseJitType == CORINFO_TYPE_UNDEF) || (simdBaseJitType == CORINFO_TYPE_VALUECLASS));
             simdBaseJitType = getBaseJitTypeAndSizeOfSIMDType(clsHnd, &simdSize);
         }
     }
@@ -334,6 +372,8 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic        intrinsic,
                                              2 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic"));
             }
 
+            assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic));
+
             CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList);
             argType                      = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass)));
             op2                          = getArgForHWIntrinsic(argType, argClass);
@@ -408,6 +448,27 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
 #if defined(TARGET_XARCH)
     bool isVectorT256 = (SimdAsHWIntrinsicInfo::lookupClassId(intrinsic) == SimdAsHWIntrinsicClassId::VectorT256);
 
+    if (isVectorT256 && (simdSize != 32))
+    {
+        // We have a couple extension methods for Vector2/3/4 and Quaternion exposed here
+        // Such APIs are not actually AVX/AVX2 dependent and operate on 128-bit vectors
+
+        switch (intrinsic)
+        {
+            case NI_VectorT256_GetElement:
+            case NI_VectorT256_WithElement:
+            {
+                isVectorT256 = false;
+                break;
+            }
+
+            default:
+            {
+                break;
+            }
+        }
+    }
+
     // We should have already exited early if SSE2 isn't supported
     assert(compIsaSupportedDebugOnly(InstructionSet_SSE2));
 
@@ -748,6 +809,61 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                     return gtNewOneConNode(retType, simdBaseType);
                 }
 
+                case NI_Vector2_get_UnitX:
+                case NI_Vector3_get_UnitX:
+                case NI_Vector4_get_UnitX:
+                {
+                    GenTreeVecCon* vecCon = gtNewVconNode(retType);
+
+                    vecCon->gtSimd16Val.f32[0] = 1.0f;
+                    vecCon->gtSimd16Val.f32[1] = 0.0f;
+                    vecCon->gtSimd16Val.f32[2] = 0.0f;
+                    vecCon->gtSimd16Val.f32[3] = 0.0f;
+
+                    return vecCon;
+                }
+
+                case NI_Vector2_get_UnitY:
+                case NI_Vector3_get_UnitY:
+                case NI_Vector4_get_UnitY:
+                {
+                    GenTreeVecCon* vecCon = gtNewVconNode(retType);
+
+                    vecCon->gtSimd16Val.f32[0] = 0.0f;
+                    vecCon->gtSimd16Val.f32[1] = 1.0f;
+                    vecCon->gtSimd16Val.f32[2] = 0.0f;
+                    vecCon->gtSimd16Val.f32[3] = 0.0f;
+
+                    return vecCon;
+                }
+
+                case NI_Vector3_get_UnitZ:
+                case NI_Vector4_get_UnitZ:
+                {
+                    GenTreeVecCon* vecCon = gtNewVconNode(retType);
+
+                    vecCon->gtSimd16Val.f32[0] = 0.0f;
+                    vecCon->gtSimd16Val.f32[1] = 0.0f;
+                    vecCon->gtSimd16Val.f32[2] = 1.0f;
+                    vecCon->gtSimd16Val.f32[3] = 0.0f;
+
+                    return vecCon;
+                }
+
+                case NI_Quaternion_get_Identity:
+                case NI_Vector4_get_UnitW:
+                {
+                    GenTreeVecCon* vecCon = gtNewVconNode(retType);
+
+                    vecCon->gtSimd16Val.f32[0] = 0.0f;
+                    vecCon->gtSimd16Val.f32[1] = 0.0f;
+                    vecCon->gtSimd16Val.f32[2] = 0.0f;
+                    vecCon->gtSimd16Val.f32[3] = 1.0f;
+
+                    return vecCon;
+                }
+
+                case NI_Quaternion_get_Zero:
                 case NI_Vector2_get_Zero:
                 case NI_Vector3_get_Zero:
                 case NI_Vector4_get_Zero:
@@ -817,6 +933,52 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                     return gtNewSimdCeilNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Quaternion_Conjugate:
+                {
+                    GenTreeVecCon* vecCon = gtNewVconNode(retType);
+
+                    vecCon->gtSimd16Val.f32[0] = -1.0f;
+                    vecCon->gtSimd16Val.f32[1] = -1.0f;
+                    vecCon->gtSimd16Val.f32[2] = -1.0f;
+                    vecCon->gtSimd16Val.f32[3] = +1.0f;
+
+                    return gtNewSimdBinOpNode(GT_MUL, retType, op1, vecCon, simdBaseJitType, simdSize,
+                                              /* isSimdAsHWIntrinsic */ true);
+                }
+
+                case NI_Vector2_Distance:
+                case NI_Vector3_Distance:
+                case NI_Vector4_Distance:
+                {
+                    op1 = gtNewSimdBinOpNode(GT_SUB, retType, op1, op2, simdBaseJitType, simdSize,
+                                             /* isSimdAsHWIntrinsic */ true);
+
+                    GenTree* clonedOp1;
+                    op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
+                                       nullptr DEBUGARG("Clone diff for vector distance"));
+
+                    op1 = gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize,
+                                               /* isSimdAsHWIntrinsic */ true);
+
+                    return new (this, GT_INTRINSIC)
+                        GenTreeIntrinsic(simdBaseType, op1, NI_System_Math_Sqrt, NO_METHOD_HANDLE);
+                }
+
+                case NI_Vector2_DistanceSquared:
+                case NI_Vector3_DistanceSquared:
+                case NI_Vector4_DistanceSquared:
+                {
+                    op1 = gtNewSimdBinOpNode(GT_SUB, retType, op1, op2, simdBaseJitType, simdSize,
+                                             /* isSimdAsHWIntrinsic */ true);
+
+                    GenTree* clonedOp1;
+                    op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
+                                       nullptr DEBUGARG("Clone diff for vector distance squared"));
+
+                    return gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize,
+                                                /* isSimdAsHWIntrinsic */ true);
+                }
+
                 case NI_VectorT128_Floor:
 #if defined(TARGET_XARCH)
                 case NI_VectorT256_Floor:
@@ -825,6 +987,62 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                     return gtNewSimdFloorNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Quaternion_Inverse:
+                {
+                    GenTree* clonedOp1;
+                    op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
+                                       nullptr DEBUGARG("Clone op1 for quaternion inverse (1)"));
+
+                    GenTree* clonedOp2;
+                    clonedOp1 = impCloneExpr(clonedOp1, &clonedOp2, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
+                                             nullptr DEBUGARG("Clone op1 for quaternion inverse (2)"));
+
+                    GenTreeVecCon* vecCon = gtNewVconNode(retType);
+
+                    vecCon->gtSimd16Val.f32[0] = -1.0f;
+                    vecCon->gtSimd16Val.f32[1] = -1.0f;
+                    vecCon->gtSimd16Val.f32[2] = -1.0f;
+                    vecCon->gtSimd16Val.f32[3] = +1.0f;
+
+                    GenTree* conjugate = gtNewSimdBinOpNode(GT_MUL, retType, op1, vecCon, simdBaseJitType, simdSize,
+                                                            /* isSimdAsHWIntrinsic */ true);
+
+                    op1 = gtNewSimdDotProdNode(retType, clonedOp1, clonedOp2, simdBaseJitType, simdSize,
+                                               /* isSimdAsHWIntrinsic */ true);
+
+                    return gtNewSimdBinOpNode(GT_DIV, retType, conjugate, op1, simdBaseJitType, simdSize,
+                                              /* isSimdAsHWIntrinsic */ true);
+                }
+
+                case NI_Quaternion_Length:
+                case NI_Vector2_Length:
+                case NI_Vector3_Length:
+                case NI_Vector4_Length:
+                {
+                    GenTree* clonedOp1;
+                    op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
+                                       nullptr DEBUGARG("Clone op1 for vector length"));
+
+                    op1 = gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize,
+                                               /* isSimdAsHWIntrinsic */ true);
+
+                    return new (this, GT_INTRINSIC)
+                        GenTreeIntrinsic(simdBaseType, op1, NI_System_Math_Sqrt, NO_METHOD_HANDLE);
+                }
+
+                case NI_Quaternion_LengthSquared:
+                case NI_Vector2_LengthSquared:
+                case NI_Vector3_LengthSquared:
+                case NI_Vector4_LengthSquared:
+                {
+                    GenTree* clonedOp1;
+                    op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
+                                       nullptr DEBUGARG("Clone op1 for vector length squared"));
+
+                    return gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize,
+                                                /* isSimdAsHWIntrinsic */ true);
+                }
+
                 case NI_VectorT128_Load:
                 case NI_VectorT128_LoadUnsafe:
 #if defined(TARGET_XARCH)
@@ -871,8 +1089,13 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                                         /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Quaternion_Negate:
+                case NI_Quaternion_op_UnaryNegation:
+                case NI_Vector2_Negate:
                 case NI_Vector2_op_UnaryNegation:
+                case NI_Vector3_Negate:
                 case NI_Vector3_op_UnaryNegation:
+                case NI_Vector4_Negate:
                 case NI_Vector4_op_UnaryNegation:
                 case NI_VectorT128_Negate:
                 case NI_VectorT128_op_UnaryNegation:
@@ -885,6 +1108,28 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                              /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Quaternion_Normalize:
+                case NI_Vector2_Normalize:
+                case NI_Vector3_Normalize:
+                case NI_Vector4_Normalize:
+                {
+                    GenTree* clonedOp1;
+                    op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
+                                       nullptr DEBUGARG("Clone op1 for vector normalize (1)"));
+
+                    GenTree* clonedOp2;
+                    clonedOp1 = impCloneExpr(clonedOp1, &clonedOp2, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
+                                             nullptr DEBUGARG("Clone op1 for vector normalize (2)"));
+
+                    op1 = gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize,
+                                               /* isSimdAsHWIntrinsic */ true);
+
+                    op1 = gtNewSimdSqrtNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true);
+
+                    return gtNewSimdBinOpNode(GT_DIV, retType, clonedOp2, op1, simdBaseJitType, simdSize,
+                                              /* isSimdAsHWIntrinsic */ true);
+                }
+
                 case NI_VectorT128_OnesComplement:
                 case NI_VectorT128_op_OnesComplement:
 #if defined(TARGET_XARCH)
@@ -1037,6 +1282,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                              2 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic"));
             }
 
+            assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic));
+
             CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList);
             argType                      = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass)));
             op2                          = getArgForHWIntrinsic(argType, argClass);
@@ -1059,8 +1306,13 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
 
             switch (intrinsic)
             {
+                case NI_Quaternion_Add:
+                case NI_Quaternion_op_Addition:
+                case NI_Vector2_Add:
                 case NI_Vector2_op_Addition:
+                case NI_Vector3_Add:
                 case NI_Vector3_op_Addition:
+                case NI_Vector4_Add:
                 case NI_Vector4_op_Addition:
                 case NI_VectorT128_Add:
                 case NI_VectorT128_op_Addition:
@@ -1120,8 +1372,22 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                     break;
                 }
 
+                case NI_Plane_CreateFromVector4:
+                {
+                    assert(retType == TYP_VOID);
+
+                    copyBlkDst = op1;
+                    copyBlkSrc = op2;
+
+                    break;
+                }
+
+                case NI_Quaternion_Divide:
+                case NI_Vector2_Divide:
                 case NI_Vector2_op_Division:
+                case NI_Vector3_Divide:
                 case NI_Vector3_op_Division:
+                case NI_Vector4_Divide:
                 case NI_Vector4_op_Division:
                 case NI_VectorT128_Divide:
                 case NI_VectorT128_op_Division:
@@ -1134,6 +1400,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                               /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Plane_Dot:
+                case NI_Quaternion_Dot:
                 case NI_Vector2_Dot:
                 case NI_Vector3_Dot:
                 case NI_Vector4_Dot:
@@ -1155,6 +1423,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                               /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Plane_op_Equality:
+                case NI_Quaternion_op_Equality:
                 case NI_Vector2_op_Equality:
                 case NI_Vector3_op_Equality:
                 case NI_Vector4_op_Equality:
@@ -1189,6 +1459,10 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                               /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Quaternion_get_Item:
+                case NI_Vector2_get_Item:
+                case NI_Vector3_get_Item:
+                case NI_Vector4_get_Item:
                 case NI_VectorT128_get_Item:
                 case NI_VectorT128_GetElement:
 #if defined(TARGET_XARCH)
@@ -1254,6 +1528,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                                  /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Plane_op_Inequality:
+                case NI_Quaternion_op_Inequality:
                 case NI_Vector2_op_Inequality:
                 case NI_Vector3_op_Inequality:
                 case NI_Vector4_op_Inequality:
@@ -1364,8 +1640,13 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                             /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Quaternion_Multiply:
+                case NI_Quaternion_op_Multiply:
+                case NI_Vector2_Multiply:
                 case NI_Vector2_op_Multiply:
+                case NI_Vector3_Multiply:
                 case NI_Vector3_op_Multiply:
+                case NI_Vector4_Multiply:
                 case NI_Vector4_op_Multiply:
                 case NI_VectorT128_Multiply:
                 case NI_VectorT128_op_Multiply:
@@ -1473,8 +1754,13 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                                          /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Quaternion_Subtract:
+                case NI_Quaternion_op_Subtraction:
+                case NI_Vector2_Subtract:
                 case NI_Vector2_op_Subtraction:
+                case NI_Vector3_Subtract:
                 case NI_Vector3_op_Subtraction:
+                case NI_Vector4_Subtract:
                 case NI_Vector4_op_Subtraction:
                 case NI_VectorT128_Subtract:
                 case NI_VectorT128_op_Subtraction:
@@ -1505,6 +1791,12 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                              3 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic"));
             }
 
+            if (SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic) && (newobjThis == nullptr))
+            {
+                impSpillSideEffect(true, verCurrentState.esStackDepth -
+                                             2 DEBUGARG("Spilling op2 side effects for SimdAsHWIntrinsic"));
+            }
+
             CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList);
             CORINFO_ARG_LIST_HANDLE arg3 = info.compCompHnd->getArgNext(arg2);
 
@@ -1532,6 +1824,16 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
 
             switch (intrinsic)
             {
+                case NI_Vector2_Clamp:
+                case NI_Vector3_Clamp:
+                case NI_Vector4_Clamp:
+                {
+                    GenTree* maxNode = gtNewSimdMaxNode(retType, op1, op2, simdBaseJitType, simdSize,
+                                                        /* isSimdAsHWIntrinsic */ true);
+                    return gtNewSimdMinNode(retType, maxNode, op3, simdBaseJitType, simdSize,
+                                            /* isSimdAsHWIntrinsic */ true);
+                }
+
                 case NI_VectorT128_ConditionalSelect:
 #if defined(TARGET_XARCH)
                 case NI_VectorT256_ConditionalSelect:
@@ -1541,6 +1843,53 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                                                /* isSimdAsHWIntrinsic */ true);
                 }
 
+                case NI_Vector2_Lerp:
+                case NI_Vector3_Lerp:
+                case NI_Vector4_Lerp:
+                {
+                    // We generate nodes equivalent to `(op1 * (1.0f - op3)) + (op2 * op3)`
+                    // optimizing for xarch by doing a single broadcast and for arm64 by
+                    // using multiply by scalar
+
+                    assert(simdBaseType == TYP_FLOAT);
+
+#if defined(TARGET_XARCH)
+                    // op3 = broadcast(op3)
+                    op3 = gtNewSimdCreateBroadcastNode(retType, op3, simdBaseJitType, simdSize,
+                                                       /* isSimdAsHWIntrinsic */ true);
+#endif // TARGET_XARCH
+
+                    // clonedOp3 = op3
+                    GenTree* clonedOp3;
+                    op3 = impCloneExpr(op3, &clonedOp3, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
+                                       nullptr DEBUGARG("Clone op3 for vector lerp"));
+
+#if defined(TARGET_XARCH)
+                    // op3 = 1.0f - op3
+                    GenTree* oneCon = gtNewOneConNode(retType, simdBaseType);
+                    op3             = gtNewSimdBinOpNode(GT_SUB, retType, oneCon, op3, simdBaseJitType, simdSize,
+                                             /* isSimdAsHWIntrinsic */ true);
+#elif defined(TARGET_ARM64)
+                    // op3 = 1.0f - op3
+                    GenTree* oneCon = gtNewOneConNode(simdBaseType);
+                    op3             = gtNewOperNode(GT_SUB, TYP_FLOAT, oneCon, op3);
+#else
+#error Unsupported platform
+#endif
+
+                    // op1 *= op3
+                    op1 = gtNewSimdBinOpNode(GT_MUL, retType, op1, op3, simdBaseJitType, simdSize,
+                                             /* isSimdAsHWIntrinsic */ true);
+
+                    // op2 *= clonedOp3
+                    op2 = gtNewSimdBinOpNode(GT_MUL, retType, op2, clonedOp3, simdBaseJitType, simdSize,
+                                             /* isSimdAsHWIntrinsic */ true);
+
+                    // return op1 + op2
+                    return gtNewSimdBinOpNode(GT_ADD, retType, op1, op2, simdBaseJitType, simdSize,
+                                              /* isSimdAsHWIntrinsic */ true);
+                }
+
                 case NI_VectorT128_StoreUnsafeIndex:
 #if defined(TARGET_XARCH)
                 case NI_VectorT256_StoreUnsafeIndex:
@@ -1597,7 +1946,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                         copyBlkSrc = gtNewSimdHWIntrinsicNode(TYP_SIMD8, std::move(nodeBuilder), NI_Vector128_Create,
                                                               simdBaseJitType, 16, /* isSimdAsHWIntrinsic */ true);
 #elif defined(TARGET_ARM64)
-                        copyBlkSrc = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op2, op3, NI_Vector64_Create, simdBaseJitType,
+                        copyBlkSrc  = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op2, op3, NI_Vector64_Create, simdBaseJitType,
                                                               8, /* isSimdAsHWIntrinsic */ true);
 #else
 #error Unsupported platform
@@ -1608,6 +1957,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
                     break;
                 }
 
+                case NI_Plane_CreateFromVector3:
+                case NI_Quaternion_CreateFromVector3:
                 case NI_Vector3_CreateFromVector2:
                 case NI_Vector4_CreateFromVector3:
                 {
@@ -1668,6 +2019,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
         {
             assert(isInstanceMethod);
             assert(SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic));
+            assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic));
 
             if (newobjThis == nullptr)
             {
@@ -1788,6 +2140,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
         {
             assert(isInstanceMethod);
             assert(SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic));
+            assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic));
 
             if (newobjThis == nullptr)
             {
@@ -1824,6 +2177,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic       intrinsic,
 
             switch (intrinsic)
             {
+                case NI_Plane_Create:
+                case NI_Quaternion_Create:
                 case NI_Vector4_Create:
                 {
                     assert(retType == TYP_VOID);
index f14b087..556e937 100644 (file)
@@ -7,6 +7,8 @@
 enum class SimdAsHWIntrinsicClassId
 {
     Unknown,
+    Plane,
+    Quaternion,
     Vector2,
     Vector3,
     Vector4,
@@ -34,6 +36,9 @@ enum class SimdAsHWIntrinsicFlag : unsigned int
 
     // Indicates that side effects need to be spilled for op1
     SpillSideEffectsOp1 = 0x20,
+
+    // Indicates that side effects need to be spilled for op2
+    SpillSideEffectsOp2 = 0x40,
 };
 
 inline SimdAsHWIntrinsicFlag operator~(SimdAsHWIntrinsicFlag value)
@@ -145,6 +150,12 @@ struct SimdAsHWIntrinsicInfo
         SimdAsHWIntrinsicFlag flags = lookupFlags(id);
         return (flags & SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) == SimdAsHWIntrinsicFlag::SpillSideEffectsOp1;
     }
+
+    static bool SpillSideEffectsOp2(NamedIntrinsic id)
+    {
+        SimdAsHWIntrinsicFlag flags = lookupFlags(id);
+        return (flags & SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) == SimdAsHWIntrinsicFlag::SpillSideEffectsOp2;
+    }
 };
 
 #endif // _SIMD_AS_HWINTRINSIC_H_
index 80e37fc..ff4beba 100644 (file)
 //                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                                                   Flags
 //                                                                                                     {TYP_BYTE,                                      TYP_UBYTE,                                      TYP_SHORT,                                      TYP_USHORT,                                     TYP_INT,                                        TYP_UINT,                                       TYP_LONG,                                       TYP_ULONG,                                      TYP_FLOAT,                                      TYP_DOUBLE}
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//  Plane Intrinsics
+SIMD_AS_HWINTRINSIC_NM(Plane,       Create,                     ".ctor",                    5,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Plane_Create,                                NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_NM(Plane,       CreateFromVector3,          ".ctor",                    3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Plane_CreateFromVector3,                     NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_NM(Plane,       CreateFromVector4,          ".ctor",                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Plane_CreateFromVector4,                     NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Plane,       Dot,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Plane_Dot,                                   NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Plane,       op_Equality,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Plane_op_Equality,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Plane,       op_Inequality,                                          2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Plane_op_Inequality,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+
+// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                                                   Flags
+//                                                                                                     {TYP_BYTE,                                      TYP_UBYTE,                                      TYP_SHORT,                                      TYP_USHORT,                                     TYP_INT,                                        TYP_UINT,                                       TYP_LONG,                                       TYP_ULONG,                                      TYP_FLOAT,                                      TYP_DOUBLE}
+// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//  Quaternion Intrinsics
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Add,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Add,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Conjugate,                                              1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Conjugate,                        NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_NM(Quaternion,  Create,                     ".ctor",                    5,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Create,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_NM(Quaternion,  CreateFromVector3,          ".ctor",                    3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_CreateFromVector3,                NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Divide,                                                 2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Divide,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Dot,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Dot,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  get_Identity,                                           0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_get_Identity,                     NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  get_Item,                                               0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_get_Item,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  get_Zero,                                               0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_get_Zero,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Inverse,                                                1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Inverse,                          NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Length,                                                 1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Length,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  LengthSquared,                                          1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_LengthSquared,                    NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Multiply,                                               2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Multiply,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Negate,                                                 1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Negate,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Normalize,                                              1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Normalize,                        NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Addition,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_op_Addition,                      NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Equality,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_op_Equality,                      NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Inequality,                                          2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_op_Inequality,                    NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Multiply,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_op_Multiply,                      NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Subtraction,                                         2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_op_Subtraction,                   NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_UnaryNegation,                                       1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_op_UnaryNegation,                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Subtract,                                               2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Quaternion_Subtract,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+
+// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                                                   Flags
+//                                                                                                     {TYP_BYTE,                                      TYP_UBYTE,                                      TYP_SHORT,                                      TYP_USHORT,                                     TYP_INT,                                        TYP_UINT,                                       TYP_LONG,                                       TYP_ULONG,                                      TYP_FLOAT,                                      TYP_DOUBLE}
+// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //  Vector2 Intrinsics
 SIMD_AS_HWINTRINSIC_ID(Vector2,     Abs,                                                    1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Abs,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Add,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Add,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Clamp,                                                  3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Clamp,                               NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector2,     Create,                     ".ctor",                    3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Create,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
 SIMD_AS_HWINTRINSIC_NM(Vector2,     CreateBroadcast,            ".ctor",                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_CreateBroadcast,                     NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Distance,                                               1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Distance,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     DistanceSquared,                                        1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_DistanceSquared,                     NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Divide,                                                 2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Divide,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     Dot,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Dot,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     get_Item,                                               0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_get_Item,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     get_One,                                                0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_get_One,                             NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     get_UnitX,                                              0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_get_UnitX,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     get_UnitY,                                              0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_get_UnitY,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     get_Zero,                                               0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_get_Zero,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Length,                                                 1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Length,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     LengthSquared,                                          1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_LengthSquared,                       NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Lerp,                                                   3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Lerp,                                NI_Illegal},                                    SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     Max,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Max,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     Min,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Min,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Multiply,                                               2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Multiply,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Negate,                                                 1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Negate,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Normalize,                                              1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Normalize,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Addition,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_op_Addition,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Division,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_op_Division,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Equality,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_op_Equality,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
@@ -53,6 +107,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Multiply,
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Subtraction,                                         2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_op_Subtraction,                      NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_UnaryNegation,                                       1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_op_UnaryNegation,                    NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector2,     Sqrt,                       "SquareRoot",               1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Sqrt,                                NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Subtract,                                               2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector2_Subtract,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                                                   Flags
@@ -60,14 +115,29 @@ SIMD_AS_HWINTRINSIC_NM(Vector2,     Sqrt,                       "SquareRoot",
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //  Vector3 Intrinsics
 SIMD_AS_HWINTRINSIC_ID(Vector3,     Abs,                                                    1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Abs,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Add,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Add,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Clamp,                                                  3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Clamp,                               NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector3,     Create,                     ".ctor",                    4,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Create,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
 SIMD_AS_HWINTRINSIC_NM(Vector3,     CreateBroadcast,            ".ctor",                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_CreateBroadcast,                     NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
-SIMD_AS_HWINTRINSIC_NM(Vector3,     CreateFromVector2,          ".ctor",                    3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_CreateFromVector2,                   NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_NM(Vector3,     CreateFromVector2,          ".ctor",                    3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_CreateFromVector2,                   NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Distance,                                               1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Distance,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     DistanceSquared,                                        1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_DistanceSquared,                     NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Divide,                                                 2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Divide,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     Dot,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Dot,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     get_Item,                                               0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_get_Item,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     get_One,                                                0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_get_One,                             NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
-SIMD_AS_HWINTRINSIC_ID(Vector3,     get_Zero,                                               0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_get_Zero  ,                          NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     get_UnitX,                                              0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_get_UnitX,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     get_UnitY,                                              0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_get_UnitY,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     get_UnitZ,                                              0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_get_UnitZ,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     get_Zero,                                               0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_get_Zero,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Length,                                                 1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Length,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     LengthSquared,                                          1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_LengthSquared,                       NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Lerp,                                                   3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Lerp,                                NI_Illegal},                                    SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     Max,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Max,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     Min,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Min,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Multiply,                                               2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Multiply,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Negate,                                                 1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Negate,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Normalize,                                              1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Normalize,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Addition,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_op_Addition,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Division,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_op_Division,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Equality,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_op_Equality,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
@@ -76,6 +146,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Multiply,
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Subtraction,                                         2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_op_Subtraction,                      NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_UnaryNegation,                                       1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_op_UnaryNegation,                    NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector3,     Sqrt,                       "SquareRoot",               1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Sqrt,                                NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Subtract,                                               2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector3_Subtract,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                                                   Flags
@@ -83,15 +154,31 @@ SIMD_AS_HWINTRINSIC_NM(Vector3,     Sqrt,                       "SquareRoot",
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //  Vector4 Intrinsics
 SIMD_AS_HWINTRINSIC_ID(Vector4,     Abs,                                                    1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Abs,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Add,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Add,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Clamp,                                                  3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Clamp,                               NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector4,     Create,                     ".ctor",                    5,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Create,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
 SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateBroadcast,            ".ctor",                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_CreateBroadcast,                     NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
-SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateFromVector2,          ".ctor",                    4,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_CreateFromVector2,                   NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
-SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateFromVector3,          ".ctor",                    3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_CreateFromVector3,                   NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateFromVector2,          ".ctor",                    4,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_CreateFromVector2,                   NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateFromVector3,          ".ctor",                    3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_CreateFromVector3,                   NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Distance,                                               1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Distance,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     DistanceSquared,                                        1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_DistanceSquared,                     NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Divide,                                                 2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Divide,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     Dot,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Dot,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_Item,                                               0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_get_Item,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     get_One,                                                0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_get_One,                             NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_UnitX,                                              0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_get_UnitX,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_UnitY,                                              0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_get_UnitY,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_UnitZ,                                              0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_get_UnitZ,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_UnitW,                                              0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_get_UnitW,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     get_Zero,                                               0,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_get_Zero,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Length,                                                 1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Length,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     LengthSquared,                                          1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_LengthSquared,                       NI_Illegal},                                    SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Lerp,                                                   3,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Lerp,                                NI_Illegal},                                    SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     Max,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Max,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     Min,                                                    2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Min,                                 NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Multiply,                                               2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Multiply,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Negate,                                                 1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Negate,                              NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Normalize,                                              1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Normalize,                           NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Addition,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_op_Addition,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Division,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_op_Division,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Equality,                                            2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_op_Equality,                         NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
@@ -100,6 +187,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Multiply,
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Subtraction,                                         2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_op_Subtraction,                      NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_UnaryNegation,                                       1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_op_UnaryNegation,                    NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector4,     Sqrt,                       "SquareRoot",               1,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Sqrt,                                NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Subtract,                                               2,         {NI_Illegal,                                    NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Illegal,                                     NI_Vector4_Subtract,                            NI_Illegal},                                    SimdAsHWIntrinsicFlag::None)
+
 
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                                                   Flags
index 24671df..7ad571f 100644 (file)
 //                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                           Flags
 //                                                                                                     {TYP_BYTE,                                  TYP_UBYTE,                                  TYP_SHORT,                                  TYP_USHORT,                                 TYP_INT,                                    TYP_UINT,                                   TYP_LONG,                                   TYP_ULONG,                                  TYP_FLOAT,                                  TYP_DOUBLE}
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//  Plane Intrinsics
+SIMD_AS_HWINTRINSIC_NM(Plane,       Create,                     ".ctor",                    5,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Plane_Create,                            NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_NM(Plane,       CreateFromVector3,          ".ctor",                    3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Plane_CreateFromVector3,                 NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_NM(Plane,       CreateFromVector4,          ".ctor",                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Plane_CreateFromVector4,                 NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Plane,       Dot,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Plane_Dot,                               NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Plane,       op_Equality,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Plane_op_Equality,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Plane,       op_Inequality,                                          2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Plane_op_Inequality,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+
+// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                           Flags
+//                                                                                                     {TYP_BYTE,                                  TYP_UBYTE,                                  TYP_SHORT,                                  TYP_USHORT,                                 TYP_INT,                                    TYP_UINT,                                   TYP_LONG,                                   TYP_ULONG,                                  TYP_FLOAT,                                  TYP_DOUBLE}
+// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//  Quaternion Intrinsics
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Add,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Add,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Conjugate,                                              1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Conjugate,                    NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_NM(Quaternion,  Create,                     ".ctor",                    5,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Create,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_NM(Quaternion,  CreateFromVector3,          ".ctor",                    3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_CreateFromVector3,            NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Divide,                                                 2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Divide,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Dot,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Dot,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  get_Identity,                                           0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_get_Identity,                 NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  get_Item,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_get_Item,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  get_Zero,                                               0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_get_Zero,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Inverse,                                                1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Inverse,                      NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Length,                                                 1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Length,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  LengthSquared,                                          1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_LengthSquared,                NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Multiply,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Multiply,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Negate,                                                 1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Negate,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Normalize,                                              1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Normalize,                    NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Addition,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_op_Addition,                  NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Equality,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_op_Equality,                  NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Inequality,                                          2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_op_Inequality,                NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Multiply,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_op_Multiply,                  NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_Subtraction,                                         2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_op_Subtraction,               NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  op_UnaryNegation,                                       1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_op_UnaryNegation,             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Quaternion,  Subtract,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Quaternion_Subtract,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+
+// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                           Flags
+//                                                                                                     {TYP_BYTE,                                  TYP_UBYTE,                                  TYP_SHORT,                                  TYP_USHORT,                                 TYP_INT,                                    TYP_UINT,                                   TYP_LONG,                                   TYP_ULONG,                                  TYP_FLOAT,                                  TYP_DOUBLE}
+// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //  Vector2 Intrinsics
 SIMD_AS_HWINTRINSIC_ID(Vector2,     Abs,                                                    1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Abs,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Add,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Add,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Clamp,                                                  3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Clamp,                           NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector2,     Create,                     ".ctor",                    3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Create,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
 SIMD_AS_HWINTRINSIC_NM(Vector2,     CreateBroadcast,            ".ctor",                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_CreateBroadcast,                 NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Distance,                                               1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Distance,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     DistanceSquared,                                        1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_DistanceSquared,                 NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Divide,                                                 2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Divide,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     Dot,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Dot,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     get_Item,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_get_Item,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     get_One,                                                0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_get_One,                         NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     get_UnitX,                                              0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_get_UnitX,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     get_UnitY,                                              0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_get_UnitY,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     get_Zero,                                               0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_get_Zero,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Length,                                                 1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Length,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     LengthSquared,                                          1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_LengthSquared,                   NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Lerp,                                                   3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Lerp,                            NI_Illegal},                                SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     Max,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Max,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     Min,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Min,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Multiply,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Multiply,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Negate,                                                 1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Negate,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Normalize,                                              1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Normalize,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Addition,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_op_Addition,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Division,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_op_Division,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Equality,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_op_Equality,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
@@ -53,6 +107,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Multiply,
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_Subtraction,                                         2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_op_Subtraction,                  NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector2,     op_UnaryNegation,                                       1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_op_UnaryNegation,                NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector2,     Sqrt,                       "SquareRoot",               1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Sqrt,                            NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector2,     Subtract,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector2_Subtract,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                           Flags
@@ -60,14 +115,29 @@ SIMD_AS_HWINTRINSIC_NM(Vector2,     Sqrt,                       "SquareRoot",
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //  Vector3 Intrinsics
 SIMD_AS_HWINTRINSIC_ID(Vector3,     Abs,                                                    1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Abs,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Add,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Add,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Clamp,                                                  3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Clamp,                           NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector3,     Create,                     ".ctor",                    4,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Create,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
 SIMD_AS_HWINTRINSIC_NM(Vector3,     CreateBroadcast,            ".ctor",                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_CreateBroadcast,                 NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
-SIMD_AS_HWINTRINSIC_NM(Vector3,     CreateFromVector2,          ".ctor",                    3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_CreateFromVector2,               NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_NM(Vector3,     CreateFromVector2,          ".ctor",                    3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_CreateFromVector2,               NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Distance,                                               1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Distance,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     DistanceSquared,                                        1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_DistanceSquared,                 NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Divide,                                                 2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Divide,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     Dot,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Dot,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     get_Item,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_get_Item,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     get_One,                                                0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_get_One,                         NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     get_UnitX,                                              0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_get_UnitX,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     get_UnitY,                                              0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_get_UnitY,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     get_UnitZ,                                              0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_get_UnitZ,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     get_Zero,                                               0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_get_Zero,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Length,                                                 1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Length,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     LengthSquared,                                          1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_LengthSquared,                   NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Lerp,                                                   3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Lerp,                            NI_Illegal},                                SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     Max,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Max,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     Min,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Min,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Multiply,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Multiply,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Negate,                                                 1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Negate,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Normalize,                                              1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Normalize,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Addition,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_op_Addition,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Division,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_op_Division,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Equality,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_op_Equality,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
@@ -76,6 +146,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Multiply,
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_Subtraction,                                         2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_op_Subtraction,                  NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector3,     op_UnaryNegation,                                       1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_op_UnaryNegation,                NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector3,     Sqrt,                       "SquareRoot",               1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Sqrt,                            NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector3,     Subtract,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector3_Subtract,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                           Flags
@@ -83,15 +154,31 @@ SIMD_AS_HWINTRINSIC_NM(Vector3,     Sqrt,                       "SquareRoot",
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //  Vector4 Intrinsics
 SIMD_AS_HWINTRINSIC_ID(Vector4,     Abs,                                                    1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Abs,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Add,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Add,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Clamp,                                                  3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Clamp,                           NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector4,     Create,                     ".ctor",                    5,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Create,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
 SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateBroadcast,            ".ctor",                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_CreateBroadcast,                 NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
-SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateFromVector2,          ".ctor",                    4,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_CreateFromVector2,               NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
-SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateFromVector3,          ".ctor",                    3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_CreateFromVector3,               NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1)
+SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateFromVector2,          ".ctor",                    4,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_CreateFromVector2,               NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_NM(Vector4,     CreateFromVector3,          ".ctor",                    3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_CreateFromVector3,               NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Distance,                                               1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Distance,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     DistanceSquared,                                        1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_DistanceSquared,                 NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Divide,                                                 2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Divide,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     Dot,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Dot,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_Item,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_get_Item,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     get_One,                                                0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_get_One,                         NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_UnitX,                                              0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_get_UnitX,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_UnitY,                                              0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_get_UnitY,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_UnitZ,                                              0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_get_UnitZ,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     get_UnitW,                                              0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_get_UnitW,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     get_Zero,                                               0,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_get_Zero,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Length,                                                 1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Length,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     LengthSquared,                                          1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_LengthSquared,                   NI_Illegal},                                SimdAsHWIntrinsicFlag::InstanceMethod)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Lerp,                                                   3,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Lerp,                            NI_Illegal},                                SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     Max,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Max,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     Min,                                                    2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Min,                             NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Multiply,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Multiply,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Negate,                                                 1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Negate,                          NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Normalize,                                              1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Normalize,                       NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Addition,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_op_Addition,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Division,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_op_Division,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Equality,                                            2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_op_Equality,                     NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
@@ -100,6 +187,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Multiply,
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_Subtraction,                                         2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_op_Subtraction,                  NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_ID(Vector4,     op_UnaryNegation,                                       1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_op_UnaryNegation,                NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 SIMD_AS_HWINTRINSIC_NM(Vector4,     Sqrt,                       "SquareRoot",               1,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Sqrt,                            NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
+SIMD_AS_HWINTRINSIC_ID(Vector4,     Subtract,                                               2,         {NI_Illegal,                                NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Illegal,                                 NI_Vector4_Subtract,                        NI_Illegal},                                SimdAsHWIntrinsicFlag::None)
 
 // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //                     ISA          ID                          Name                        NumArg                                                                                                                                                                                                      Instructions                                                                                                                                                                                                                                           Flags
index ce2500e..152cf86 100644 (file)
@@ -16,7 +16,7 @@ namespace System.Numerics
         public float M32;
         public Matrix3x2(float m11, float m12, float m21, float m22, float m31, float m32) { throw null; }
         public static System.Numerics.Matrix3x2 Identity { get { throw null; } }
-        public float this[int row, int column] { get { throw null; } set { throw null; } }
+        public float this[int row, int column] { readonly get { throw null; } set { throw null; } }
         public readonly bool IsIdentity { get { throw null; } }
         public System.Numerics.Vector2 Translation { readonly get { throw null; } set { } }
         public static System.Numerics.Matrix3x2 Add(System.Numerics.Matrix3x2 value1, System.Numerics.Matrix3x2 value2) { throw null; }
@@ -72,7 +72,7 @@ namespace System.Numerics
         public Matrix4x4(System.Numerics.Matrix3x2 value) { throw null; }
         public Matrix4x4(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44) { throw null; }
         public static System.Numerics.Matrix4x4 Identity { get { throw null; } }
-        public float this[int row, int column] { get { throw null; } set { throw null; } }
+        public float this[int row, int column] { readonly get { throw null; } set { throw null; } }
         public readonly bool IsIdentity { get { throw null; } }
         public System.Numerics.Vector3 Translation { readonly get { throw null; } set { } }
         public static System.Numerics.Matrix4x4 Add(System.Numerics.Matrix4x4 value1, System.Numerics.Matrix4x4 value2) { throw null; }
@@ -157,7 +157,7 @@ namespace System.Numerics
         public Quaternion(float x, float y, float z, float w) { throw null; }
         public static System.Numerics.Quaternion Zero { get { throw null; } }
         public static System.Numerics.Quaternion Identity { get { throw null; } }
-        public float this[int index] { get { throw null; } set { throw null; } }
+        public float this[int index] { readonly get { throw null; } set { throw null; } }
         public readonly bool IsIdentity { get { throw null; } }
         public static System.Numerics.Quaternion Add(System.Numerics.Quaternion value1, System.Numerics.Quaternion value2) { throw null; }
         public static System.Numerics.Quaternion Concatenate(System.Numerics.Quaternion value1, System.Numerics.Quaternion value2) { throw null; }
@@ -396,7 +396,7 @@ namespace System.Numerics
         public static System.Numerics.Vector2 One { get { throw null; } }
         public static System.Numerics.Vector2 UnitX { get { throw null; } }
         public static System.Numerics.Vector2 UnitY { get { throw null; } }
-        public float this[int index] { get { throw null; } set { throw null; } }
+        public float this[int index] { readonly get { throw null; } set { throw null; } }
         public static System.Numerics.Vector2 Zero { get { throw null; } }
         public static System.Numerics.Vector2 Abs(System.Numerics.Vector2 value) { throw null; }
         public static System.Numerics.Vector2 Add(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; }
@@ -458,7 +458,7 @@ namespace System.Numerics
         public static System.Numerics.Vector3 UnitX { get { throw null; } }
         public static System.Numerics.Vector3 UnitY { get { throw null; } }
         public static System.Numerics.Vector3 UnitZ { get { throw null; } }
-        public float this[int index] { get { throw null; } set { throw null; } }
+        public float this[int index] { readonly get { throw null; } set { throw null; } }
         public static System.Numerics.Vector3 Zero { get { throw null; } }
         public static System.Numerics.Vector3 Abs(System.Numerics.Vector3 value) { throw null; }
         public static System.Numerics.Vector3 Add(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; }
@@ -522,7 +522,7 @@ namespace System.Numerics
         public static System.Numerics.Vector4 UnitX { get { throw null; } }
         public static System.Numerics.Vector4 UnitY { get { throw null; } }
         public static System.Numerics.Vector4 UnitZ { get { throw null; } }
-        public float this[int index] { get { throw null; } set { throw null; } }
+        public float this[int index] { readonly get { throw null; } set { throw null; } }
         public static System.Numerics.Vector4 Zero { get { throw null; } }
         public static System.Numerics.Vector4 Abs(System.Numerics.Vector4 value) { throw null; }
         public static System.Numerics.Vector4 Add(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; }
index a3dc18c..03d6724 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Matrix4x4.Impl.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Plane.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Quaternion.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Quaternion.Extensions.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\TotalOrderIeee754Comparer.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector_1.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector2.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector2.Extensions.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector3.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector3.Extensions.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector4.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector4.Extensions.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\VectorDebugView_1.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\VectorMath.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Object.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\IUnaryPlusOperators.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\IUnsignedNumber.cs" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
index f60f32c..57c15f4 100644 (file)
@@ -2,7 +2,6 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.Intrinsics;
 
@@ -23,35 +22,38 @@ namespace System.Numerics
         /// <summary>The distance of the plane along its normal from the origin.</summary>
         public float D;
 
-        /// <summary>Creates a <see cref="System.Numerics.Plane" /> object from the X, Y, and Z components of its normal, and its distance from the origin on that normal.</summary>
+        /// <summary>Creates a <see cref="Plane" /> object from the X, Y, and Z components of its normal, and its distance from the origin on that normal.</summary>
         /// <param name="x">The X component of the normal.</param>
         /// <param name="y">The Y component of the normal.</param>
         /// <param name="z">The Z component of the normal.</param>
         /// <param name="d">The distance of the plane along its normal from the origin.</param>
+        [Intrinsic]
         public Plane(float x, float y, float z, float d)
         {
             Normal = new Vector3(x, y, z);
             D = d;
         }
 
-        /// <summary>Creates a <see cref="System.Numerics.Plane" /> object from a specified normal and the distance along the normal from the origin.</summary>
+        /// <summary>Creates a <see cref="Plane" /> object from a specified normal and the distance along the normal from the origin.</summary>
         /// <param name="normal">The plane's normal vector.</param>
         /// <param name="d">The plane's distance from the origin along its normal vector.</param>
+        [Intrinsic]
         public Plane(Vector3 normal, float d)
         {
             Normal = normal;
             D = d;
         }
 
-        /// <summary>Creates a <see cref="System.Numerics.Plane" /> object from a specified four-dimensional vector.</summary>
-        /// <param name="value">A vector whose first three elements describe the normal vector, and whose <see cref="System.Numerics.Vector4.W" /> defines the distance along that normal from the origin.</param>
+        /// <summary>Creates a <see cref="Plane" /> object from a specified four-dimensional vector.</summary>
+        /// <param name="value">A vector whose first three elements describe the normal vector, and whose <see cref="Vector4.W" /> defines the distance along that normal from the origin.</param>
+        [Intrinsic]
         public Plane(Vector4 value)
         {
             Normal = new Vector3(value.X, value.Y, value.Z);
             D = value.W;
         }
 
-        /// <summary>Creates a <see cref="System.Numerics.Plane" /> object that contains three specified points.</summary>
+        /// <summary>Creates a <see cref="Plane" /> object that contains three specified points.</summary>
         /// <param name="point1">The first point defining the plane.</param>
         /// <param name="point2">The second point defining the plane.</param>
         /// <param name="point3">The third point defining the plane.</param>
@@ -107,16 +109,17 @@ namespace System.Numerics
         /// <param name="plane">The plane.</param>
         /// <param name="value">The four-dimensional vector.</param>
         /// <returns>The dot product.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float Dot(Plane plane, Vector4 value)
         {
-            return plane.Normal.X * value.X +
-                   plane.Normal.Y * value.Y +
-                   plane.Normal.Z * value.Z +
-                   plane.D * value.W;
+            return (plane.Normal.X * value.X)
+                 + (plane.Normal.Y * value.Y)
+                 + (plane.Normal.Z * value.Z)
+                 + (plane.D * value.W);
         }
 
-        /// <summary>Returns the dot product of a specified three-dimensional vector and the normal vector of this plane plus the distance (<see cref="System.Numerics.Plane.D" />) value of the plane.</summary>
+        /// <summary>Returns the dot product of a specified three-dimensional vector and the normal vector of this plane plus the distance (<see cref="D" />) value of the plane.</summary>
         /// <param name="plane">The plane.</param>
         /// <param name="value">The 3-dimensional vector.</param>
         /// <returns>The dot product.</returns>
@@ -136,7 +139,7 @@ namespace System.Numerics
             }
         }
 
-        /// <summary>Returns the dot product of a specified three-dimensional vector and the <see cref="System.Numerics.Plane.Normal" /> vector of this plane.</summary>
+        /// <summary>Returns the dot product of a specified three-dimensional vector and the <see cref="Normal" /> vector of this plane.</summary>
         /// <param name="plane">The plane.</param>
         /// <param name="value">The three-dimensional vector.</param>
         /// <returns>The dot product.</returns>
@@ -155,7 +158,7 @@ namespace System.Numerics
             }
         }
 
-        /// <summary>Creates a new <see cref="System.Numerics.Plane" /> object whose normal vector is the source plane's normal vector normalized.</summary>
+        /// <summary>Creates a new <see cref="Plane" /> object whose normal vector is the source plane's normal vector normalized.</summary>
         /// <param name="value">The source plane.</param>
         /// <returns>The normalized plane.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -197,7 +200,7 @@ namespace System.Numerics
         /// <param name="plane">The normalized plane to transform.</param>
         /// <param name="matrix">The transformation matrix to apply to <paramref name="plane" />.</param>
         /// <returns>The transformed plane.</returns>
-        /// <remarks><paramref name="plane" /> must already be normalized so that its <see cref="System.Numerics.Plane.Normal" /> vector is of unit length before this method is called.</remarks>
+        /// <remarks><paramref name="plane" /> must already be normalized so that its <see cref="Normal" /> vector is of unit length before this method is called.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Plane Transform(Plane plane, Matrix4x4 matrix)
         {
@@ -216,7 +219,7 @@ namespace System.Numerics
         /// <param name="plane">The normalized plane to transform.</param>
         /// <param name="rotation">The Quaternion rotation to apply to the plane.</param>
         /// <returns>A new plane that results from applying the Quaternion rotation.</returns>
-        /// <remarks><paramref name="plane" /> must already be normalized so that its <see cref="System.Numerics.Plane.Normal" /> vector is of unit length before this method is called.</remarks>
+        /// <remarks><paramref name="plane" /> must already be normalized so that its <see cref="Normal" /> vector is of unit length before this method is called.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Plane Transform(Plane plane, Quaternion rotation)
         {
@@ -260,22 +263,22 @@ namespace System.Numerics
         /// <param name="value1">The first plane to compare.</param>
         /// <param name="value2">The second plane to compare.</param>
         /// <returns><see langword="true" /> if <paramref name="value1" /> and <paramref name="value2" /> are equal; otherwise, <see langword="false" />.</returns>
-        /// <remarks>Two <see cref="System.Numerics.Plane" /> objects are equal if their <see cref="System.Numerics.Plane.Normal" /> and <see cref="System.Numerics.Plane.D" /> fields are equal.
-        /// The <see cref="System.Numerics.Plane.op_Equality" /> method defines the operation of the equality operator for <see cref="System.Numerics.Plane" /> objects.</remarks>
+        /// <remarks>Two <see cref="Plane" /> objects are equal if their <see cref="Normal" /> and <see cref="D" /> fields are equal.
+        /// The <see cref="op_Equality" /> method defines the operation of the equality operator for <see cref="Plane" /> objects.</remarks>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool operator ==(Plane value1, Plane value2)
         {
-            return (value1.Normal.X == value2.Normal.X &&
-                    value1.Normal.Y == value2.Normal.Y &&
-                    value1.Normal.Z == value2.Normal.Z &&
-                    value1.D == value2.D);
+            return (value1.Normal == value2.Normal)
+                && (value1.D == value2.D);
         }
 
         /// <summary>Returns a value that indicates whether two planes are not equal.</summary>
         /// <param name="value1">The first plane to compare.</param>
         /// <param name="value2">The second plane to compare.</param>
         /// <returns><see langword="true" /> if <paramref name="value1" /> and <paramref name="value2" /> are not equal; otherwise, <see langword="false" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Plane.op_Inequality" /> method defines the operation of the inequality operator for <see cref="System.Numerics.Plane" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Inequality" /> method defines the operation of the inequality operator for <see cref="Plane" /> objects.</remarks>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool operator !=(Plane value1, Plane value2)
         {
@@ -285,7 +288,7 @@ namespace System.Numerics
         /// <summary>Returns a value that indicates whether this instance and a specified object are equal.</summary>
         /// <param name="obj">The object to compare with the current instance.</param>
         /// <returns><see langword="true" /> if the current instance and <paramref name="obj" /> are equal; otherwise, <see langword="false" />. If <paramref name="obj" /> is <see langword="null" />, the method returns <see langword="false" />.</returns>
-        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="System.Numerics.Plane" /> object and their <see cref="System.Numerics.Plane.Normal" /> and <see cref="System.Numerics.Plane.D" /> fields are equal.</remarks>
+        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="Plane" /> object and their <see cref="Normal" /> and <see cref="D" /> fields are equal.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public override readonly bool Equals([NotNullWhen(true)] object? obj)
         {
@@ -295,7 +298,7 @@ namespace System.Numerics
         /// <summary>Returns a value that indicates whether this instance and another plane object are equal.</summary>
         /// <param name="other">The other plane.</param>
         /// <returns><see langword="true" /> if the two planes are equal; otherwise, <see langword="false" />.</returns>
-        /// <remarks>Two <see cref="System.Numerics.Plane" /> objects are equal if their <see cref="System.Numerics.Plane.Normal" /> and <see cref="System.Numerics.Plane.D" /> fields are equal.</remarks>
+        /// <remarks>Two <see cref="Plane" /> objects are equal if their <see cref="Normal" /> and <see cref="D" /> fields are equal.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly bool Equals(Plane other)
         {
@@ -304,7 +307,7 @@ namespace System.Numerics
 
             if (Vector128.IsHardwareAccelerated)
             {
-                return Vector128.LoadUnsafe(ref Unsafe.AsRef(in Normal.X)).Equals(Vector128.LoadUnsafe(ref other.Normal.X));
+                return this.AsVector128().Equals(other.AsVector128());
             }
 
             return SoftwareFallback(in this, other);
@@ -324,8 +327,8 @@ namespace System.Numerics
         }
 
         /// <summary>Returns the string representation of this plane object.</summary>
-        /// <returns>A string that represents this <see cref="System.Numerics.Plane" /> object.</returns>
-        /// <remarks>The string representation of a <see cref="System.Numerics.Plane" /> object use the formatting conventions of the current culture to format the numeric values in the returned string. For example, a <see cref="System.Numerics.Plane" /> object whose string representation is formatted by using the conventions of the en-US culture might appear as <c>{Normal:&lt;1.1, 2.2, 3.3&gt; D:4.4}</c>.</remarks>
+        /// <returns>A string that represents this <see cref="Plane" /> object.</returns>
+        /// <remarks>The string representation of a <see cref="Plane" /> object use the formatting conventions of the current culture to format the numeric values in the returned string. For example, a <see cref="Plane" /> object whose string representation is formatted by using the conventions of the en-US culture might appear as <c>{Normal:&lt;1.1, 2.2, 3.3&gt; D:4.4}</c>.</remarks>
         public override readonly string ToString() => $"{{Normal:{Normal} D:{D}}}";
     }
 }
diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs
new file mode 100644 (file)
index 0000000..7c0e561
--- /dev/null
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Numerics
+{
+    public static unsafe partial class Vector
+    {
+        /// <summary>Gets the element at the specified index.</summary>
+        /// <param name="quaternion">The quaternion to get the element from.</param>
+        /// <param name="index">The index of the element to get.</param>
+        /// <returns>The value of the element at <paramref name="index" />.</returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static float GetElement(this Quaternion quaternion, int index)
+        {
+            if ((uint)(index) >= (uint)(Quaternion.Count))
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+            }
+
+            return quaternion.GetElementUnsafe(index);
+        }
+
+        /// <summary>Creates a new <see cref="Quaternion" /> with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given quaternion.</summary>
+        /// <param name="quaternion">The quaternion to get the remaining elements from.</param>
+        /// <param name="index">The index of the element to set.</param>
+        /// <param name="value">The value to set the element to.</param>
+        /// <returns>A <see cref="Quaternion" /> with the value of the element at <paramref name="index" /> set to <paramref name="value" /> and the remaining elements set to the same value as that in <paramref name="quaternion" />.</returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
+        [Intrinsic]
+        internal static Quaternion WithElement(this Quaternion quaternion, int index, float value)
+        {
+            if ((uint)(index) >= (uint)(Quaternion.Count))
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+            }
+
+            Quaternion result = quaternion;
+            result.SetElementUnsafe(index, value);
+            return result;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static float GetElementUnsafe(in this Quaternion quaternion, int index)
+        {
+            Debug.Assert((index >= 0) && (index < Quaternion.Count));
+            ref float address = ref Unsafe.AsRef(in quaternion.X);
+            return Unsafe.Add(ref address, index);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static void SetElementUnsafe(ref this Quaternion quaternion, int index, float value)
+        {
+            Debug.Assert((index >= 0) && (index < Quaternion.Count));
+            Unsafe.Add(ref quaternion.X, index) = value;
+        }
+    }
+}
index 1546153..594491f 100644 (file)
@@ -9,7 +9,7 @@ using System.Runtime.Intrinsics;
 namespace System.Numerics
 {
     /// <summary>Represents a vector that is used to encode three-dimensional physical rotations.</summary>
-    /// <remarks>The <see cref="System.Numerics.Quaternion" /> structure is used to efficiently rotate an object about the (x,y,z) vector by the angle theta, where:
+    /// <remarks>The <see cref="Quaternion" /> structure is used to efficiently rotate an object about the (x,y,z) vector by the angle theta, where:
     /// <c>w = cos(theta/2)</c></remarks>
     [Intrinsic]
     public struct Quaternion : IEquatable<Quaternion>
@@ -35,6 +35,7 @@ namespace System.Numerics
         /// <param name="y">The value to assign to the Y component of the quaternion.</param>
         /// <param name="z">The value to assign to the Z component of the quaternion.</param>
         /// <param name="w">The value to assign to the W component of the quaternion.</param>
+        [Intrinsic]
         public Quaternion(float x, float y, float z, float w)
         {
             X = x;
@@ -46,6 +47,7 @@ namespace System.Numerics
         /// <summary>Creates a quaternion from the specified vector and rotation parts.</summary>
         /// <param name="vectorPart">The vector part of the quaternion.</param>
         /// <param name="scalarPart">The rotation part of the quaternion.</param>
+        [Intrinsic]
         public Quaternion(Vector3 vectorPart, float scalarPart)
         {
             X = vectorPart.X;
@@ -58,6 +60,7 @@ namespace System.Numerics
         /// <value>A quaternion whose values are <c>(0, 0, 0, 0)</c>.</value>
         public static Quaternion Zero
         {
+            [Intrinsic]
             get => default;
         }
 
@@ -65,7 +68,8 @@ namespace System.Numerics
         /// <value>A quaternion whose values are <c>(0, 0, 0, 1)</c>.</value>
         public static Quaternion Identity
         {
-            get => new Quaternion(0, 0, 0, 1);
+            [Intrinsic]
+            get => new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
         }
 
         /// <summary>Gets or sets the element at the specified index.</summary>
@@ -74,61 +78,17 @@ namespace System.Numerics
         /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
         public float this[int index]
         {
-            get => GetElement(this, index);
-            set => this = WithElement(this, index, value);
-        }
+            [Intrinsic]
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => this.GetElement(index);
 
-        /// <summary>Gets the element at the specified index.</summary>
-        /// <param name="quaternion">The vector of the element to get.</param>
-        /// <param name="index">The index of the element to get.</param>
-        /// <returns>The value of the element at <paramref name="index" />.</returns>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
-        [Intrinsic]
-        internal static float GetElement(Quaternion quaternion, int index)
-        {
-            if ((uint)index >= Count)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
-            }
-
-            return GetElementUnsafe(ref quaternion, index);
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static float GetElementUnsafe(ref Quaternion quaternion, int index)
-        {
-            Debug.Assert(index is >= 0 and < Count);
-            return Unsafe.Add(ref Unsafe.As<Quaternion, float>(ref quaternion), index);
-        }
-
-        /// <summary>Sets the element at the specified index.</summary>
-        /// <param name="quaternion">The vector of the element to set.</param>
-        /// <param name="index">The index of the element to set.</param>
-        /// <param name="value">The value of the element to set.</param>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
-        [Intrinsic]
-        internal static Quaternion WithElement(Quaternion quaternion, int index, float value)
-        {
-            if ((uint)index >= Count)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
-            }
-
-            Quaternion result = quaternion;
-            SetElementUnsafe(ref result, index, value);
-            return result;
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static void SetElementUnsafe(ref Quaternion quaternion, int index, float value)
-        {
-            Debug.Assert(index is >= 0 and < Count);
-            Unsafe.Add(ref Unsafe.As<Quaternion, float>(ref quaternion), index) = value;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => this = this.WithElement(index, value);
         }
 
         /// <summary>Gets a value that indicates whether the current instance is the identity quaternion.</summary>
         /// <value><see langword="true" /> if the current instance is the identity quaternion; otherwise, <see langword="false" />.</value>
-        /// <altmember cref="System.Numerics.Quaternion.Identity"/>
+        /// <altmember cref="Identity"/>
         public readonly bool IsIdentity
         {
             get => this == Identity;
@@ -138,24 +98,24 @@ namespace System.Numerics
         /// <param name="value1">The first quaternion.</param>
         /// <param name="value2">The second quaternion.</param>
         /// <returns>The quaternion that contains the summed values of <paramref name="value1" /> and <paramref name="value2" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Quaternion.op_Addition" /> method defines the operation of the addition operator for <see cref="System.Numerics.Quaternion" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Addition" /> method defines the operation of the addition operator for <see cref="Quaternion" /> objects.</remarks>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion operator +(Quaternion value1, Quaternion value2)
         {
-            Quaternion ans;
-
-            ans.X = value1.X + value2.X;
-            ans.Y = value1.Y + value2.Y;
-            ans.Z = value1.Z + value2.Z;
-            ans.W = value1.W + value2.W;
-
-            return ans;
+            return new Quaternion(
+                value1.X + value2.X,
+                value1.Y + value2.Y,
+                value1.Z + value2.Z,
+                value1.W + value2.W
+            );
         }
 
         /// <summary>Divides one quaternion by a second quaternion.</summary>
         /// <param name="value1">The dividend.</param>
         /// <param name="value2">The divisor.</param>
         /// <returns>The quaternion that results from dividing <paramref name="value1" /> by <paramref name="value2" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Quaternion.op_Division" /> method defines the division operation for <see cref="System.Numerics.Quaternion" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Division" /> method defines the division operation for <see cref="Quaternion" /> objects.</remarks>
         public static Quaternion operator /(Quaternion value1, Quaternion value2)
         {
             Quaternion ans;
@@ -199,7 +159,9 @@ namespace System.Numerics
         /// <param name="value2">The second quaternion to compare.</param>
         /// <returns><see langword="true" /> if the two quaternions are equal; otherwise, <see langword="false" />.</returns>
         /// <remarks>Two quaternions are equal if each of their corresponding components is equal.
-        /// The <see cref="System.Numerics.Quaternion.op_Equality" /> method defines the operation of the equality operator for <see cref="System.Numerics.Quaternion" /> objects.</remarks>
+        /// The <see cref="op_Equality" /> method defines the operation of the equality operator for <see cref="Quaternion" /> objects.</remarks>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool operator ==(Quaternion value1, Quaternion value2)
         {
             return (value1.X == value2.X)
@@ -212,6 +174,8 @@ namespace System.Numerics
         /// <param name="value1">The first quaternion to compare.</param>
         /// <param name="value2">The second quaternion to compare.</param>
         /// <returns><see langword="true" /> if <paramref name="value1" /> and <paramref name="value2" /> are not equal; otherwise, <see langword="false" />.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool operator !=(Quaternion value1, Quaternion value2)
         {
             return !(value1 == value2);
@@ -221,7 +185,7 @@ namespace System.Numerics
         /// <param name="value1">The first quaternion.</param>
         /// <param name="value2">The second quaternion.</param>
         /// <returns>The product quaternion.</returns>
-        /// <remarks>The <see cref="System.Numerics.Quaternion.op_Multiply" /> method defines the operation of the multiplication operator for <see cref="System.Numerics.Quaternion" /> objects.</remarks>
+        /// <remarks>The <see cref="Quaternion.op_Multiply" /> method defines the operation of the multiplication operator for <see cref="Quaternion" /> objects.</remarks>
         public static Quaternion operator *(Quaternion value1, Quaternion value2)
         {
             Quaternion ans;
@@ -255,56 +219,52 @@ namespace System.Numerics
         /// <param name="value1">The source quaternion.</param>
         /// <param name="value2">The scalar value.</param>
         /// <returns>The scaled quaternion.</returns>
-        /// <remarks>The <see cref="System.Numerics.Quaternion.op_Multiply" /> method defines the operation of the multiplication operator for <see cref="System.Numerics.Quaternion" /> objects.</remarks>
+        /// <remarks>The <see cref="Quaternion.op_Multiply" /> method defines the operation of the multiplication operator for <see cref="Quaternion" /> objects.</remarks>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion operator *(Quaternion value1, float value2)
         {
-            Quaternion ans;
-
-            ans.X = value1.X * value2;
-            ans.Y = value1.Y * value2;
-            ans.Z = value1.Z * value2;
-            ans.W = value1.W * value2;
-
-            return ans;
+            return new Quaternion(
+                value1.X * value2,
+                value1.Y * value2,
+                value1.Z * value2,
+                value1.W * value2
+            );
         }
 
         /// <summary>Subtracts each element in a second quaternion from its corresponding element in a first quaternion.</summary>
         /// <param name="value1">The first quaternion.</param>
         /// <param name="value2">The second quaternion.</param>
         /// <returns>The quaternion containing the values that result from subtracting each element in <paramref name="value2" /> from its corresponding element in <paramref name="value1" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Quaternion.op_Subtraction" /> method defines the operation of the subtraction operator for <see cref="System.Numerics.Quaternion" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Subtraction" /> method defines the operation of the subtraction operator for <see cref="Quaternion" /> objects.</remarks>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion operator -(Quaternion value1, Quaternion value2)
         {
-            Quaternion ans;
-
-            ans.X = value1.X - value2.X;
-            ans.Y = value1.Y - value2.Y;
-            ans.Z = value1.Z - value2.Z;
-            ans.W = value1.W - value2.W;
-
-            return ans;
+            return new Quaternion(
+                value1.X - value2.X,
+                value1.Y - value2.Y,
+                value1.Z - value2.Z,
+                value1.W - value2.W
+            );
         }
 
         /// <summary>Reverses the sign of each component of the quaternion.</summary>
         /// <param name="value">The quaternion to negate.</param>
         /// <returns>The negated quaternion.</returns>
-        /// <remarks>The <see cref="System.Numerics.Quaternion.op_UnaryNegation" /> method defines the operation of the unary negation operator for <see cref="System.Numerics.Quaternion" /> objects.</remarks>
+        /// <remarks>The <see cref="op_UnaryNegation" /> method defines the operation of the unary negation operator for <see cref="Quaternion" /> objects.</remarks>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion operator -(Quaternion value)
         {
-            Quaternion ans;
-
-            ans.X = -value.X;
-            ans.Y = -value.Y;
-            ans.Z = -value.Z;
-            ans.W = -value.W;
-
-            return ans;
+            return Zero - value;
         }
 
         /// <summary>Adds each element in one quaternion with its corresponding element in a second quaternion.</summary>
         /// <param name="value1">The first quaternion.</param>
         /// <param name="value2">The second quaternion.</param>
         /// <returns>The quaternion that contains the summed values of <paramref name="value1" /> and <paramref name="value2" />.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion Add(Quaternion value1, Quaternion value2)
         {
@@ -349,23 +309,18 @@ namespace System.Numerics
         /// <summary>Returns the conjugate of a specified quaternion.</summary>
         /// <param name="value">The quaternion.</param>
         /// <returns>A new quaternion that is the conjugate of <see langword="value" />.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion Conjugate(Quaternion value)
         {
-            Quaternion ans;
-
-            ans.X = -value.X;
-            ans.Y = -value.Y;
-            ans.Z = -value.Z;
-            ans.W = value.W;
-
-            return ans;
+            return Multiply(value, new Vector4(-1.0f, -1.0f, -1.0f, 1.0f));
         }
 
         /// <summary>Creates a quaternion from a unit vector and an angle to rotate around the vector.</summary>
         /// <param name="axis">The unit vector to rotate around.</param>
         /// <param name="angle">The angle, in radians, to rotate around the vector.</param>
         /// <returns>The newly created quaternion.</returns>
-        /// <remarks><paramref name="axis" /> vector must be normalized before calling this method or the resulting <see cref="System.Numerics.Quaternion" /> will be incorrect.</remarks>
+        /// <remarks><paramref name="axis" /> vector must be normalized before calling this method or the resulting <see cref="Quaternion" /> will be incorrect.</remarks>
         public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
         {
             Quaternion ans;
@@ -477,38 +432,48 @@ namespace System.Numerics
             return value1 / value2;
         }
 
+        /// <summary>Divides the specified quaternion by a specified scalar value.</summary>
+        /// <param name="left">The quaternion.</param>
+        /// <param name="divisor">The scalar value.</param>
+        /// <returns>The quaternion that results from the division.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Quaternion Divide(Quaternion left, float divisor)
+        {
+            return new Quaternion(
+                left.X / divisor,
+                left.Y / divisor,
+                left.Z / divisor,
+                left.W / divisor
+            );
+        }
+
         /// <summary>Calculates the dot product of two quaternions.</summary>
         /// <param name="quaternion1">The first quaternion.</param>
         /// <param name="quaternion2">The second quaternion.</param>
         /// <returns>The dot product.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float Dot(Quaternion quaternion1, Quaternion quaternion2)
         {
-            return quaternion1.X * quaternion2.X +
-                   quaternion1.Y * quaternion2.Y +
-                   quaternion1.Z * quaternion2.Z +
-                   quaternion1.W * quaternion2.W;
+            return (quaternion1.X * quaternion2.X)
+                 + (quaternion1.Y * quaternion2.Y)
+                 + (quaternion1.Z * quaternion2.Z)
+                 + (quaternion1.W * quaternion2.W);
         }
 
         /// <summary>Returns the inverse of a quaternion.</summary>
         /// <param name="value">The quaternion.</param>
         /// <returns>The inverted quaternion.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion Inverse(Quaternion value)
         {
             //  -1   (       a              -v       )
             // q   = ( -------------   ------------- )
             //       (  a^2 + |v|^2  ,  a^2 + |v|^2  )
 
-            Quaternion ans;
-
-            float ls = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W;
-            float invNorm = 1.0f / ls;
-
-            ans.X = -value.X * invNorm;
-            ans.Y = -value.Y * invNorm;
-            ans.Z = -value.Z * invNorm;
-            ans.W = value.W * invNorm;
-
-            return ans;
+            return Divide(Conjugate(value), value.LengthSquared());
         }
 
         /// <summary>Performs a linear interpolation between two quaternions based on a value that specifies the weighting of the second quaternion.</summary>
@@ -563,10 +528,27 @@ namespace System.Numerics
             return value1 * value2;
         }
 
+        /// <summary>Returns a new quaternion whose values are the product of each pair of elements in specified quaternion and vector.</summary>
+        /// <param name="value1">The quaternion.</param>
+        /// <param name="value2">The vector.</param>
+        /// <returns>The element-wise product vector.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Quaternion Multiply(Quaternion value1, Vector4 value2)
+        {
+            return new Quaternion(
+                value1.X * value2.X,
+                value1.Y * value2.Y,
+                value1.Z * value2.Z,
+                value1.W * value2.W
+            );
+        }
+
         /// <summary>Returns the quaternion that results from scaling all the components of a specified quaternion by a scalar factor.</summary>
         /// <param name="value1">The source quaternion.</param>
         /// <param name="value2">The scalar value.</param>
         /// <returns>The scaled quaternion.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion Multiply(Quaternion value1, float value2)
         {
@@ -576,29 +558,21 @@ namespace System.Numerics
         /// <summary>Reverses the sign of each component of the quaternion.</summary>
         /// <param name="value">The quaternion to negate.</param>
         /// <returns>The negated quaternion.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion Negate(Quaternion value)
         {
             return -value;
         }
 
-        /// <summary>Divides each component of a specified <see cref="System.Numerics.Quaternion" /> by its length.</summary>
+        /// <summary>Divides each component of a specified <see cref="Quaternion" /> by its length.</summary>
         /// <param name="value">The quaternion to normalize.</param>
         /// <returns>The normalized quaternion.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion Normalize(Quaternion value)
         {
-            Quaternion ans;
-
-            float ls = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W;
-
-            float invNorm = 1.0f / MathF.Sqrt(ls);
-
-            ans.X = value.X * invNorm;
-            ans.Y = value.Y * invNorm;
-            ans.Z = value.Z * invNorm;
-            ans.W = value.W * invNorm;
-
-            return ans;
+            return Divide(value, value.Length());
         }
 
         /// <summary>Interpolates between two quaternions, using spherical linear interpolation.</summary>
@@ -654,6 +628,7 @@ namespace System.Numerics
         /// <param name="value1">The first quaternion.</param>
         /// <param name="value2">The second quaternion.</param>
         /// <returns>The quaternion containing the values that result from subtracting each element in <paramref name="value2" /> from its corresponding element in <paramref name="value1" />.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Quaternion Subtract(Quaternion value1, Quaternion value2)
         {
@@ -663,7 +638,7 @@ namespace System.Numerics
         /// <summary>Returns a value that indicates whether this instance and a specified object are equal.</summary>
         /// <param name="obj">The object to compare with the current instance.</param>
         /// <returns><see langword="true" /> if the current instance and <paramref name="obj" /> are equal; otherwise, <see langword="false" />. If <paramref name="obj" /> is <see langword="null" />, the method returns <see langword="false" />.</returns>
-        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="System.Numerics.Quaternion" /> object and the corresponding components of each matrix are equal.</remarks>
+        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="Quaternion" /> object and the corresponding components of each matrix are equal.</remarks>
         public override readonly bool Equals([NotNullWhen(true)] object? obj)
         {
             return (obj is Quaternion other) && Equals(other);
@@ -681,7 +656,7 @@ namespace System.Numerics
 
             if (Vector128.IsHardwareAccelerated)
             {
-                return Vector128.LoadUnsafe(ref Unsafe.AsRef(in X)).Equals(Vector128.LoadUnsafe(ref other.X));
+                return this.AsVector128().Equals(other.AsVector128());
             }
 
             return SoftwareFallback(in this, other);
@@ -704,6 +679,8 @@ namespace System.Numerics
 
         /// <summary>Calculates the length of the quaternion.</summary>
         /// <returns>The computed length of the quaternion.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly float Length()
         {
             float lengthSquared = LengthSquared();
@@ -712,9 +689,11 @@ namespace System.Numerics
 
         /// <summary>Calculates the squared length of the quaternion.</summary>
         /// <returns>The length squared of the quaternion.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly float LengthSquared()
         {
-            return X * X + Y * Y + Z * Z + W * W;
+            return Dot(this, this);
         }
 
         /// <summary>Returns a string that represents this quaternion.</summary>
diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs
new file mode 100644 (file)
index 0000000..5b57163
--- /dev/null
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Numerics
+{
+    public static unsafe partial class Vector
+    {
+        /// <summary>Gets the element at the specified index.</summary>
+        /// <param name="vector">The vector to get the element from.</param>
+        /// <param name="index">The index of the element to get.</param>
+        /// <returns>The value of the element at <paramref name="index" />.</returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static float GetElement(this Vector2 vector, int index)
+        {
+            if ((uint)(index) >= (uint)(Vector2.Count))
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+            }
+
+            return vector.GetElementUnsafe(index);
+        }
+
+        /// <summary>Creates a new <see cref="Vector2" /> with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given vector.</summary>
+        /// <param name="vector">The vector to get the remaining elements from.</param>
+        /// <param name="index">The index of the element to set.</param>
+        /// <param name="value">The value to set the element to.</param>
+        /// <returns>A <see cref="Vector2" /> with the value of the element at <paramref name="index" /> set to <paramref name="value" /> and the remaining elements set to the same value as that in <paramref name="vector" />.</returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
+        [Intrinsic]
+        internal static Vector2 WithElement(this Vector2 vector, int index, float value)
+        {
+            if ((uint)(index) >= (uint)(Vector2.Count))
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+            }
+
+            Vector2 result = vector;
+            result.SetElementUnsafe(index, value);
+            return result;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static float GetElementUnsafe(in this Vector2 vector, int index)
+        {
+            Debug.Assert((index >= 0) && (index < Vector2.Count));
+            ref float address = ref Unsafe.AsRef(in vector.X);
+            return Unsafe.Add(ref address, index);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static void SetElementUnsafe(ref this Vector2 vector, int index, float value)
+        {
+            Debug.Assert((index >= 0) && (index < Vector2.Count));
+            Unsafe.Add(ref vector.X, index) = value;
+        }
+    }
+}
index 6c6e054..e57dee2 100644 (file)
@@ -1,13 +1,11 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.Intrinsics;
-using System.Text;
 
 namespace System.Numerics
 {
@@ -27,7 +25,7 @@ namespace System.Numerics
 
         internal const int Count = 2;
 
-        /// <summary>Creates a new <see cref="System.Numerics.Vector2" /> object whose two elements have the same value.</summary>
+        /// <summary>Creates a new <see cref="Vector2" /> object whose two elements have the same value.</summary>
         /// <param name="value">The value to assign to both elements.</param>
         [Intrinsic]
         public Vector2(float value) : this(value, value)
@@ -35,8 +33,8 @@ namespace System.Numerics
         }
 
         /// <summary>Creates a vector whose elements have the specified values.</summary>
-        /// <param name="x">The value to assign to the <see cref="System.Numerics.Vector2.X" /> field.</param>
-        /// <param name="y">The value to assign to the <see cref="System.Numerics.Vector2.Y" /> field.</param>
+        /// <param name="x">The value to assign to the <see cref="X" /> field.</param>
+        /// <param name="y">The value to assign to the <see cref="Y" /> field.</param>
         [Intrinsic]
         public Vector2(float x, float y)
         {
@@ -76,6 +74,7 @@ namespace System.Numerics
         /// <value>The vector <c>(1,0)</c>.</value>
         public static Vector2 UnitX
         {
+            [Intrinsic]
             get => new Vector2(1.0f, 0.0f);
         }
 
@@ -83,6 +82,7 @@ namespace System.Numerics
         /// <value>The vector <c>(0,1)</c>.</value>
         public static Vector2 UnitY
         {
+            [Intrinsic]
             get => new Vector2(0.0f, 1.0f);
         }
 
@@ -92,63 +92,19 @@ namespace System.Numerics
         /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
         public float this[int index]
         {
-            get => GetElement(this, index);
-            set => this = WithElement(this, index, value);
-        }
-
-        /// <summary>Gets the element at the specified index.</summary>
-        /// <param name="vector">The vector of the element to get.</param>
-        /// <param name="index">The index of the element to get.</param>
-        /// <returns>The value of the element at <paramref name="index" />.</returns>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
-        [Intrinsic]
-        internal static float GetElement(Vector2 vector, int index)
-        {
-            if ((uint)index >= Count)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
-            }
-
-            return GetElementUnsafe(ref vector, index);
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static float GetElementUnsafe(ref Vector2 vector, int index)
-        {
-            Debug.Assert(index is >= 0 and < Count);
-            return Unsafe.Add(ref Unsafe.As<Vector2, float>(ref vector), index);
-        }
-
-        /// <summary>Sets the element at the specified index.</summary>
-        /// <param name="vector">The vector of the element to get.</param>
-        /// <param name="index">The index of the element to set.</param>
-        /// <param name="value">The value of the element to set.</param>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
-        [Intrinsic]
-        internal static Vector2 WithElement(Vector2 vector, int index, float value)
-        {
-            if ((uint)index >= Count)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
-            }
-
-            Vector2 result = vector;
-            SetElementUnsafe(ref result, index, value);
-            return result;
-        }
+            [Intrinsic]
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => this.GetElement(index);
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static void SetElementUnsafe(ref Vector2 vector, int index, float value)
-        {
-            Debug.Assert(index is >= 0 and < Count);
-            Unsafe.Add(ref Unsafe.As<Vector2, float>(ref vector), index) = value;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => this = this.WithElement(index, value);
         }
 
         /// <summary>Adds two vectors together.</summary>
         /// <param name="left">The first vector to add.</param>
         /// <param name="right">The second vector to add.</param>
         /// <returns>The summed vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector2.op_Addition" /> method defines the addition operation for <see cref="System.Numerics.Vector2" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Addition" /> method defines the addition operation for <see cref="Vector2" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 operator +(Vector2 left, Vector2 right)
@@ -163,7 +119,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The vector that results from dividing <paramref name="left" /> by <paramref name="right" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector2.op_Division" /> method defines the division operation for <see cref="System.Numerics.Vector2" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector2.op_Division" /> method defines the division operation for <see cref="Vector2" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 operator /(Vector2 left, Vector2 right)
@@ -178,7 +134,8 @@ namespace System.Numerics
         /// <param name="value1">The vector.</param>
         /// <param name="value2">The scalar value.</param>
         /// <returns>The result of the division.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector2.op_Division" /> method defines the division operation for <see cref="System.Numerics.Vector2" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector2.op_Division" /> method defines the division operation for <see cref="Vector2" /> objects.</remarks>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 operator /(Vector2 value1, float value2)
         {
@@ -189,7 +146,7 @@ namespace System.Numerics
         /// <param name="left">The first vector to compare.</param>
         /// <param name="right">The second vector to compare.</param>
         /// <returns><see langword="true" /> if <paramref name="left" /> and <paramref name="right" /> are equal; otherwise, <see langword="false" />.</returns>
-        /// <remarks>Two <see cref="System.Numerics.Vector2" /> objects are equal if each value in <paramref name="left" /> is equal to the corresponding value in <paramref name="right" />.</remarks>
+        /// <remarks>Two <see cref="Vector2" /> objects are equal if each value in <paramref name="left" /> is equal to the corresponding value in <paramref name="right" />.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool operator ==(Vector2 left, Vector2 right)
@@ -213,7 +170,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The element-wise product vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector2.op_Multiply" /> method defines the multiplication operation for <see cref="System.Numerics.Vector2" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector2.op_Multiply" /> method defines the multiplication operation for <see cref="Vector2" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 operator *(Vector2 left, Vector2 right)
@@ -228,7 +185,7 @@ namespace System.Numerics
         /// <param name="left">The vector.</param>
         /// <param name="right">The scalar value.</param>
         /// <returns>The scaled vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector2.op_Multiply" /> method defines the multiplication operation for <see cref="System.Numerics.Vector2" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector2.op_Multiply" /> method defines the multiplication operation for <see cref="Vector2" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 operator *(Vector2 left, float right)
@@ -240,7 +197,7 @@ namespace System.Numerics
         /// <param name="left">The vector.</param>
         /// <param name="right">The scalar value.</param>
         /// <returns>The scaled vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector2.op_Multiply" /> method defines the multiplication operation for <see cref="System.Numerics.Vector2" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector2.op_Multiply" /> method defines the multiplication operation for <see cref="Vector2" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 operator *(float left, Vector2 right)
@@ -252,7 +209,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The vector that results from subtracting <paramref name="right" /> from <paramref name="left" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector2.op_Subtraction" /> method defines the subtraction operation for <see cref="System.Numerics.Vector2" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Subtraction" /> method defines the subtraction operation for <see cref="Vector2" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 operator -(Vector2 left, Vector2 right)
@@ -266,7 +223,7 @@ namespace System.Numerics
         /// <summary>Negates the specified vector.</summary>
         /// <param name="value">The vector to negate.</param>
         /// <returns>The negated vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector2.op_UnaryNegation" /> method defines the unary negation operation for <see cref="System.Numerics.Vector2" /> objects.</remarks>
+        /// <remarks>The <see cref="op_UnaryNegation" /> method defines the unary negation operation for <see cref="Vector2" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 operator -(Vector2 value)
@@ -291,6 +248,7 @@ namespace System.Numerics
         /// <param name="left">The first vector to add.</param>
         /// <param name="right">The second vector to add.</param>
         /// <returns>The summed vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Add(Vector2 left, Vector2 right)
         {
@@ -302,6 +260,7 @@ namespace System.Numerics
         /// <param name="min">The minimum value.</param>
         /// <param name="max">The maximum value.</param>
         /// <returns>The restricted vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max)
         {
@@ -313,6 +272,7 @@ namespace System.Numerics
         /// <param name="value1">The first point.</param>
         /// <param name="value2">The second point.</param>
         /// <returns>The distance.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float Distance(Vector2 value1, Vector2 value2)
         {
@@ -324,6 +284,7 @@ namespace System.Numerics
         /// <param name="value1">The first point.</param>
         /// <param name="value2">The second point.</param>
         /// <returns>The distance squared.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float DistanceSquared(Vector2 value1, Vector2 value2)
         {
@@ -335,6 +296,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The vector resulting from the division.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Divide(Vector2 left, Vector2 right)
         {
@@ -345,6 +307,7 @@ namespace System.Numerics
         /// <param name="left">The vector.</param>
         /// <param name="divisor">The scalar value.</param>
         /// <returns>The vector that results from the division.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Divide(Vector2 left, float divisor)
         {
@@ -371,6 +334,7 @@ namespace System.Numerics
         /// <remarks><format type="text/markdown"><![CDATA[
         /// The behavior of this method changed in .NET 5.0. For more information, see [Behavior change for Vector2.Lerp and Vector4.Lerp](/dotnet/core/compatibility/3.1-5.0#behavior-change-for-vector2lerp-and-vector4lerp).
         /// ]]></format></remarks>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount)
         {
@@ -409,6 +373,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The element-wise product vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Multiply(Vector2 left, Vector2 right)
         {
@@ -419,6 +384,7 @@ namespace System.Numerics
         /// <param name="left">The vector to multiply.</param>
         /// <param name="right">The scalar value.</param>
         /// <returns>The scaled vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Multiply(Vector2 left, float right)
         {
@@ -429,6 +395,7 @@ namespace System.Numerics
         /// <param name="left">The scaled value.</param>
         /// <param name="right">The vector.</param>
         /// <returns>The scaled vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Multiply(float left, Vector2 right)
         {
@@ -438,6 +405,7 @@ namespace System.Numerics
         /// <summary>Negates a specified vector.</summary>
         /// <param name="value">The vector to negate.</param>
         /// <returns>The negated vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Negate(Vector2 value)
         {
@@ -447,6 +415,7 @@ namespace System.Numerics
         /// <summary>Returns a vector with the same direction as the specified vector, but with a length of one.</summary>
         /// <param name="value">The vector to normalize.</param>
         /// <returns>The normalized vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Normalize(Vector2 value)
         {
@@ -461,7 +430,7 @@ namespace System.Numerics
         public static Vector2 Reflect(Vector2 vector, Vector2 normal)
         {
             float dot = Dot(vector, normal);
-            return vector - (2 * dot * normal);
+            return vector - (2.0f * (dot * normal));
         }
 
         /// <summary>Returns a vector whose elements are the square root of each of a specified vector's elements.</summary>
@@ -481,6 +450,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The difference vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Subtract(Vector2 left, Vector2 right)
         {
@@ -494,10 +464,18 @@ namespace System.Numerics
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Transform(Vector2 position, Matrix3x2 matrix)
         {
-            return new Vector2(
-                (position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M31,
-                (position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M32
-            );
+            return Transform(position, in matrix.AsImpl());
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Vector2 Transform(Vector2 position, in Matrix3x2.Impl matrix)
+        {
+            Vector2 result = matrix.X * position.X;
+
+            result += matrix.Y * position.Y;
+            result += matrix.Z;
+
+            return result;
         }
 
         /// <summary>Transforms a vector by a specified 4x4 matrix.</summary>
@@ -507,10 +485,7 @@ namespace System.Numerics
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Transform(Vector2 position, Matrix4x4 matrix)
         {
-            return new Vector2(
-                (position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M41,
-                (position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M42
-            );
+            return Vector4.Transform(position, in matrix.AsImpl()).AsVector128().AsVector2();
         }
 
         /// <summary>Transforms a vector by the specified Quaternion rotation value.</summary>
@@ -543,10 +518,17 @@ namespace System.Numerics
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 TransformNormal(Vector2 normal, Matrix3x2 matrix)
         {
-            return new Vector2(
-                (normal.X * matrix.M11) + (normal.Y * matrix.M21),
-                (normal.X * matrix.M12) + (normal.Y * matrix.M22)
-            );
+            return TransformNormal(normal, in matrix.AsImpl());
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Vector2 TransformNormal(Vector2 normal, in Matrix3x2.Impl matrix)
+        {
+            Vector2 result = matrix.X * normal.X;
+
+            result += matrix.Y * normal.Y;
+
+            return result;
         }
 
         /// <summary>Transforms a vector normal by the given 4x4 matrix.</summary>
@@ -556,18 +538,25 @@ namespace System.Numerics
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 TransformNormal(Vector2 normal, Matrix4x4 matrix)
         {
-            return new Vector2(
-                (normal.X * matrix.M11) + (normal.Y * matrix.M21),
-                (normal.X * matrix.M12) + (normal.Y * matrix.M22)
-            );
+            return TransformNormal(normal, in matrix.AsImpl());
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Vector2 TransformNormal(Vector2 normal, in Matrix4x4.Impl matrix)
+        {
+            Vector4 result = matrix.X * normal.X;
+
+            result += matrix.Y * normal.Y;
+
+            return result.AsVector128().AsVector2();
         }
 
         /// <summary>Copies the elements of the vector to a specified array.</summary>
         /// <param name="array">The destination array.</param>
         /// <remarks><paramref name="array" /> must have at least two elements. The method copies the vector's elements starting at index 0.</remarks>
-        /// <exception cref="System.NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
-        /// <exception cref="System.ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
-        /// <exception cref="System.RankException"><paramref name="array" /> is multidimensional.</exception>
+        /// <exception cref="NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
+        /// <exception cref="ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
+        /// <exception cref="RankException"><paramref name="array" /> is multidimensional.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly void CopyTo(float[] array)
         {
@@ -585,12 +574,12 @@ namespace System.Numerics
         /// <param name="array">The destination array.</param>
         /// <param name="index">The index at which to copy the first element of the vector.</param>
         /// <remarks><paramref name="array" /> must have a sufficient number of elements to accommodate the two vector elements. In other words, elements <paramref name="index" /> and <paramref name="index" /> + 1 must already exist in <paramref name="array" />.</remarks>
-        /// <exception cref="System.NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
-        /// <exception cref="System.ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
-        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="index" /> is less than zero.
+        /// <exception cref="NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
+        /// <exception cref="ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> is less than zero.
         /// -or-
         /// <paramref name="index" /> is greater than or equal to the array length.</exception>
-        /// <exception cref="System.RankException"><paramref name="array" /> is multidimensional.</exception>
+        /// <exception cref="RankException"><paramref name="array" /> is multidimensional.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly void CopyTo(float[] array, int index)
         {
@@ -611,7 +600,7 @@ namespace System.Numerics
 
         /// <summary>Copies the vector to the given <see cref="Span{T}" />.The length of the destination span must be at least 2.</summary>
         /// <param name="destination">The destination span which the values are copied into.</param>
-        /// <exception cref="System.ArgumentException">If number of elements in source vector is greater than those available in destination span.</exception>
+        /// <exception cref="ArgumentException">If number of elements in source vector is greater than those available in destination span.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly void CopyTo(Span<float> destination)
         {
@@ -641,7 +630,7 @@ namespace System.Numerics
         /// <summary>Returns a value that indicates whether this instance and a specified object are equal.</summary>
         /// <param name="obj">The object to compare with the current instance.</param>
         /// <returns><see langword="true" /> if the current instance and <paramref name="obj" /> are equal; otherwise, <see langword="false" />. If <paramref name="obj" /> is <see langword="null" />, the method returns <see langword="false" />.</returns>
-        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="System.Numerics.Vector2" /> object and their <see cref="System.Numerics.Vector2.X" /> and <see cref="System.Numerics.Vector2.Y" /> elements are equal.</remarks>
+        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="Vector2" /> object and their <see cref="X" /> and <see cref="Y" /> elements are equal.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public override readonly bool Equals([NotNullWhen(true)] object? obj)
         {
@@ -651,7 +640,7 @@ namespace System.Numerics
         /// <summary>Returns a value that indicates whether this instance and another vector are equal.</summary>
         /// <param name="other">The other vector.</param>
         /// <returns><see langword="true" /> if the two vectors are equal; otherwise, <see langword="false" />.</returns>
-        /// <remarks>Two vectors are equal if their <see cref="System.Numerics.Vector2.X" /> and <see cref="System.Numerics.Vector2.Y" /> elements are equal.</remarks>
+        /// <remarks>Two vectors are equal if their <see cref="X" /> and <see cref="Y" /> elements are equal.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly bool Equals(Vector2 other)
         {
@@ -685,7 +674,8 @@ namespace System.Numerics
 
         /// <summary>Returns the length of the vector.</summary>
         /// <returns>The vector's length.</returns>
-        /// <altmember cref="System.Numerics.Vector2.LengthSquared"/>
+        /// <altmember cref="LengthSquared"/>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly float Length()
         {
@@ -695,8 +685,9 @@ namespace System.Numerics
 
         /// <summary>Returns the length of the vector squared.</summary>
         /// <returns>The vector's length squared.</returns>
-        /// <remarks>This operation offers better performance than a call to the <see cref="System.Numerics.Vector2.Length" /> method.</remarks>
-        /// <altmember cref="System.Numerics.Vector2.Length"/>
+        /// <remarks>This operation offers better performance than a call to the <see cref="Length" /> method.</remarks>
+        /// <altmember cref="Length"/>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly float LengthSquared()
         {
@@ -705,7 +696,7 @@ namespace System.Numerics
 
         /// <summary>Returns the string representation of the current instance using default formatting.</summary>
         /// <returns>The string representation of the current instance.</returns>
-        /// <remarks>This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="System.Globalization.NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
+        /// <remarks>This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
         public override readonly string ToString()
         {
             return ToString("G", CultureInfo.CurrentCulture);
@@ -714,7 +705,7 @@ namespace System.Numerics
         /// <summary>Returns the string representation of the current instance using the specified format string to format individual elements.</summary>
         /// <param name="format">A standard or custom numeric format string that defines the format of individual elements.</param>
         /// <returns>The string representation of the current instance.</returns>
-        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and the current culture's formatting conventions. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="System.Globalization.NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
+        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and the current culture's formatting conventions. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
         /// <related type="Article" href="/dotnet/standard/base-types/standard-numeric-format-strings">Standard Numeric Format Strings</related>
         /// <related type="Article" href="/dotnet/standard/base-types/custom-numeric-format-strings">Custom Numeric Format Strings</related>
         public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format)
@@ -726,7 +717,7 @@ namespace System.Numerics
         /// <param name="format">A standard or custom numeric format string that defines the format of individual elements.</param>
         /// <param name="formatProvider">A format provider that supplies culture-specific formatting information.</param>
         /// <returns>The string representation of the current instance.</returns>
-        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and <paramref name="formatProvider" />. The "&lt;" and "&gt;" characters are used to begin and end the string, and the format provider's <see cref="System.Globalization.NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
+        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and <paramref name="formatProvider" />. The "&lt;" and "&gt;" characters are used to begin and end the string, and the format provider's <see cref="NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
         /// <related type="Article" href="/dotnet/standard/base-types/custom-numeric-format-strings">Custom Numeric Format Strings</related>
         /// <related type="Article" href="/dotnet/standard/base-types/standard-numeric-format-strings">Standard Numeric Format Strings</related>
         public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? formatProvider)
diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs
new file mode 100644 (file)
index 0000000..2eb006e
--- /dev/null
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Numerics
+{
+    public static unsafe partial class Vector
+    {
+        /// <summary>Gets the element at the specified index.</summary>
+        /// <param name="vector">The vector to get the element from.</param>
+        /// <param name="index">The index of the element to get.</param>
+        /// <returns>The value of the element at <paramref name="index" />.</returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static float GetElement(this Vector3 vector, int index)
+        {
+            if ((uint)(index) >= (uint)(Vector3.Count))
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+            }
+
+            return vector.GetElementUnsafe(index);
+        }
+
+        /// <summary>Creates a new <see cref="Vector3" /> with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given vector.</summary>
+        /// <param name="vector">The vector to get the remaining elements from.</param>
+        /// <param name="index">The index of the element to set.</param>
+        /// <param name="value">The value to set the element to.</param>
+        /// <returns>A <see cref="Vector3" /> with the value of the element at <paramref name="index" /> set to <paramref name="value" /> and the remaining elements set to the same value as that in <paramref name="vector" />.</returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
+        [Intrinsic]
+        internal static Vector3 WithElement(this Vector3 vector, int index, float value)
+        {
+            if ((uint)(index) >= (uint)(Vector3.Count))
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+            }
+
+            Vector3 result = vector;
+            result.SetElementUnsafe(index, value);
+            return result;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static float GetElementUnsafe(in this Vector3 vector, int index)
+        {
+            Debug.Assert((index >= 0) && (index < Vector3.Count));
+            ref float address = ref Unsafe.AsRef(in vector.X);
+            return Unsafe.Add(ref address, index);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static void SetElementUnsafe(ref this Vector3 vector, int index, float value)
+        {
+            Debug.Assert((index >= 0) && (index < Vector3.Count));
+            Unsafe.Add(ref vector.X, index) = value;
+        }
+    }
+}
index 2773bbc..c4739ce 100644 (file)
@@ -1,13 +1,11 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.Intrinsics;
-using System.Text;
 
 namespace System.Numerics
 {
@@ -30,25 +28,25 @@ namespace System.Numerics
 
         internal const int Count = 3;
 
-        /// <summary>Creates a new <see cref="System.Numerics.Vector3" /> object whose three elements have the same value.</summary>
+        /// <summary>Creates a new <see cref="Vector3" /> object whose three elements have the same value.</summary>
         /// <param name="value">The value to assign to all three elements.</param>
         [Intrinsic]
         public Vector3(float value) : this(value, value, value)
         {
         }
 
-        /// <summary>Creates a   new <see cref="System.Numerics.Vector3" /> object from the specified <see cref="System.Numerics.Vector2" /> object and the specified value.</summary>
+        /// <summary>Creates a   new <see cref="Vector3" /> object from the specified <see cref="Vector2" /> object and the specified value.</summary>
         /// <param name="value">The vector with two elements.</param>
-        /// <param name="z">The additional value to assign to the <see cref="System.Numerics.Vector3.Z" /> field.</param>
+        /// <param name="z">The additional value to assign to the <see cref="Z" /> field.</param>
         [Intrinsic]
         public Vector3(Vector2 value, float z) : this(value.X, value.Y, z)
         {
         }
 
         /// <summary>Creates a vector whose elements have the specified values.</summary>
-        /// <param name="x">The value to assign to the <see cref="System.Numerics.Vector3.X" /> field.</param>
-        /// <param name="y">The value to assign to the <see cref="System.Numerics.Vector3.Y" /> field.</param>
-        /// <param name="z">The value to assign to the <see cref="System.Numerics.Vector3.Z" /> field.</param>
+        /// <param name="x">The value to assign to the <see cref="X" /> field.</param>
+        /// <param name="y">The value to assign to the <see cref="Y" /> field.</param>
+        /// <param name="z">The value to assign to the <see cref="Z" /> field.</param>
         [Intrinsic]
         public Vector3(float x, float y, float z)
         {
@@ -89,6 +87,7 @@ namespace System.Numerics
         /// <value>The vector <c>(1,0,0)</c>.</value>
         public static Vector3 UnitX
         {
+            [Intrinsic]
             get => new Vector3(1.0f, 0.0f, 0.0f);
         }
 
@@ -96,6 +95,7 @@ namespace System.Numerics
         /// <value>The vector <c>(0,1,0)</c>.</value>
         public static Vector3 UnitY
         {
+            [Intrinsic]
             get => new Vector3(0.0f, 1.0f, 0.0f);
         }
 
@@ -103,6 +103,7 @@ namespace System.Numerics
         /// <value>The vector <c>(0,0,1)</c>.</value>
         public static Vector3 UnitZ
         {
+            [Intrinsic]
             get => new Vector3(0.0f, 0.0f, 1.0f);
         }
 
@@ -112,63 +113,19 @@ namespace System.Numerics
         /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
         public float this[int index]
         {
-            get => GetElement(this, index);
-            set => this = WithElement(this, index, value);
-        }
-
-        /// <summary>Gets the element at the specified index.</summary>
-        /// <param name="vector">The vector of the element to get.</param>
-        /// <param name="index">The index of the element to get.</param>
-        /// <returns>The value of the element at <paramref name="index" />.</returns>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
-        [Intrinsic]
-        internal static float GetElement(Vector3 vector, int index)
-        {
-            if ((uint)index >= Count)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
-            }
-
-            return GetElementUnsafe(ref vector, index);
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static float GetElementUnsafe(ref Vector3 vector, int index)
-        {
-            Debug.Assert(index is >= 0 and < Count);
-            return Unsafe.Add(ref Unsafe.As<Vector3, float>(ref vector), index);
-        }
-
-        /// <summary>Sets the element at the specified index.</summary>
-        /// <param name="vector">The vector of the element to get.</param>
-        /// <param name="index">The index of the element to set.</param>
-        /// <param name="value">The value of the element to set.</param>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
-        [Intrinsic]
-        internal static Vector3 WithElement(Vector3 vector, int index, float value)
-        {
-            if ((uint)index >= Count)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
-            }
-
-            Vector3 result = vector;
-            SetElementUnsafe(ref result, index, value);
-            return result;
-        }
+            [Intrinsic]
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => this.GetElement(index);
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static void SetElementUnsafe(ref Vector3 vector, int index, float value)
-        {
-            Debug.Assert(index is >= 0 and < Count);
-            Unsafe.Add(ref Unsafe.As<Vector3, float>(ref vector), index) = value;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => this = this.WithElement(index, value);
         }
 
         /// <summary>Adds two vectors together.</summary>
         /// <param name="left">The first vector to add.</param>
         /// <param name="right">The second vector to add.</param>
         /// <returns>The summed vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector3.op_Addition" /> method defines the addition operation for <see cref="System.Numerics.Vector3" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Addition" /> method defines the addition operation for <see cref="Vector3" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 operator +(Vector3 left, Vector3 right)
@@ -184,7 +141,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The vector that results from dividing <paramref name="left" /> by <paramref name="right" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector3.op_Division" /> method defines the division operation for <see cref="System.Numerics.Vector3" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector3.op_Division" /> method defines the division operation for <see cref="Vector3" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 operator /(Vector3 left, Vector3 right)
@@ -200,7 +157,8 @@ namespace System.Numerics
         /// <param name="value1">The vector.</param>
         /// <param name="value2">The scalar value.</param>
         /// <returns>The result of the division.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector3.op_Division" /> method defines the division operation for <see cref="System.Numerics.Vector3" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector3.op_Division" /> method defines the division operation for <see cref="Vector3" /> objects.</remarks>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 operator /(Vector3 value1, float value2)
         {
@@ -211,7 +169,7 @@ namespace System.Numerics
         /// <param name="left">The first vector to compare.</param>
         /// <param name="right">The second vector to compare.</param>
         /// <returns><see langword="true" /> if <paramref name="left" /> and <paramref name="right" /> are equal; otherwise, <see langword="false" />.</returns>
-        /// <remarks>Two <see cref="System.Numerics.Vector3" /> objects are equal if each element in <paramref name="left" /> is equal to the corresponding element in <paramref name="right" />.</remarks>
+        /// <remarks>Two <see cref="Vector3" /> objects are equal if each element in <paramref name="left" /> is equal to the corresponding element in <paramref name="right" />.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool operator ==(Vector3 left, Vector3 right)
@@ -236,7 +194,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The element-wise product vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector3.op_Multiply" /> method defines the multiplication operation for <see cref="System.Numerics.Vector3" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector3.op_Multiply" /> method defines the multiplication operation for <see cref="Vector3" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 operator *(Vector3 left, Vector3 right)
@@ -252,7 +210,7 @@ namespace System.Numerics
         /// <param name="left">The vector.</param>
         /// <param name="right">The scalar value.</param>
         /// <returns>The scaled vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector3.op_Multiply" /> method defines the multiplication operation for <see cref="System.Numerics.Vector3" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector3.op_Multiply" /> method defines the multiplication operation for <see cref="Vector3" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 operator *(Vector3 left, float right)
@@ -264,7 +222,7 @@ namespace System.Numerics
         /// <param name="left">The vector.</param>
         /// <param name="right">The scalar value.</param>
         /// <returns>The scaled vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector3.op_Multiply" /> method defines the multiplication operation for <see cref="System.Numerics.Vector3" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector3.op_Multiply" /> method defines the multiplication operation for <see cref="Vector3" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 operator *(float left, Vector3 right)
@@ -276,7 +234,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The vector that results from subtracting <paramref name="right" /> from <paramref name="left" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector3.op_Subtraction" /> method defines the subtraction operation for <see cref="System.Numerics.Vector3" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Subtraction" /> method defines the subtraction operation for <see cref="Vector3" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 operator -(Vector3 left, Vector3 right)
@@ -291,7 +249,7 @@ namespace System.Numerics
         /// <summary>Negates the specified vector.</summary>
         /// <param name="value">The vector to negate.</param>
         /// <returns>The negated vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector3.op_UnaryNegation" /> method defines the unary negation operation for <see cref="System.Numerics.Vector3" /> objects.</remarks>
+        /// <remarks>The <see cref="op_UnaryNegation" /> method defines the unary negation operation for <see cref="Vector3" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 operator -(Vector3 value)
@@ -317,6 +275,7 @@ namespace System.Numerics
         /// <param name="left">The first vector to add.</param>
         /// <param name="right">The second vector to add.</param>
         /// <returns>The summed vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Add(Vector3 left, Vector3 right)
         {
@@ -328,6 +287,7 @@ namespace System.Numerics
         /// <param name="min">The minimum value.</param>
         /// <param name="max">The maximum value.</param>
         /// <returns>The restricted vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max)
         {
@@ -353,6 +313,7 @@ namespace System.Numerics
         /// <param name="value1">The first point.</param>
         /// <param name="value2">The second point.</param>
         /// <returns>The distance.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float Distance(Vector3 value1, Vector3 value2)
         {
@@ -364,6 +325,7 @@ namespace System.Numerics
         /// <param name="value1">The first point.</param>
         /// <param name="value2">The second point.</param>
         /// <returns>The distance squared.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float DistanceSquared(Vector3 value1, Vector3 value2)
         {
@@ -375,6 +337,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The vector resulting from the division.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Divide(Vector3 left, Vector3 right)
         {
@@ -385,6 +348,7 @@ namespace System.Numerics
         /// <param name="left">The vector.</param>
         /// <param name="divisor">The scalar value.</param>
         /// <returns>The vector that results from the division.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Divide(Vector3 left, float divisor)
         {
@@ -409,10 +373,11 @@ namespace System.Numerics
         /// <param name="value2">The second vector.</param>
         /// <param name="amount">A value between 0 and 1 that indicates the weight of <paramref name="value2" />.</param>
         /// <returns>The interpolated vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount)
         {
-            return (value1 * (1f - amount)) + (value2 * amount);
+            return (value1 * (1.0f - amount)) + (value2 * amount);
         }
 
         /// <summary>Returns a vector whose elements are the maximum of each of the pairs of elements in two specified vectors.</summary>
@@ -449,6 +414,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The element-wise product vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Multiply(Vector3 left, Vector3 right)
         {
@@ -459,6 +425,7 @@ namespace System.Numerics
         /// <param name="left">The vector to multiply.</param>
         /// <param name="right">The scalar value.</param>
         /// <returns>The scaled vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Multiply(Vector3 left, float right)
         {
@@ -469,6 +436,7 @@ namespace System.Numerics
         /// <param name="left">The scaled value.</param>
         /// <param name="right">The vector.</param>
         /// <returns>The scaled vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Multiply(float left, Vector3 right)
         {
@@ -478,6 +446,7 @@ namespace System.Numerics
         /// <summary>Negates a specified vector.</summary>
         /// <param name="value">The vector to negate.</param>
         /// <returns>The negated vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Negate(Vector3 value)
         {
@@ -487,6 +456,7 @@ namespace System.Numerics
         /// <summary>Returns a vector with the same direction as the specified vector, but with a length of one.</summary>
         /// <param name="value">The vector to normalize.</param>
         /// <returns>The normalized vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Normalize(Vector3 value)
         {
@@ -501,7 +471,7 @@ namespace System.Numerics
         public static Vector3 Reflect(Vector3 vector, Vector3 normal)
         {
             float dot = Dot(vector, normal);
-            return vector - (2 * dot * normal);
+            return vector - (2.0f * (dot * normal));
         }
 
         /// <summary>Returns a vector whose elements are the square root of each of a specified vector's elements.</summary>
@@ -522,6 +492,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The difference vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Subtract(Vector3 left, Vector3 right)
         {
@@ -535,11 +506,7 @@ namespace System.Numerics
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 Transform(Vector3 position, Matrix4x4 matrix)
         {
-            return new Vector3(
-                (position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41,
-                (position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42,
-                (position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43
-            );
+            return Vector4.Transform(position, in matrix.AsImpl()).AsVector128().AsVector3();
         }
 
         /// <summary>Transforms a vector by the specified Quaternion rotation value.</summary>
@@ -577,19 +544,26 @@ namespace System.Numerics
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector3 TransformNormal(Vector3 normal, Matrix4x4 matrix)
         {
-            return new Vector3(
-                (normal.X * matrix.M11) + (normal.Y * matrix.M21) + (normal.Z * matrix.M31),
-                (normal.X * matrix.M12) + (normal.Y * matrix.M22) + (normal.Z * matrix.M32),
-                (normal.X * matrix.M13) + (normal.Y * matrix.M23) + (normal.Z * matrix.M33)
-            );
+            return TransformNormal(normal, in matrix.AsImpl());
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Vector3 TransformNormal(Vector3 normal, in Matrix4x4.Impl matrix)
+        {
+            Vector4 result = matrix.X * normal.X;
+
+            result += matrix.Y * normal.Y;
+            result += matrix.Z * normal.Z;
+
+            return result.AsVector128().AsVector3();
         }
 
         /// <summary>Copies the elements of the vector to a specified array.</summary>
         /// <param name="array">The destination array.</param>
         /// <remarks><paramref name="array" /> must have at least three elements. The method copies the vector's elements starting at index 0.</remarks>
-        /// <exception cref="System.NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
-        /// <exception cref="System.ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
-        /// <exception cref="System.RankException"><paramref name="array" /> is multidimensional.</exception>
+        /// <exception cref="NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
+        /// <exception cref="ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
+        /// <exception cref="RankException"><paramref name="array" /> is multidimensional.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly void CopyTo(float[] array)
         {
@@ -607,12 +581,12 @@ namespace System.Numerics
         /// <param name="array">The destination array.</param>
         /// <param name="index">The index at which to copy the first element of the vector.</param>
         /// <remarks><paramref name="array" /> must have a sufficient number of elements to accommodate the three vector elements. In other words, elements <paramref name="index" />, <paramref name="index" /> + 1, and <paramref name="index" /> + 2 must already exist in <paramref name="array" />.</remarks>
-        /// <exception cref="System.NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
-        /// <exception cref="System.ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
-        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="index" /> is less than zero.
+        /// <exception cref="NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
+        /// <exception cref="ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> is less than zero.
         /// -or-
         /// <paramref name="index" /> is greater than or equal to the array length.</exception>
-        /// <exception cref="System.RankException"><paramref name="array" /> is multidimensional.</exception>
+        /// <exception cref="RankException"><paramref name="array" /> is multidimensional.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly void CopyTo(float[] array, int index)
         {
@@ -633,7 +607,7 @@ namespace System.Numerics
 
         /// <summary>Copies the vector to the given <see cref="Span{T}" />. The length of the destination span must be at least 3.</summary>
         /// <param name="destination">The destination span which the values are copied into.</param>
-        /// <exception cref="System.ArgumentException">If number of elements in source vector is greater than those available in destination span.</exception>
+        /// <exception cref="ArgumentException">If number of elements in source vector is greater than those available in destination span.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly void CopyTo(Span<float> destination)
         {
@@ -663,7 +637,7 @@ namespace System.Numerics
         /// <summary>Returns a value that indicates whether this instance and a specified object are equal.</summary>
         /// <param name="obj">The object to compare with the current instance.</param>
         /// <returns><see langword="true" /> if the current instance and <paramref name="obj" /> are equal; otherwise, <see langword="false" />. If <paramref name="obj" /> is <see langword="null" />, the method returns <see langword="false" />.</returns>
-        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="System.Numerics.Vector3" /> object and their corresponding elements are equal.</remarks>
+        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="Vector3" /> object and their corresponding elements are equal.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public override readonly bool Equals([NotNullWhen(true)] object? obj)
         {
@@ -673,7 +647,7 @@ namespace System.Numerics
         /// <summary>Returns a value that indicates whether this instance and another vector are equal.</summary>
         /// <param name="other">The other vector.</param>
         /// <returns><see langword="true" /> if the two vectors are equal; otherwise, <see langword="false" />.</returns>
-        /// <remarks>Two vectors are equal if their <see cref="System.Numerics.Vector3.X" />, <see cref="System.Numerics.Vector3.Y" />, and <see cref="System.Numerics.Vector3.Z" /> elements are equal.</remarks>
+        /// <remarks>Two vectors are equal if their <see cref="X" />, <see cref="Y" />, and <see cref="Z" /> elements are equal.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly bool Equals(Vector3 other)
         {
@@ -704,7 +678,8 @@ namespace System.Numerics
 
         /// <summary>Returns the length of this vector object.</summary>
         /// <returns>The vector's length.</returns>
-        /// <altmember cref="System.Numerics.Vector3.LengthSquared"/>
+        /// <altmember cref="LengthSquared"/>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly float Length()
         {
@@ -714,8 +689,9 @@ namespace System.Numerics
 
         /// <summary>Returns the length of the vector squared.</summary>
         /// <returns>The vector's length squared.</returns>
-        /// <remarks>This operation offers better performance than a call to the <see cref="System.Numerics.Vector3.Length" /> method.</remarks>
-        /// <altmember cref="System.Numerics.Vector3.Length"/>
+        /// <remarks>This operation offers better performance than a call to the <see cref="Length" /> method.</remarks>
+        /// <altmember cref="Length"/>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly float LengthSquared()
         {
@@ -724,7 +700,7 @@ namespace System.Numerics
 
         /// <summary>Returns the string representation of the current instance using default formatting.</summary>
         /// <returns>The string representation of the current instance.</returns>
-        /// <remarks>This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="System.Globalization.NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
+        /// <remarks>This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
         public override readonly string ToString()
         {
             return ToString("G", CultureInfo.CurrentCulture);
@@ -733,7 +709,7 @@ namespace System.Numerics
         /// <summary>Returns the string representation of the current instance using the specified format string to format individual elements.</summary>
         /// <param name="format">A standard or custom numeric format string that defines the format of individual elements.</param>
         /// <returns>The string representation of the current instance.</returns>
-        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and the current culture's formatting conventions. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="System.Globalization.NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
+        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and the current culture's formatting conventions. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
         /// <related type="Article" href="/dotnet/standard/base-types/standard-numeric-format-strings">Standard Numeric Format Strings</related>
         /// <related type="Article" href="/dotnet/standard/base-types/custom-numeric-format-strings">Custom Numeric Format Strings</related>
         public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format)
@@ -745,7 +721,7 @@ namespace System.Numerics
         /// <param name="format">A standard or custom numeric format string that defines the format of individual elements.</param>
         /// <param name="formatProvider">A format provider that supplies culture-specific formatting information.</param>
         /// <returns>The string representation of the current instance.</returns>
-        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and <paramref name="formatProvider" />. The "&lt;" and "&gt;" characters are used to begin and end the string, and the format provider's <see cref="System.Globalization.NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
+        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and <paramref name="formatProvider" />. The "&lt;" and "&gt;" characters are used to begin and end the string, and the format provider's <see cref="NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
         /// <related type="Article" href="/dotnet/standard/base-types/standard-numeric-format-strings">Standard Numeric Format Strings</related>
         /// <related type="Article" href="/dotnet/standard/base-types/custom-numeric-format-strings">Custom Numeric Format Strings</related>
         public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? formatProvider)
diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs
new file mode 100644 (file)
index 0000000..143d003
--- /dev/null
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Numerics
+{
+    public static unsafe partial class Vector
+    {
+        /// <summary>Gets the element at the specified index.</summary>
+        /// <param name="vector">The vector to get the element from.</param>
+        /// <param name="index">The index of the element to get.</param>
+        /// <returns>The value of the element at <paramref name="index" />.</returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static float GetElement(this Vector4 vector, int index)
+        {
+            if ((uint)(index) >= (uint)(Vector4.Count))
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+            }
+
+            return vector.GetElementUnsafe(index);
+        }
+
+        /// <summary>Creates a new <see cref="Vector4" /> with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given vector.</summary>
+        /// <param name="vector">The vector to get the remaining elements from.</param>
+        /// <param name="index">The index of the element to set.</param>
+        /// <param name="value">The value to set the element to.</param>
+        /// <returns>A <see cref="Vector4" /> with the value of the element at <paramref name="index" /> set to <paramref name="value" /> and the remaining elements set to the same value as that in <paramref name="vector" />.</returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
+        [Intrinsic]
+        internal static Vector4 WithElement(this Vector4 vector, int index, float value)
+        {
+            if ((uint)(index) >= (uint)(Vector4.Count))
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+            }
+
+            Vector4 result = vector;
+            result.SetElementUnsafe(index, value);
+            return result;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static float GetElementUnsafe(in this Vector4 vector, int index)
+        {
+            Debug.Assert((index >= 0) && (index < Vector4.Count));
+            ref float address = ref Unsafe.AsRef(in vector.X);
+            return Unsafe.Add(ref address, index);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static void SetElementUnsafe(ref this Vector4 vector, int index, float value)
+        {
+            Debug.Assert((index >= 0) && (index < Vector4.Count));
+            Unsafe.Add(ref vector.X, index) = value;
+        }
+    }
+}
index 485cbd4..831b4f5 100644 (file)
@@ -1,13 +1,11 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.Intrinsics;
-using System.Text;
 
 namespace System.Numerics
 {
@@ -33,14 +31,14 @@ namespace System.Numerics
 
         internal const int Count = 4;
 
-        /// <summary>Creates a new <see cref="System.Numerics.Vector4" /> object whose four elements have the same value.</summary>
+        /// <summary>Creates a new <see cref="Vector4" /> object whose four elements have the same value.</summary>
         /// <param name="value">The value to assign to all four elements.</param>
         [Intrinsic]
         public Vector4(float value) : this(value, value, value, value)
         {
         }
 
-        /// <summary>Creates a   new <see cref="System.Numerics.Vector4" /> object from the specified <see cref="System.Numerics.Vector2" /> object and a Z and a W component.</summary>
+        /// <summary>Creates a   new <see cref="Vector4" /> object from the specified <see cref="Vector2" /> object and a Z and a W component.</summary>
         /// <param name="value">The vector to use for the X and Y components.</param>
         /// <param name="z">The Z component.</param>
         /// <param name="w">The W component.</param>
@@ -49,7 +47,7 @@ namespace System.Numerics
         {
         }
 
-        /// <summary>Constructs a new <see cref="System.Numerics.Vector4" /> object from the specified <see cref="System.Numerics.Vector3" /> object and a W component.</summary>
+        /// <summary>Constructs a new <see cref="Vector4" /> object from the specified <see cref="Vector3" /> object and a W component.</summary>
         /// <param name="value">The vector to use for the X, Y, and Z components.</param>
         /// <param name="w">The W component.</param>
         [Intrinsic]
@@ -58,10 +56,10 @@ namespace System.Numerics
         }
 
         /// <summary>Creates a vector whose elements have the specified values.</summary>
-        /// <param name="x">The value to assign to the <see cref="System.Numerics.Vector4.X" /> field.</param>
-        /// <param name="y">The value to assign to the <see cref="System.Numerics.Vector4.Y" /> field.</param>
-        /// <param name="z">The value to assign to the <see cref="System.Numerics.Vector4.Z" /> field.</param>
-        /// <param name="w">The value to assign to the <see cref="System.Numerics.Vector4.W" /> field.</param>
+        /// <param name="x">The value to assign to the <see cref="X" /> field.</param>
+        /// <param name="y">The value to assign to the <see cref="Y" /> field.</param>
+        /// <param name="z">The value to assign to the <see cref="Z" /> field.</param>
+        /// <param name="w">The value to assign to the <see cref="W" /> field.</param>
         [Intrinsic]
         public Vector4(float x, float y, float z, float w)
         {
@@ -92,7 +90,7 @@ namespace System.Numerics
         }
 
         /// <summary>Gets a vector whose 4 elements are equal to one.</summary>
-        /// <value>Returns <see cref="System.Numerics.Vector4" />.</value>
+        /// <value>Returns <see cref="Vector4" />.</value>
         /// <remarks>A vector whose four elements are equal to one (that is, it returns the vector <c>(1,1,1,1)</c>.</remarks>
         public static Vector4 One
         {
@@ -104,6 +102,7 @@ namespace System.Numerics
         /// <value>The vector <c>(1,0,0,0)</c>.</value>
         public static Vector4 UnitX
         {
+            [Intrinsic]
             get => new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
         }
 
@@ -111,6 +110,7 @@ namespace System.Numerics
         /// <value>The vector <c>(0,1,0,0)</c>.</value>
         public static Vector4 UnitY
         {
+            [Intrinsic]
             get => new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
         }
 
@@ -118,6 +118,7 @@ namespace System.Numerics
         /// <value>The vector <c>(0,0,1,0)</c>.</value>
         public static Vector4 UnitZ
         {
+            [Intrinsic]
             get => new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
         }
 
@@ -125,6 +126,7 @@ namespace System.Numerics
         /// <value>The vector <c>(0,0,0,1)</c>.</value>
         public static Vector4 UnitW
         {
+            [Intrinsic]
             get => new Vector4(0.0f, 0.0f, 0.0f, 1.0f);
         }
 
@@ -134,63 +136,19 @@ namespace System.Numerics
         /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
         public float this[int index]
         {
-            get => GetElement(this, index);
-            set => this = WithElement(this, index, value);
-        }
-
-        /// <summary>Gets the element at the specified index.</summary>
-        /// <param name="vector">The vector of the element to get.</param>
-        /// <param name="index">The index of the element to get.</param>
-        /// <returns>The value of the element at <paramref name="index" />.</returns>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
-        [Intrinsic]
-        internal static float GetElement(Vector4 vector, int index)
-        {
-            if ((uint)index >= Count)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
-            }
-
-            return GetElementUnsafe(ref vector, index);
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static float GetElementUnsafe(ref Vector4 vector, int index)
-        {
-            Debug.Assert(index is >= 0 and < Count);
-            return Unsafe.Add(ref Unsafe.As<Vector4, float>(ref vector), index);
-        }
-
-        /// <summary>Sets the element at the specified index.</summary>
-        /// <param name="vector">The vector of the element to get.</param>
-        /// <param name="index">The index of the element to set.</param>
-        /// <param name="value">The value of the element to set.</param>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
-        [Intrinsic]
-        internal static Vector4 WithElement(Vector4 vector, int index, float value)
-        {
-            if ((uint)index >= Count)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
-            }
-
-            Vector4 result = vector;
-            SetElementUnsafe(ref result, index, value);
-            return result;
-        }
+            [Intrinsic]
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => this.GetElement(index);
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static void SetElementUnsafe(ref Vector4 vector, int index, float value)
-        {
-            Debug.Assert(index is >= 0 and < Count);
-            Unsafe.Add(ref Unsafe.As<Vector4, float>(ref vector), index) = value;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => this = this.WithElement(index, value);
         }
 
         /// <summary>Adds two vectors together.</summary>
         /// <param name="left">The first vector to add.</param>
         /// <param name="right">The second vector to add.</param>
         /// <returns>The summed vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector4.op_Addition" /> method defines the addition operation for <see cref="System.Numerics.Vector4" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Addition" /> method defines the addition operation for <see cref="Vector4" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 operator +(Vector4 left, Vector4 right)
@@ -207,7 +165,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The vector that results from dividing <paramref name="left" /> by <paramref name="right" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector4.op_Division" /> method defines the division operation for <see cref="System.Numerics.Vector4" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector4.op_Division" /> method defines the division operation for <see cref="Vector4" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 operator /(Vector4 left, Vector4 right)
@@ -224,7 +182,7 @@ namespace System.Numerics
         /// <param name="value1">The vector.</param>
         /// <param name="value2">The scalar value.</param>
         /// <returns>The result of the division.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector4.op_Division" /> method defines the division operation for <see cref="System.Numerics.Vector4" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector4.op_Division" /> method defines the division operation for <see cref="Vector4" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 operator /(Vector4 value1, float value2)
@@ -236,7 +194,7 @@ namespace System.Numerics
         /// <param name="left">The first vector to compare.</param>
         /// <param name="right">The second vector to compare.</param>
         /// <returns><see langword="true" /> if <paramref name="left" /> and <paramref name="right" /> are equal; otherwise, <see langword="false" />.</returns>
-        /// <remarks>Two <see cref="System.Numerics.Vector4" /> objects are equal if each element in <paramref name="left" /> is equal to the corresponding element in <paramref name="right" />.</remarks>
+        /// <remarks>Two <see cref="Vector4" /> objects are equal if each element in <paramref name="left" /> is equal to the corresponding element in <paramref name="right" />.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool operator ==(Vector4 left, Vector4 right)
@@ -262,7 +220,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The element-wise product vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector4.op_Multiply" /> method defines the multiplication operation for <see cref="System.Numerics.Vector4" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector4.op_Multiply" /> method defines the multiplication operation for <see cref="Vector4" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 operator *(Vector4 left, Vector4 right)
@@ -279,7 +237,7 @@ namespace System.Numerics
         /// <param name="left">The vector.</param>
         /// <param name="right">The scalar value.</param>
         /// <returns>The scaled vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector4.op_Multiply" /> method defines the multiplication operation for <see cref="System.Numerics.Vector4" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector4.op_Multiply" /> method defines the multiplication operation for <see cref="Vector4" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 operator *(Vector4 left, float right)
@@ -291,7 +249,7 @@ namespace System.Numerics
         /// <param name="left">The vector.</param>
         /// <param name="right">The scalar value.</param>
         /// <returns>The scaled vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector4.op_Multiply" /> method defines the multiplication operation for <see cref="System.Numerics.Vector4" /> objects.</remarks>
+        /// <remarks>The <see cref="Vector4.op_Multiply" /> method defines the multiplication operation for <see cref="Vector4" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 operator *(float left, Vector4 right)
@@ -303,7 +261,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The vector that results from subtracting <paramref name="right" /> from <paramref name="left" />.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector4.op_Subtraction" /> method defines the subtraction operation for <see cref="System.Numerics.Vector4" /> objects.</remarks>
+        /// <remarks>The <see cref="op_Subtraction" /> method defines the subtraction operation for <see cref="Vector4" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 operator -(Vector4 left, Vector4 right)
@@ -319,7 +277,7 @@ namespace System.Numerics
         /// <summary>Negates the specified vector.</summary>
         /// <param name="value">The vector to negate.</param>
         /// <returns>The negated vector.</returns>
-        /// <remarks>The <see cref="System.Numerics.Vector4.op_UnaryNegation" /> method defines the unary negation operation for <see cref="System.Numerics.Vector4" /> objects.</remarks>
+        /// <remarks>The <see cref="op_UnaryNegation" /> method defines the unary negation operation for <see cref="Vector4" /> objects.</remarks>
         [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 operator -(Vector4 value)
@@ -346,6 +304,7 @@ namespace System.Numerics
         /// <param name="left">The first vector to add.</param>
         /// <param name="right">The second vector to add.</param>
         /// <returns>The summed vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Add(Vector4 left, Vector4 right)
         {
@@ -357,6 +316,7 @@ namespace System.Numerics
         /// <param name="min">The minimum value.</param>
         /// <param name="max">The maximum value.</param>
         /// <returns>The restricted vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max)
         {
@@ -368,6 +328,7 @@ namespace System.Numerics
         /// <param name="value1">The first point.</param>
         /// <param name="value2">The second point.</param>
         /// <returns>The distance.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float Distance(Vector4 value1, Vector4 value2)
         {
@@ -379,6 +340,7 @@ namespace System.Numerics
         /// <param name="value1">The first point.</param>
         /// <param name="value2">The second point.</param>
         /// <returns>The distance squared.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float DistanceSquared(Vector4 value1, Vector4 value2)
         {
@@ -390,6 +352,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The vector resulting from the division.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Divide(Vector4 left, Vector4 right)
         {
@@ -400,6 +363,7 @@ namespace System.Numerics
         /// <param name="left">The vector.</param>
         /// <param name="divisor">The scalar value.</param>
         /// <returns>The vector that results from the division.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Divide(Vector4 left, float divisor)
         {
@@ -428,6 +392,7 @@ namespace System.Numerics
         /// <remarks><format type="text/markdown"><![CDATA[
         /// The behavior of this method changed in .NET 5.0. For more information, see [Behavior change for Vector2.Lerp and Vector4.Lerp](/dotnet/core/compatibility/3.1-5.0#behavior-change-for-vector2lerp-and-vector4lerp).
         /// ]]></format></remarks>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Lerp(Vector4 value1, Vector4 value2, float amount)
         {
@@ -470,6 +435,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The element-wise product vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Multiply(Vector4 left, Vector4 right)
         {
@@ -480,6 +446,7 @@ namespace System.Numerics
         /// <param name="left">The vector to multiply.</param>
         /// <param name="right">The scalar value.</param>
         /// <returns>The scaled vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Multiply(Vector4 left, float right)
         {
@@ -490,6 +457,7 @@ namespace System.Numerics
         /// <param name="left">The scaled value.</param>
         /// <param name="right">The vector.</param>
         /// <returns>The scaled vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Multiply(float left, Vector4 right)
         {
@@ -499,6 +467,7 @@ namespace System.Numerics
         /// <summary>Negates a specified vector.</summary>
         /// <param name="value">The vector to negate.</param>
         /// <returns>The negated vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Negate(Vector4 value)
         {
@@ -508,6 +477,7 @@ namespace System.Numerics
         /// <summary>Returns a vector with the same direction as the specified vector, but with a length of one.</summary>
         /// <param name="vector">The vector to normalize.</param>
         /// <returns>The normalized vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Normalize(Vector4 vector)
         {
@@ -533,6 +503,7 @@ namespace System.Numerics
         /// <param name="left">The first vector.</param>
         /// <param name="right">The second vector.</param>
         /// <returns>The difference vector.</returns>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Subtract(Vector4 left, Vector4 right)
         {
@@ -545,13 +516,17 @@ namespace System.Numerics
         /// <returns>The transformed vector.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Transform(Vector2 position, Matrix4x4 matrix)
+            => Transform(position, in matrix.AsImpl());
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Vector4 Transform(Vector2 position, in Matrix4x4.Impl matrix)
         {
-            return new Vector4(
-                (position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M41,
-                (position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M42,
-                (position.X * matrix.M13) + (position.Y * matrix.M23) + matrix.M43,
-                (position.X * matrix.M14) + (position.Y * matrix.M24) + matrix.M44
-            );
+            Vector4 result = matrix.X * position.X;
+
+            result += matrix.Y * position.Y;
+            result += matrix.W;
+
+            return result;
         }
 
         /// <summary>Transforms a two-dimensional vector by the specified Quaternion rotation value.</summary>
@@ -589,13 +564,18 @@ namespace System.Numerics
         /// <returns>The transformed vector.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Transform(Vector3 position, Matrix4x4 matrix)
+            => Transform(position, in matrix.AsImpl());
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Vector4 Transform(Vector3 position, in Matrix4x4.Impl matrix)
         {
-            return new Vector4(
-                (position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41,
-                (position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42,
-                (position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43,
-                (position.X * matrix.M14) + (position.Y * matrix.M24) + (position.Z * matrix.M34) + matrix.M44
-            );
+            Vector4 result = matrix.X * position.X;
+
+            result += matrix.Y * position.Y;
+            result += matrix.Z * position.Z;
+            result += matrix.W;
+
+            return result;
         }
 
         /// <summary>Transforms a three-dimensional vector by the specified Quaternion rotation value.</summary>
@@ -678,9 +658,9 @@ namespace System.Numerics
         /// <summary>Copies the elements of the vector to a specified array.</summary>
         /// <param name="array">The destination array.</param>
         /// <remarks><paramref name="array" /> must have at least four elements. The method copies the vector's elements starting at index 0.</remarks>
-        /// <exception cref="System.NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
-        /// <exception cref="System.ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
-        /// <exception cref="System.RankException"><paramref name="array" /> is multidimensional.</exception>
+        /// <exception cref="NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
+        /// <exception cref="ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
+        /// <exception cref="RankException"><paramref name="array" /> is multidimensional.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly void CopyTo(float[] array)
         {
@@ -698,12 +678,12 @@ namespace System.Numerics
         /// <param name="array">The destination array.</param>
         /// <param name="index">The index at which to copy the first element of the vector.</param>
         /// <remarks><paramref name="array" /> must have a sufficient number of elements to accommodate the four vector elements. In other words, elements <paramref name="index" /> through <paramref name="index" /> + 3 must already exist in <paramref name="array" />.</remarks>
-        /// <exception cref="System.NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
-        /// <exception cref="System.ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
-        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="index" /> is less than zero.
+        /// <exception cref="NullReferenceException"><paramref name="array" /> is <see langword="null" />.</exception>
+        /// <exception cref="ArgumentException">The number of elements in the current instance is greater than in the array.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> is less than zero.
         /// -or-
         /// <paramref name="index" /> is greater than or equal to the array length.</exception>
-        /// <exception cref="System.RankException"><paramref name="array" /> is multidimensional.</exception>
+        /// <exception cref="RankException"><paramref name="array" /> is multidimensional.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly void CopyTo(float[] array, int index)
         {
@@ -724,7 +704,7 @@ namespace System.Numerics
 
         /// <summary>Copies the vector to the given <see cref="Span{T}" />. The length of the destination span must be at least 4.</summary>
         /// <param name="destination">The destination span which the values are copied into.</param>
-        /// <exception cref="System.ArgumentException">If number of elements in source vector is greater than those available in destination span.</exception>
+        /// <exception cref="ArgumentException">If number of elements in source vector is greater than those available in destination span.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly void CopyTo(Span<float> destination)
         {
@@ -754,7 +734,7 @@ namespace System.Numerics
         /// <summary>Returns a value that indicates whether this instance and another vector are equal.</summary>
         /// <param name="other">The other vector.</param>
         /// <returns><see langword="true" /> if the two vectors are equal; otherwise, <see langword="false" />.</returns>
-        /// <remarks>Two vectors are equal if their <see cref="System.Numerics.Vector4.X" />, <see cref="System.Numerics.Vector4.Y" />, <see cref="System.Numerics.Vector4.Z" />, and <see cref="System.Numerics.Vector4.W" /> elements are equal.</remarks>
+        /// <remarks>Two vectors are equal if their <see cref="X" />, <see cref="Y" />, <see cref="Z" />, and <see cref="W" /> elements are equal.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly bool Equals(Vector4 other)
         {
@@ -780,7 +760,7 @@ namespace System.Numerics
         /// <summary>Returns a value that indicates whether this instance and a specified object are equal.</summary>
         /// <param name="obj">The object to compare with the current instance.</param>
         /// <returns><see langword="true" /> if the current instance and <paramref name="obj" /> are equal; otherwise, <see langword="false" />. If <paramref name="obj" /> is <see langword="null" />, the method returns <see langword="false" />.</returns>
-        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="System.Numerics.Vector4" /> object and their corresponding elements are equal.</remarks>
+        /// <remarks>The current instance and <paramref name="obj" /> are equal if <paramref name="obj" /> is a <see cref="Vector4" /> object and their corresponding elements are equal.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public override readonly bool Equals([NotNullWhen(true)] object? obj)
         {
@@ -796,7 +776,8 @@ namespace System.Numerics
 
         /// <summary>Returns the length of this vector object.</summary>
         /// <returns>The vector's length.</returns>
-        /// <altmember cref="System.Numerics.Vector4.LengthSquared"/>
+        /// <altmember cref="LengthSquared"/>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly float Length()
         {
@@ -806,8 +787,9 @@ namespace System.Numerics
 
         /// <summary>Returns the length of the vector squared.</summary>
         /// <returns>The vector's length squared.</returns>
-        /// <remarks>This operation offers better performance than a call to the <see cref="System.Numerics.Vector4.Length" /> method.</remarks>
-        /// <altmember cref="System.Numerics.Vector4.Length"/>
+        /// <remarks>This operation offers better performance than a call to the <see cref="Length" /> method.</remarks>
+        /// <altmember cref="Length"/>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public readonly float LengthSquared()
         {
@@ -816,7 +798,7 @@ namespace System.Numerics
 
         /// <summary>Returns the string representation of the current instance using default formatting.</summary>
         /// <returns>The string representation of the current instance.</returns>
-        /// <remarks>This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="System.Globalization.NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
+        /// <remarks>This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
         public override readonly string ToString()
         {
             return ToString("G", CultureInfo.CurrentCulture);
@@ -825,7 +807,7 @@ namespace System.Numerics
         /// <summary>Returns the string representation of the current instance using the specified format string to format individual elements.</summary>
         /// <param name="format">A standard or custom numeric format string that defines the format of individual elements.</param>
         /// <returns>The string representation of the current instance.</returns>
-        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and the current culture's formatting conventions. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="System.Globalization.NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
+        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and the current culture's formatting conventions. The "&lt;" and "&gt;" characters are used to begin and end the string, and the current culture's <see cref="NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
         /// <related type="Article" href="/dotnet/standard/base-types/standard-numeric-format-strings">Standard Numeric Format Strings</related>
         /// <related type="Article" href="/dotnet/standard/base-types/custom-numeric-format-strings">Custom Numeric Format Strings</related>
         public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format)
@@ -837,7 +819,7 @@ namespace System.Numerics
         /// <param name="format">A standard or custom numeric format string that defines the format of individual elements.</param>
         /// <param name="formatProvider">A format provider that supplies culture-specific formatting information.</param>
         /// <returns>The string representation of the current instance.</returns>
-        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and <paramref name="formatProvider" />. The "&lt;" and "&gt;" characters are used to begin and end the string, and the format provider's <see cref="System.Globalization.NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
+        /// <remarks>This method returns a string in which each element of the vector is formatted using <paramref name="format" /> and <paramref name="formatProvider" />. The "&lt;" and "&gt;" characters are used to begin and end the string, and the format provider's <see cref="NumberFormatInfo.NumberGroupSeparator" /> property followed by a space is used to separate each element.</remarks>
         /// <related type="Article" href="/dotnet/standard/base-types/standard-numeric-format-strings">Standard Numeric Format Strings</related>
         /// <related type="Article" href="/dotnet/standard/base-types/custom-numeric-format-strings">Custom Numeric Format Strings</related>
         public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? formatProvider)
index de163d2..99295c9 100644 (file)
@@ -234,6 +234,22 @@ namespace System.Runtime.Intrinsics
         public static Vector128<ulong> AsUInt64<T>(this Vector128<T> vector)
             where T : struct => vector.As<T, ulong>();
 
+        /// <summary>Reinterprets a <see cref="Plane" /> as a new <see cref="Vector128{Single}" />.</summary>
+        /// <param name="value">The plane to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector128{Single}" />.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Vector128<float> AsVector128(this Plane value)
+            => Unsafe.As<Plane, Vector128<float>>(ref value);
+
+        /// <summary>Reinterprets a <see cref="Quaternion" /> as a new <see cref="Vector128{Single}" />.</summary>
+        /// <param name="value">The quaternion to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector128{Single}" />.</returns>
+        [Intrinsic]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static Vector128<float> AsVector128(this Quaternion value)
+            => Unsafe.As<Quaternion, Vector128<float>>(ref value);
+
         /// <summary>Reinterprets a <see cref="Vector2" /> as a new <see cref="Vector128{Single}" />.</summary>
         /// <param name="value">The vector to reinterpret.</param>
         /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector128{Single}" />.</returns>
index cad1e07..816c0e1 100644 (file)
@@ -1123,8 +1123,19 @@ is_create_from_half_vectors_overload (MonoMethodSignature *fsig)
 static gboolean
 is_element_type_primitive (MonoType *vector_type)
 {
-       MonoType *element_type = get_vector_t_elem_type (vector_type);
-       return MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type);
+       if (vector_type->type == MONO_TYPE_GENERICINST) {
+               MonoType *element_type = get_vector_t_elem_type (vector_type);
+               return MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type);
+       } else {
+               MonoClass *klass = mono_class_from_mono_type_internal (vector_type);
+               g_assert (
+                       !strcmp (m_class_get_name (klass), "Plane") ||
+                       !strcmp (m_class_get_name (klass), "Quaternion") ||
+                       !strcmp (m_class_get_name (klass), "Vector2") ||
+                       !strcmp (m_class_get_name (klass), "Vector3") ||
+                       !strcmp (m_class_get_name (klass), "Vector4"));
+               return TRUE;
+       }
 }
 
 static MonoInst*
@@ -1414,13 +1425,26 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
 #endif
        }
        case SN_GetElement: {
+               int elems;
+
                if (!is_element_type_primitive (fsig->params [0]))
                        return NULL;
+
                MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
-               MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0];
-               int size = mono_class_value_size (arg_class, NULL);
-               int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL);
-               int elems = size / esize;
+
+               if (fsig->params [0]->type == MONO_TYPE_GENERICINST) {
+                       MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0];
+                       int size = mono_class_value_size (arg_class, NULL);
+                       int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL);
+                       elems = size / esize;
+               } else {
+                       // This exists to handle the static extension methods for Vector2/3/4 and Quaterion
+                       // which live on System.Numerics.Vector
+
+                       arg0_type = MONO_TYPE_R4;
+                       elems = 4;
+               }
+
                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, elems);
                MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException");
                int extract_op = type_to_xextract_op (arg0_type);
@@ -1666,13 +1690,26 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
                return emit_simd_ins_for_sig (cfg, klass, op, 0, arg0_type, fsig, args);
        }
        case SN_WithElement: {
+               int elems;
+               
                if (!is_element_type_primitive (fsig->params [0]))
                        return NULL;
+
                MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
-               MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0];
-               int size = mono_class_value_size (arg_class, NULL);
-               int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL);
-               int elems = size / esize;
+
+               if (fsig->params [0]->type == MONO_TYPE_GENERICINST) {
+                       MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0];
+                       int size = mono_class_value_size (arg_class, NULL);
+                       int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL);
+                       elems = size / esize;
+               } else {
+                       // This exists to handle the static extension methods for Vector2/3/4 and Quaterion
+                       // which live on System.Numerics.Vector
+
+                       arg0_type = MONO_TYPE_R4;
+                       elems = 4;
+               }
+
                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, elems);
                MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException");
                int insert_op = type_to_xinsert_op (arg0_type);
@@ -1834,18 +1871,28 @@ static guint16 vector2_methods[] = {
        SN_ctor,
        SN_Abs,
        SN_Add,
+       SN_Clamp,
        SN_CopyTo,
+       SN_Distance,
+       SN_DistanceSquared,
        SN_Divide,
        SN_Dot,
-       SN_GetElement,
+       SN_Length,
+       SN_LengthSquared,
+       SN_Lerp,
        SN_Max,
        SN_Min,
        SN_Multiply,
+       SN_Negate,
+       SN_Normalize,
        SN_SquareRoot,
        SN_Subtract,
-       SN_WithElement,
        SN_get_Item,
        SN_get_One,
+       SN_get_UnitW,
+       SN_get_UnitX,
+       SN_get_UnitY,
+       SN_get_UnitZ,
        SN_get_Zero,
        SN_op_Addition,
        SN_op_Division,
@@ -1950,18 +1997,15 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
                ins->inst_c1 = ty;
                return ins;
        }
-       case SN_GetElement: {
-               g_assert (!fsig->hasthis && fsig->param_count == 2 && mono_metadata_type_equal (fsig->params [0], type) && fsig->params [1]->type == MONO_TYPE_I4);
-               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, len);
-               MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException");
-               MonoTypeEnum ty = etype->type;
-               int opcode = type_to_xextract_op (ty);
-               ins = emit_simd_ins (cfg, klass, opcode, args [0]->dreg, args [1]->dreg);
-               ins->inst_c1 = ty;
-               return ins;
-       }
        case SN_get_Zero:
                return emit_xzero (cfg, klass);
+       case SN_get_UnitX:
+       case SN_get_UnitY:
+       case SN_get_UnitZ:
+       case SN_get_UnitW: {
+               // FIXME:
+               return NULL;
+       }
        case SN_get_One: {
                static const float r4_one = 1.0f;
 
@@ -1987,15 +2031,6 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
                ins->dreg = dreg;
                return ins;
        }
-       case SN_WithElement: {
-               g_assert (!fsig->hasthis && fsig->param_count == 3 && fsig->params [1]->type == MONO_TYPE_I4 && fsig->params [2]->type == MONO_TYPE_R4);
-               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, len);
-               MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException");
-               ins = emit_simd_ins (cfg, klass, OP_XINSERT_R4, args [0]->dreg, args [2]->dreg);
-               ins->sreg3 = args [1]->dreg;
-               ins->inst_c1 = MONO_TYPE_R4;
-               return ins;
-       }
        case SN_Add:
        case SN_Divide:
        case SN_Multiply:
@@ -2034,6 +2069,7 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
                return NULL;
 #endif
        }
+       case SN_Negate:
        case SN_op_UnaryNegation: {
 #if defined(TARGET_ARM64) || defined(TARGET_AMD64)
                return emit_simd_ins (cfg, klass, OP_NEGATION, args [0]->dreg, -1);
@@ -2078,6 +2114,29 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
        case SN_CopyTo:
                // FIXME:
                return NULL;
+       case SN_Clamp: {
+               if (!(!fsig->hasthis && fsig->param_count == 3 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type) && mono_metadata_type_equal (fsig->params [2], type)))
+                       return NULL;
+
+               MonoInst *max = emit_simd_ins (cfg, klass, OP_XBINOP, args[0]->dreg, args[1]->dreg);
+               max->inst_c0 = OP_FMAX;
+               max->inst_c1 = MONO_TYPE_R4;
+
+               MonoInst *min = emit_simd_ins (cfg, klass, OP_XBINOP, max->dreg, args[2]->dreg);
+               min->inst_c0 = OP_FMIN;
+               min->inst_c1 = MONO_TYPE_R4;
+
+               return min;
+       }
+       case SN_Distance:
+       case SN_DistanceSquared:
+       case SN_Length:
+       case SN_LengthSquared:
+       case SN_Lerp:
+       case SN_Normalize: {
+               // FIXME:
+               return NULL;
+       }
        default:
                g_assert_not_reached ();
        }
index 1a6a429..e8d4af1 100644 (file)
@@ -1,5 +1,8 @@
 METHOD2(".ctor", ctor)
+METHOD(Clamp)
 METHOD(CopyTo)
+METHOD(Distance)
+METHOD(DistanceSquared)
 METHOD(Equals)
 METHOD(GreaterThan)
 METHOD(GreaterThanAll)
@@ -13,10 +16,14 @@ METHOD(LessThanAny)
 METHOD(LessThanOrEqual)
 METHOD(LessThanOrEqualAll)
 METHOD(LessThanOrEqualAny)
+METHOD(Length)
+METHOD(LengthSquared)
+METHOD(Lerp)
 METHOD(Min)
 METHOD(Max)
 METHOD(MinScalar)
 METHOD(MaxScalar)
+METHOD(Normalize)
 METHOD(PopCount)
 METHOD(LeadingZeroCount)
 METHOD(get_Count)
@@ -25,6 +32,10 @@ METHOD(get_IsSupported)
 METHOD(get_AllBitsSet)
 METHOD(get_Item)
 METHOD(get_One)
+METHOD(get_UnitW)
+METHOD(get_UnitX)
+METHOD(get_UnitY)
+METHOD(get_UnitZ)
 METHOD(get_Zero)
 METHOD(op_Addition)
 METHOD(op_BitwiseAnd)