From f69972fb744524a7d5345600e1b9b51c3fac736c Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 15 Jun 2024 06:49:05 -0700 Subject: [PATCH] Expose various new Create and conversion APIs for the Vector types (#103462) * Expose various new Create and conversion APIs for the Vector types * Remove simdashwintrinsic handling for Vector2/3 * Apply formatting patch * Ensure creation from a span checks the right element count for Vector2/3 * Ensure that we create more correct WithElement nodes * Ensure that Vector128.AsVector128Unsafe preserves the fact it produces TYP_SIMD16 --- .../src/System/Math.CoreCLR.cs | 1 + .../src/System/MathF.CoreCLR.cs | 1 + src/coreclr/jit/compiler.h | 10 +- src/coreclr/jit/fgbasic.cpp | 7 +- src/coreclr/jit/gentree.cpp | 1 + src/coreclr/jit/hwintrinsic.cpp | 32 +- src/coreclr/jit/hwintrinsicarm64.cpp | 12 + src/coreclr/jit/hwintrinsicxarch.cpp | 12 + src/coreclr/jit/importercalls.cpp | 8 +- src/coreclr/jit/lclmorph.cpp | 36 +- src/coreclr/jit/lower.cpp | 21 +- src/coreclr/jit/simdashwintrinsic.cpp | 419 ++---------------- src/coreclr/jit/simdashwintrinsic.h | 40 +- src/coreclr/jit/simdashwintrinsiclistarm64.h | 53 +-- src/coreclr/jit/simdashwintrinsiclistxarch.h | 53 +-- .../ref/System.Numerics.Vectors.cs | 24 + .../System.Private.CoreLib.Shared.projitems | 3 +- .../src/System/Numerics/Matrix3x2.Impl.cs | 100 ++--- .../src/System/Numerics/Matrix4x4.Impl.cs | 351 +++++++-------- .../src/System/Numerics/Matrix4x4.cs | 4 +- .../src/System/Numerics/Plane.Extensions.cs | 25 ++ .../src/System/Numerics/Plane.cs | 45 +- .../System/Numerics/Quaternion.Extensions.cs | 44 +- .../src/System/Numerics/Quaternion.cs | 78 ++-- .../src/System/Numerics/Vector.cs | 77 +++- .../src/System/Numerics/Vector2.Extensions.cs | 56 +-- .../src/System/Numerics/Vector2.cs | 203 ++++----- .../src/System/Numerics/Vector3.Extensions.cs | 56 +-- .../src/System/Numerics/Vector3.cs | 233 ++++------ .../src/System/Numerics/Vector4.Extensions.cs | 43 +- .../src/System/Numerics/Vector4.cs | 106 ++++- .../src/System/Numerics/Vector_1.cs | 6 +- .../System/Runtime/Intrinsics/Vector128.cs | 50 ++- .../System/Runtime/Intrinsics/Vector256.cs | 16 + .../System/Runtime/Intrinsics/Vector512.cs | 24 + .../SearchValues/IndexOfAnyAsciiSearcher.cs | 10 +- .../System/SearchValues/ProbabilisticMap.cs | 12 +- .../Strings/Helpers/TeddyBucketizer.cs | 11 +- .../src/System/SpanHelpers.T.cs | 2 +- .../ref/System.Runtime.Intrinsics.cs | 8 + 40 files changed, 947 insertions(+), 1346 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.Extensions.cs diff --git a/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs index 5dd46b02d4231..1384da2c81d1f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs @@ -92,6 +92,7 @@ public static partial class Math [MethodImpl(MethodImplOptions.InternalCall)] public static extern double Sin(double a); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe (double Sin, double Cos) SinCos(double x) { double sin, cos; diff --git a/src/coreclr/System.Private.CoreLib/src/System/MathF.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/MathF.CoreCLR.cs index e9caae4c18a38..2bef2b8d3e175 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MathF.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MathF.CoreCLR.cs @@ -89,6 +89,7 @@ public static partial class MathF [MethodImpl(MethodImplOptions.InternalCall)] public static extern float Sin(float x); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe (float Sin, float Cos) SinCos(float x) { float sin, cos; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 5dca9aa7f5e32..8ccaeec161f06 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4562,8 +4562,7 @@ class Compiler GenTreeLclVarCommon* data, WCHAR* cns, int len, int dataOffset, StringComparison cmpMode); GenTreeStrCon* impGetStrConFromSpan(GenTree* span); - GenTree* impIntrinsic(GenTree* newobjThis, - CORINFO_CLASS_HANDLE clsHnd, + GenTree* impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, unsigned methodFlags, @@ -4628,7 +4627,6 @@ class Compiler CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, - GenTree* newobjThis, bool mustExpand); protected: @@ -4640,7 +4638,6 @@ class Compiler var_types retType, CorInfoType simdBaseJitType, unsigned simdSize, - GenTree* newobjThis, bool mustExpand); GenTree* impSpecialIntrinsic(NamedIntrinsic intrinsic, @@ -4653,10 +4650,7 @@ class Compiler unsigned simdSize, bool mustExpand); - GenTree* getArgForHWIntrinsic(var_types argType, - CORINFO_CLASS_HANDLE argClass, - bool expectAddr = false, - GenTree* newobjThis = nullptr); + GenTree* getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE argClass); GenTree* impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, CorInfoType simdBaseJitType); GenTree* addRangeCheckIfNeeded( NamedIntrinsic intrinsic, GenTree* immOp, bool mustExpand, int immLowerBound, int immUpperBound); diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 4b3f0cc9afd2b..653ff015c3272 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -1395,15 +1395,10 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed case NI_Vector64_CreateScalar: case NI_Vector64_CreateScalarUnsafe: #endif // TARGET_ARM64 - case NI_Vector2_Create: - case NI_Vector2_CreateBroadcast: - case NI_Vector3_Create: - case NI_Vector3_CreateBroadcast: - case NI_Vector3_CreateFromVector2: case NI_Vector128_Create: case NI_Vector128_CreateScalar: case NI_Vector128_CreateScalarUnsafe: - case NI_VectorT_CreateBroadcast: + case NI_VectorT_Create: #if defined(TARGET_XARCH) case NI_BMI1_TrailingZeroCount: case NI_BMI1_X64_TrailingZeroCount: diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index ec22b00d63639..9a899443294b5 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -27176,6 +27176,7 @@ GenTree* Compiler::gtNewSimdWithElementNode( assert(varTypeIsArithmetic(simdBaseType)); assert(op2->IsCnsIntOrI()); + assert(varTypeIsArithmetic(op3)); ssize_t imm8 = op2->AsIntCon()->IconValue(); ssize_t count = simdSize / genTypeSize(simdBaseType); diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 26af49073c5d6..f2f04b4a820a6 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -745,16 +745,11 @@ bool HWIntrinsicInfo::isImmOp(NamedIntrinsic id, const GenTree* op) // Arguments: // argType -- the required type of argument // argClass -- the class handle of argType -// expectAddr -- if true indicates we are expecting type stack entry to be a TYP_BYREF. -// newobjThis -- For CEE_NEWOBJ, this is the temp grabbed for the allocated uninitialized object. // // Return Value: // the validated argument // -GenTree* Compiler::getArgForHWIntrinsic(var_types argType, - CORINFO_CLASS_HANDLE argClass, - bool expectAddr, - GenTree* newobjThis) +GenTree* Compiler::getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE argClass) { GenTree* arg = nullptr; @@ -768,31 +763,12 @@ GenTree* Compiler::getArgForHWIntrinsic(var_types argType, } assert(varTypeIsSIMD(argType)); - if (newobjThis == nullptr) - { - if (expectAddr) - { - arg = gtNewLoadValueNode(argType, impPopStack().val); - } - else - { - arg = impSIMDPopStack(); - } - assert(varTypeIsSIMDOrMask(arg)); - } - else - { - assert(newobjThis->IsLclVarAddr()); - arg = newobjThis; - - // push newobj result on type stack - unsigned lclNum = arg->AsLclVarCommon()->GetLclNum(); - impPushOnStack(gtNewLclvNode(lclNum, lvaGetRealType(lclNum)), verMakeTypeInfo(argClass)); - } + arg = impSIMDPopStack(); + assert(varTypeIsSIMDOrMask(arg)); } else { - assert(varTypeIsArithmetic(argType) || ((argType == TYP_BYREF) && (newobjThis == nullptr))); + assert(varTypeIsArithmetic(argType) || (argType == TYP_BYREF)); arg = impPopStack().val; assert(varTypeIsArithmetic(arg->TypeGet()) || ((argType == TYP_BYREF) && arg->TypeIs(TYP_BYREF))); diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 3a481e2934517..5a32b4cbeee3d 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -721,6 +721,18 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_AsVector128Unsafe: + { + assert(sig->numArgs == 1); + assert(retType == TYP_SIMD16); + assert(simdBaseJitType == CORINFO_TYPE_FLOAT); + assert((simdSize == 8) || (simdSize == 12)); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, NI_Vector128_AsVector128Unsafe, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_op_BitwiseAnd: case NI_Vector128_op_BitwiseAnd: { diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index b44c9cf0785e7..5acac342b6211 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -1279,6 +1279,18 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_AsVector128Unsafe: + { + assert(sig->numArgs == 1); + assert(retType == TYP_SIMD16); + assert(simdBaseJitType == CORINFO_TYPE_FLOAT); + assert((simdSize == 8) || (simdSize == 12)); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, NI_Vector128_AsVector128Unsafe, simdBaseJitType, simdSize); + break; + } + case NI_Vector256_AsVector: case NI_Vector256_AsVector256: { diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 59a3fadf40f1e..c920ac70cfef5 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -242,7 +242,7 @@ var_types Compiler::impImportCall(OPCODE opcode, } #endif // FEATURE_READYTORUN - call = impIntrinsic(newobjThis, clsHnd, methHnd, sig, mflags, pResolvedToken, isReadonlyCall, isTailCall, + call = impIntrinsic(clsHnd, methHnd, sig, mflags, pResolvedToken, isReadonlyCall, isTailCall, opcode == CEE_CALLVIRT, pConstrainedResolvedToken, callInfo->thisTransform R2RARG(&entryPoint), &ni, &isSpecialIntrinsic); @@ -2818,7 +2818,6 @@ GenTree* Compiler::impCreateSpanIntrinsic(CORINFO_SIG_INFO* sig) // impIntrinsic: possibly expand intrinsic call into alternate IR sequence // // Arguments: -// newobjThis - for constructor calls, the tree for the newly allocated object // clsHnd - handle for the intrinsic method's class // method - handle for the intrinsic method // sig - signature of the intrinsic method @@ -2861,8 +2860,7 @@ GenTree* Compiler::impCreateSpanIntrinsic(CORINFO_SIG_INFO* sig) // identified as "must expand" if they are invoked from within their // own method bodies. // -GenTree* Compiler::impIntrinsic(GenTree* newobjThis, - CORINFO_CLASS_HANDLE clsHnd, +GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, unsigned methodFlags, @@ -3088,7 +3086,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, if (isIntrinsic) { - GenTree* hwintrinsic = impSimdAsHWIntrinsic(ni, clsHnd, method, sig, newobjThis, mustExpand); + GenTree* hwintrinsic = impSimdAsHWIntrinsic(ni, clsHnd, method, sig, mustExpand); if (hwintrinsic == nullptr) { diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 0c005f1909a54..1774aea55c831 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1307,9 +1307,10 @@ class LocalAddressVisitor final : public GenTreeVisitor 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 + // We have three cases we want to handle: + // 1. Vector2/3/4 and Quaternion where we have 2-4x float fields // 2. Plane where we have 1x Vector3 and 1x float field + // 3. Accesses of halves of larger SIMD types case IndirTransform::GetElement: { @@ -1321,24 +1322,29 @@ class LocalAddressVisitor final : public GenTreeVisitor { case TYP_FLOAT: { + // Handle case 1 or the float field of case 2 GenTree* indexNode = m_compiler->gtNewIconNode(offset / genTypeSize(elementType)); hwiNode = m_compiler->gtNewSimdGetElementNode(elementType, lclNode, indexNode, CORINFO_TYPE_FLOAT, genTypeSize(varDsc)); break; } + case TYP_SIMD12: { + // Handle the Vector3 field of case 2 assert(genTypeSize(varDsc) == 16); hwiNode = m_compiler->gtNewSimdHWIntrinsicNode(elementType, lclNode, NI_Vector128_AsVector3, CORINFO_TYPE_FLOAT, 16); break; } + case TYP_SIMD8: #if defined(FEATURE_SIMD) && defined(TARGET_XARCH) case TYP_SIMD16: case TYP_SIMD32: #endif { + // Handle case 3 assert(genTypeSize(elementType) * 2 == genTypeSize(varDsc)); if (offset == 0) { @@ -1374,29 +1380,44 @@ class LocalAddressVisitor final : public GenTreeVisitor { case TYP_FLOAT: { + // Handle case 1 or the float field of case 2 GenTree* indexNode = m_compiler->gtNewIconNode(offset / genTypeSize(elementType)); hwiNode = m_compiler->gtNewSimdWithElementNode(varDsc->TypeGet(), simdLclNode, indexNode, elementNode, CORINFO_TYPE_FLOAT, genTypeSize(varDsc)); break; } + case TYP_SIMD12: { + // Handle the Vector3 field of case 2 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, + // We effectively 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 + + elementNode = m_compiler->gtNewSimdHWIntrinsicNode(TYP_SIMD16, elementNode, + NI_Vector128_AsVector128Unsafe, + CORINFO_TYPE_FLOAT, 12); + + GenTree* indexNode1 = m_compiler->gtNewIconNode(3, TYP_INT); + simdLclNode = m_compiler->gtNewSimdGetElementNode(TYP_FLOAT, simdLclNode, indexNode1, + CORINFO_TYPE_FLOAT, 16); + + GenTree* indexNode2 = m_compiler->gtNewIconNode(3, TYP_INT); + hwiNode = m_compiler->gtNewSimdWithElementNode(TYP_SIMD16, elementNode, indexNode2, simdLclNode, CORINFO_TYPE_FLOAT, 16); break; } + case TYP_SIMD8: #if defined(FEATURE_SIMD) && defined(TARGET_XARCH) case TYP_SIMD16: case TYP_SIMD32: #endif { + // Handle case 3 assert(genTypeSize(elementType) * 2 == genTypeSize(varDsc)); if (offset == 0) { @@ -1412,6 +1433,7 @@ class LocalAddressVisitor final : public GenTreeVisitor break; } + default: unreached(); } @@ -1541,7 +1563,7 @@ class LocalAddressVisitor final : public GenTreeVisitor if (varTypeIsSIMD(varDsc)) { // We have three cases we want to handle: - // 1. Vector2/3/4 and Quaternion where we have 4x float fields + // 1. Vector2/3/4 and Quaternion where we have 2-4x float fields // 2. Plane where we have 1x Vector3 and 1x float field // 3. Accesses of halves of larger SIMD types diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 2137874887e70..c7790fb6199d6 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -1752,18 +1752,23 @@ void Lowering::LowerArg(GenTreeCall* call, CallArg* callArg, bool late) } else if (arg->OperIs(GT_HWINTRINSIC)) { - GenTreeJitIntrinsic* jitIntrinsic = reinterpret_cast(arg); + GenTreeHWIntrinsic* hwintrinsic = arg->AsHWIntrinsic(); // For HWIntrinsic, there are some intrinsics like ExtractVector128 which have - // a gtType of TYP_SIMD16 but a SimdSize of 32, so we need to include that in - // the assert below. + // a gtType of TYP_SIMD16 but a SimdSize of 32, so we can't necessarily assert + // the simd size - assert((jitIntrinsic->GetSimdSize() == 12) || (jitIntrinsic->GetSimdSize() == 16) || - (jitIntrinsic->GetSimdSize() == 32) || (jitIntrinsic->GetSimdSize() == 64)); - - if (jitIntrinsic->GetSimdSize() == 12) + if (hwintrinsic->GetSimdSize() == 12) { - type = TYP_SIMD12; + if (hwintrinsic->GetHWIntrinsicId() != NI_Vector128_AsVector128Unsafe) + { + // Most nodes that have a simdSize of 12 are actually producing a TYP_SIMD12 + // and have been massaged to TYP_SIMD16 to match the actual product size. This + // is not the case for NI_Vector128_AsVector128Unsafe which is explicitly taking + // a TYP_SIMD12 and producing a TYP_SIMD16. + + type = TYP_SIMD12; + } } } } diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index b15a9988195e1..d04c5f10009b9 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -65,13 +65,11 @@ NamedIntrinsic SimdAsHWIntrinsicInfo::lookupId(Compiler* comp, return NI_Illegal; } - unsigned numArgs = sig->numArgs; - bool isInstanceMethod = false; + unsigned numArgs = sig->numArgs; if (sig->hasThis()) { - numArgs++; - isInstanceMethod = true; + return NI_Illegal; } if (classId == SimdAsHWIntrinsicClassId::Vector) @@ -79,8 +77,6 @@ NamedIntrinsic SimdAsHWIntrinsicInfo::lookupId(Compiler* comp, // We want to avoid doing anything that would unnecessarily trigger a recorded dependency against Vector // so we duplicate a few checks here to ensure this works smoothly for the static Vector class. - assert(!isInstanceMethod); - if (strcmp(methodName, "get_IsHardwareAccelerated") == 0) { return comp->IsBaselineSimdIsaSupported() ? NI_IsSupported_True : NI_IsSupported_False; @@ -128,11 +124,6 @@ NamedIntrinsic SimdAsHWIntrinsicInfo::lookupId(Compiler* comp, continue; } - if (isInstanceMethod != SimdAsHWIntrinsicInfo::IsInstanceMethod(intrinsicInfo.id)) - { - continue; - } - if (strcmp(methodName, intrinsicInfo.name) != 0) { continue; @@ -165,24 +156,6 @@ SimdAsHWIntrinsicClassId SimdAsHWIntrinsicInfo::lookupClassId(Compiler* comp, switch (className[0]) { - case 'P': - { - 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) @@ -196,18 +169,6 @@ SimdAsHWIntrinsicClassId SimdAsHWIntrinsicInfo::lookupClassId(Compiler* comp, { return SimdAsHWIntrinsicClassId::Vector; } - else 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 (strcmp(className, "`1") == 0) { uint32_t vectorTByteLength = comp->getVectorTByteLength(); @@ -253,7 +214,6 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, - GenTree* newobjThis, bool mustExpand) { if (!IsBaselineSimdIsaSupported()) @@ -270,13 +230,12 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, return nullptr; } - CORINFO_CLASS_HANDLE argClass = NO_CLASS_HANDLE; - var_types retType = genActualType(JITtype2varType(sig->retType)); - CorInfoType simdBaseJitType = CORINFO_TYPE_UNDEF; - var_types simdType = TYP_UNKNOWN; - unsigned simdSize = 0; - unsigned numArgs = sig->numArgs; - bool isInstanceMethod = false; + CORINFO_CLASS_HANDLE argClass = NO_CLASS_HANDLE; + var_types retType = genActualType(JITtype2varType(sig->retType)); + CorInfoType simdBaseJitType = CORINFO_TYPE_UNDEF; + var_types simdType = TYP_UNKNOWN; + unsigned simdSize = 0; + unsigned numArgs = sig->numArgs; // We want to resolve and populate the handle cache for this type even // if it isn't the basis for anything carried on the node. @@ -314,22 +273,10 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, } } - if (sig->hasThis()) - { - assert(SimdAsHWIntrinsicInfo::IsInstanceMethod(intrinsic)); - numArgs++; - - isInstanceMethod = true; - argClass = clsHnd; + assert(!sig->hasThis()); - if (SimdAsHWIntrinsicInfo::BaseTypeFromThisArg(intrinsic)) - { - assert((simdBaseJitType == CORINFO_TYPE_UNDEF) || (simdBaseJitType == CORINFO_TYPE_VALUECLASS)); - simdBaseJitType = getBaseJitTypeAndSizeOfSIMDType(clsHnd, &simdSize); - } - } - else if ((clsHnd == m_simdHandleCache->VectorHandle) && (numArgs != 0) && - !SimdAsHWIntrinsicInfo::KeepBaseTypeFromRet(intrinsic)) + if ((clsHnd == m_simdHandleCache->VectorHandle) && (numArgs != 0) && + !SimdAsHWIntrinsicInfo::KeepBaseTypeFromRet(intrinsic)) { // We need to fixup the clsHnd in the case we are an intrinsic on Vector // The first argument will be the appropriate Vector handle to use @@ -362,18 +309,14 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, return nullptr; } - if (SimdAsHWIntrinsicInfo::IsFloatingPointUsed(intrinsic)) - { - // Set `compFloatingPointUsed` to cover the scenario where an intrinsic - // is operating on SIMD fields, but where no SIMD local vars are in use. - compFloatingPointUsed = true; - } + // Set `compFloatingPointUsed` to cover the scenario where an intrinsic + // is operating on SIMD fields, but where no SIMD local vars are in use. + compFloatingPointUsed = true; if (hwIntrinsic == intrinsic) { // The SIMD intrinsic requires special handling outside the normal code path - return impSimdAsHWIntrinsicSpecial(intrinsic, clsHnd, sig, retType, simdBaseJitType, simdSize, newobjThis, - mustExpand); + return impSimdAsHWIntrinsicSpecial(intrinsic, clsHnd, sig, retType, simdBaseJitType, simdSize, mustExpand); } CORINFO_InstructionSet hwIntrinsicIsa = HWIntrinsicInfo::lookupIsa(hwIntrinsic); @@ -399,9 +342,8 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, case 1: { - argType = isInstanceMethod ? simdType - : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); - op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); + argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass); return gtNewSimdAsHWIntrinsicNode(retType, op1, hwIntrinsic, simdBaseJitType, simdSize); } @@ -410,20 +352,18 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, { if (SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic)) { - assert(newobjThis == nullptr); impSpillSideEffect(true, verCurrentState.esStackDepth - 2 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic")); } assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)); - CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList); + CORINFO_ARG_LIST_HANDLE arg2 = info.compCompHnd->getArgNext(argList); argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); op2 = getArgForHWIntrinsic(argType, argClass); - argType = isInstanceMethod ? simdType - : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); - op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); + argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass); return gtNewSimdAsHWIntrinsicNode(retType, op1, op2, hwIntrinsic, simdBaseJitType, simdSize); } @@ -455,7 +395,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, var_types retType, CorInfoType simdBaseJitType, unsigned simdSize, - GenTree* newobjThis, bool mustExpand) { var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); @@ -478,17 +417,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, GenTree* op4 = nullptr; GenTree* op5 = nullptr; - unsigned numArgs = sig->numArgs; - bool isInstanceMethod = false; - - if (sig->hasThis()) - { - assert(SimdAsHWIntrinsicInfo::IsInstanceMethod(intrinsic)); - numArgs++; - - isInstanceMethod = true; - argClass = clsHnd; - } + unsigned numArgs = sig->numArgs; + assert(!sig->hasThis()); #if defined(TARGET_XARCH) // We should have already exited early if SSE2 isn't supported @@ -544,8 +474,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } - case NI_Vector2_MultiplyAddEstimate: - case NI_Vector3_MultiplyAddEstimate: case NI_VectorT_MultiplyAddEstimate: { if (BlockNonDeterministicIntrinsics(mustExpand)) @@ -601,7 +529,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, #endif // TARGET_XARCH #if defined(TARGET_X86) - case NI_VectorT_CreateBroadcast: + case NI_VectorT_Create: { if (varTypeIsLong(simdBaseType) && !impStackTop(0).val->IsIntegralConst()) { @@ -728,8 +656,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } - case NI_Vector2_WithElement: - case NI_Vector3_WithElement: case NI_VectorT_WithElement: { assert(sig->numArgs == 3); @@ -810,8 +736,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } - case NI_Vector2_WithElement: - case NI_Vector3_WithElement: case NI_VectorT_WithElement: { assert(numArgs == 3); @@ -849,8 +773,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } #endif // TARGET_XARCH - case NI_Vector2_FusedMultiplyAdd: - case NI_Vector3_FusedMultiplyAdd: case NI_VectorT_FusedMultiplyAdd: { bool isFmaAccelerated = false; @@ -917,8 +839,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, { case 0: { - assert(newobjThis == nullptr); - switch (intrinsic) { case NI_VectorT_get_AllBitsSet: @@ -954,8 +874,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, case 1: { - assert(newobjThis == nullptr); - isOpExplicit |= (intrinsic == NI_VectorT_op_Explicit); if (isOpExplicit) @@ -970,14 +888,11 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return op1; } - argType = isInstanceMethod ? simdType - : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); - op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); + argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass); switch (intrinsic) { - case NI_Vector2_Abs: - case NI_Vector3_Abs: case NI_VectorT_Abs: { return gtNewSimdAbsNode(retType, op1, simdBaseJitType, simdSize); @@ -1026,8 +941,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdLoadNonTemporalNode(retType, op1, simdBaseJitType, simdSize); } - case NI_Vector2_op_UnaryNegation: - case NI_Vector3_op_UnaryNegation: case NI_VectorT_op_UnaryNegation: { return gtNewSimdUnOpNode(GT_NEG, retType, op1, simdBaseJitType, simdSize); @@ -1038,8 +951,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdUnOpNode(GT_NOT, retType, op1, simdBaseJitType, simdSize); } - case NI_Vector2_Sqrt: - case NI_Vector3_Sqrt: case NI_VectorT_Sqrt: { return gtNewSimdSqrtNode(retType, op1, simdBaseJitType, simdSize); @@ -1257,7 +1168,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, case 2: { - if (SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic) && (newobjThis == nullptr)) + if (SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic)) { impSpillSideEffect(true, verCurrentState.esStackDepth - 2 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic")); @@ -1265,30 +1176,16 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)); - CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList); + CORINFO_ARG_LIST_HANDLE arg2 = info.compCompHnd->getArgNext(argList); argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); op2 = getArgForHWIntrinsic(argType, argClass); - bool implicitConstructor = isInstanceMethod && (newobjThis == nullptr) && (retType == TYP_VOID); - - if (implicitConstructor) - { - op1 = getArgForHWIntrinsic(TYP_BYREF, argClass, isInstanceMethod, newobjThis); - } - else - { - argType = isInstanceMethod - ? simdType - : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); - op1 = getArgForHWIntrinsic(argType, (newobjThis != nullptr) ? clsHnd : argClass, isInstanceMethod, - newobjThis); - } + op1 = getArgForHWIntrinsic(argType, argClass); switch (intrinsic) { - case NI_Vector2_op_Addition: - case NI_Vector3_op_Addition: case NI_VectorT_op_Addition: { return gtNewSimdBinOpNode(GT_ADD, retType, op1, op2, simdBaseJitType, simdSize); @@ -1309,9 +1206,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdBinOpNode(GT_OR, retType, op1, op2, simdBaseJitType, simdSize); } - case NI_Vector2_CreateBroadcast: - case NI_Vector3_CreateBroadcast: - case NI_VectorT_CreateBroadcast: + case NI_VectorT_Create: { assert(retType == TYP_VOID); @@ -1325,15 +1220,11 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdCreateSequenceNode(simdType, op1, op2, simdBaseJitType, simdSize); } - case NI_Vector2_op_Division: - case NI_Vector3_op_Division: case NI_VectorT_op_Division: { return gtNewSimdBinOpNode(GT_DIV, retType, op1, op2, simdBaseJitType, simdSize); } - case NI_Vector2_Dot: - case NI_Vector3_Dot: case NI_VectorT_Dot: { op1 = gtNewSimdDotProdNode(simdType, op1, op2, simdBaseJitType, simdSize); @@ -1345,8 +1236,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdCmpOpNode(GT_EQ, retType, op1, op2, simdBaseJitType, simdSize); } - case NI_Vector2_op_Equality: - case NI_Vector3_op_Equality: case NI_VectorT_op_Equality: { return gtNewSimdCmpOpAllNode(GT_EQ, retType, op1, op2, simdBaseJitType, simdSize); @@ -1362,8 +1251,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdBinOpNode(GT_XOR, retType, op1, op2, simdBaseJitType, simdSize); } - case NI_Vector2_GetElement: - case NI_Vector3_GetElement: case NI_VectorT_GetElement: { return gtNewSimdGetElementNode(retType, op1, op2, simdBaseJitType, simdSize); @@ -1399,8 +1286,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdCmpOpAnyNode(GT_GE, retType, op1, op2, simdBaseJitType, simdSize); } - case NI_Vector2_op_Inequality: - case NI_Vector3_op_Inequality: case NI_VectorT_op_Inequality: { return gtNewSimdCmpOpAnyNode(GT_NE, retType, op1, op2, simdBaseJitType, simdSize); @@ -1453,22 +1338,16 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdLoadNode(retType, op1, simdBaseJitType, simdSize); } - case NI_Vector2_Max: - case NI_Vector3_Max: case NI_VectorT_Max: { return gtNewSimdMaxNode(retType, op1, op2, simdBaseJitType, simdSize); } - case NI_Vector2_Min: - case NI_Vector3_Min: case NI_VectorT_Min: { return gtNewSimdMinNode(retType, op1, op2, simdBaseJitType, simdSize); } - case NI_Vector2_op_Multiply: - case NI_Vector3_op_Multiply: case NI_VectorT_op_Multiply: { return gtNewSimdBinOpNode(GT_MUL, retType, op1, op2, simdBaseJitType, simdSize); @@ -1534,8 +1413,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdStoreNonTemporalNode(op2, op1, simdBaseJitType, simdSize); } - case NI_Vector2_op_Subtraction: - case NI_Vector3_op_Subtraction: case NI_VectorT_op_Subtraction: { return gtNewSimdBinOpNode(GT_SUB, retType, op1, op2, simdBaseJitType, simdSize); @@ -1553,19 +1430,19 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, case 3: { - if (SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic) && (newobjThis == nullptr)) + if (SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic)) { impSpillSideEffect(true, verCurrentState.esStackDepth - 3 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic")); } - if (SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic) && (newobjThis == nullptr)) + if (SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)) { 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 arg2 = info.compCompHnd->getArgNext(argList); CORINFO_ARG_LIST_HANDLE arg3 = info.compCompHnd->getArgNext(arg2); argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg3, &argClass))); @@ -1574,21 +1451,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); op2 = getArgForHWIntrinsic(argType, argClass); - bool implicitConstructor = isInstanceMethod && (newobjThis == nullptr) && (retType == TYP_VOID); - - if (implicitConstructor) - { - op1 = getArgForHWIntrinsic(TYP_BYREF, argClass, isInstanceMethod, newobjThis); - } - else - { - argType = isInstanceMethod - ? simdType - : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); - - op1 = getArgForHWIntrinsic(argType, (newobjThis != nullptr) ? clsHnd : argClass, isInstanceMethod, - newobjThis); - } + argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass); switch (intrinsic) { @@ -1597,55 +1461,11 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdCndSelNode(retType, op1, op2, op3, simdBaseJitType, simdSize); } - case NI_Vector2_FusedMultiplyAdd: - case NI_Vector3_FusedMultiplyAdd: case NI_VectorT_FusedMultiplyAdd: { return gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); } - case NI_Vector2_Lerp: - case NI_Vector3_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); -#endif // TARGET_XARCH - - // clonedOp3 = op3 - GenTree* clonedOp3; - op3 = impCloneExpr(op3, &clonedOp3, 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); -#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); - - // op2 *= clonedOp3 - op2 = gtNewSimdBinOpNode(GT_MUL, retType, op2, clonedOp3, simdBaseJitType, simdSize); - - // return op1 + op2 - return gtNewSimdBinOpNode(GT_ADD, retType, op1, op2, simdBaseJitType, simdSize); - } - - case NI_Vector2_MultiplyAddEstimate: - case NI_Vector3_MultiplyAddEstimate: case NI_VectorT_MultiplyAddEstimate: { bool isFmaAccelerated = false; @@ -1683,88 +1503,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdStoreNode(op2, op1, simdBaseJitType, simdSize); } - case NI_Vector2_Create: - { - assert(retType == TYP_VOID); - assert(simdBaseType == TYP_FLOAT); - assert(simdSize == 8); - - if (op2->IsCnsFltOrDbl() && op3->IsCnsFltOrDbl()) - { - GenTreeVecCon* vecCon = gtNewVconNode(TYP_SIMD8); - - float cnsVal = 0; - - vecCon->gtSimdVal.f32[0] = static_cast(op2->AsDblCon()->DconValue()); - vecCon->gtSimdVal.f32[1] = static_cast(op3->AsDblCon()->DconValue()); - - copyBlkSrc = vecCon; - } - else if (areArgumentsContiguous(op2, op3)) - { - GenTree* op2Address = CreateAddressNodeForSimdHWIntrinsicCreate(op2, simdBaseType, 8); - copyBlkSrc = gtNewIndir(TYP_SIMD8, op2Address); - } - else - { -#if defined(TARGET_XARCH) - IntrinsicNodeBuilder nodeBuilder(getAllocator(CMK_ASTNode), 4); - - nodeBuilder.AddOperand(0, op2); - nodeBuilder.AddOperand(1, op3); - nodeBuilder.AddOperand(2, gtNewZeroConNode(TYP_FLOAT)); - nodeBuilder.AddOperand(3, gtNewZeroConNode(TYP_FLOAT)); - - copyBlkSrc = gtNewSimdHWIntrinsicNode(TYP_SIMD8, std::move(nodeBuilder), NI_Vector128_Create, - simdBaseJitType, 16); -#elif defined(TARGET_ARM64) - copyBlkSrc = - gtNewSimdHWIntrinsicNode(TYP_SIMD8, op2, op3, NI_Vector64_Create, simdBaseJitType, 8); -#else -#error Unsupported platform -#endif // !TARGET_XARCH && !TARGET_ARM64 - } - - copyBlkDst = op1; - break; - } - - case NI_Vector3_CreateFromVector2: - { - assert(retType == TYP_VOID); - assert(simdBaseType == TYP_FLOAT); - assert(simdSize == 12); - assert(simdType == TYP_SIMD12); - - // TODO-CQ: We should be able to check for contiguous args here after - // the relevant methods are updated to support more than just float - - if (op2->IsCnsVec() && op3->IsCnsFltOrDbl()) - { - GenTreeVecCon* vecCon = op2->AsVecCon(); - vecCon->gtType = simdType; - - vecCon->gtSimdVal.f32[2] = static_cast(op3->AsDblCon()->DconValue()); - copyBlkSrc = vecCon; - } - else - { - GenTree* idx = gtNewIconNode(2, TYP_INT); - - op2 = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op2, NI_Vector128_AsVector128Unsafe, simdBaseJitType, - 12); - op2 = gtNewSimdWithElementNode(TYP_SIMD16, op2, idx, op3, simdBaseJitType, 16); - - copyBlkSrc = - gtNewSimdHWIntrinsicNode(TYP_SIMD12, op2, NI_Vector128_AsVector3, simdBaseJitType, 16); - } - - copyBlkDst = op1; - break; - } - - case NI_Vector2_WithElement: - case NI_Vector3_WithElement: case NI_VectorT_WithElement: { return gtNewSimdWithElementNode(retType, op1, op2, op3, simdBaseJitType, simdSize); @@ -1779,93 +1517,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } break; } - - case 4: - { - assert(isInstanceMethod); - assert(SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic)); - assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)); - - if (newobjThis == nullptr) - { - impSpillSideEffect(true, verCurrentState.esStackDepth - - 4 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic")); - } - - CORINFO_ARG_LIST_HANDLE arg2 = argList; - CORINFO_ARG_LIST_HANDLE arg3 = info.compCompHnd->getArgNext(arg2); - CORINFO_ARG_LIST_HANDLE arg4 = info.compCompHnd->getArgNext(arg3); - - argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg4, &argClass))); - op4 = getArgForHWIntrinsic(argType, argClass); - - argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg3, &argClass))); - op3 = getArgForHWIntrinsic(argType, argClass); - - argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); - op2 = getArgForHWIntrinsic(argType, argClass); - - if ((newobjThis == nullptr) && (retType == TYP_VOID)) - { - op1 = getArgForHWIntrinsic(TYP_BYREF, argClass, isInstanceMethod, newobjThis); - } - else - { - op1 = getArgForHWIntrinsic(simdType, (newobjThis != nullptr) ? clsHnd : argClass, isInstanceMethod, - newobjThis); - } - - switch (intrinsic) - { - case NI_Vector3_Create: - { - assert(retType == TYP_VOID); - assert(simdBaseType == TYP_FLOAT); - assert(simdSize == 12); - - if (op2->IsCnsFltOrDbl() && op3->IsCnsFltOrDbl() && op4->IsCnsFltOrDbl()) - { - GenTreeVecCon* vecCon = gtNewVconNode(TYP_SIMD12); - - float cnsVal = 0; - - vecCon->gtSimdVal.f32[0] = static_cast(op2->AsDblCon()->DconValue()); - vecCon->gtSimdVal.f32[1] = static_cast(op3->AsDblCon()->DconValue()); - vecCon->gtSimdVal.f32[2] = static_cast(op4->AsDblCon()->DconValue()); - - copyBlkSrc = vecCon; - } - else if (areArgumentsContiguous(op2, op3) && areArgumentsContiguous(op3, op4)) - { - GenTree* op2Address = CreateAddressNodeForSimdHWIntrinsicCreate(op2, simdBaseType, 12); - copyBlkSrc = gtNewIndir(TYP_SIMD12, op2Address); - } - else - { - IntrinsicNodeBuilder nodeBuilder(getAllocator(CMK_ASTNode), 4); - - nodeBuilder.AddOperand(0, op2); - nodeBuilder.AddOperand(1, op3); - nodeBuilder.AddOperand(2, op4); - nodeBuilder.AddOperand(3, gtNewZeroConNode(TYP_FLOAT)); - - copyBlkSrc = gtNewSimdHWIntrinsicNode(TYP_SIMD12, std::move(nodeBuilder), NI_Vector128_Create, - simdBaseJitType, 16); - } - - copyBlkDst = op1; - break; - } - - default: - { - // Some platforms warn about unhandled switch cases - // We handle it more generally via the assert and nullptr return below. - break; - } - } - break; - } } if (copyBlkDst != nullptr) diff --git a/src/coreclr/jit/simdashwintrinsic.h b/src/coreclr/jit/simdashwintrinsic.h index d42fff256ab8e..77fc25ae74f4e 100644 --- a/src/coreclr/jit/simdashwintrinsic.h +++ b/src/coreclr/jit/simdashwintrinsic.h @@ -7,11 +7,6 @@ enum class SimdAsHWIntrinsicClassId { Unknown, - Plane, - Quaternion, - Vector2, - Vector3, - Vector4, Vector, VectorT, }; @@ -20,25 +15,14 @@ enum class SimdAsHWIntrinsicFlag : unsigned int { None = 0, - // Indicates compFloatingPointUsed does not need to be set. - NoFloatingPointUsed = 0x1, - - // Indicates the intrinsic is for an instance method. - InstanceMethod = 0x02, - - /* UnusedFlag = 0x04, */ - - // Base type should come from the this argument - BaseTypeFromThisArg = 0x08, - // For SIMDVectorHandle, keep the base type from the result type - KeepBaseTypeFromRet = 0x10, + KeepBaseTypeFromRet = 0x01, // Indicates that side effects need to be spilled for op1 - SpillSideEffectsOp1 = 0x20, + SpillSideEffectsOp1 = 0x02, // Indicates that side effects need to be spilled for op2 - SpillSideEffectsOp2 = 0x40, + SpillSideEffectsOp2 = 0x04, }; inline SimdAsHWIntrinsicFlag operator~(SimdAsHWIntrinsicFlag value) @@ -121,24 +105,6 @@ struct SimdAsHWIntrinsicInfo // Flags lookup - static bool IsFloatingPointUsed(NamedIntrinsic id) - { - SimdAsHWIntrinsicFlag flags = lookupFlags(id); - return (flags & SimdAsHWIntrinsicFlag::NoFloatingPointUsed) == SimdAsHWIntrinsicFlag::None; - } - - static bool IsInstanceMethod(NamedIntrinsic id) - { - SimdAsHWIntrinsicFlag flags = lookupFlags(id); - return (flags & SimdAsHWIntrinsicFlag::InstanceMethod) == SimdAsHWIntrinsicFlag::InstanceMethod; - } - - static bool BaseTypeFromThisArg(NamedIntrinsic id) - { - SimdAsHWIntrinsicFlag flags = lookupFlags(id); - return (flags & SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) == SimdAsHWIntrinsicFlag::BaseTypeFromThisArg; - } - static bool KeepBaseTypeFromRet(NamedIntrinsic id) { SimdAsHWIntrinsicFlag flags = lookupFlags(id); diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index bcf8364e75d6f..efb3107930b03 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -32,57 +32,6 @@ * Each intrinsic has one or more flags with type of `enum SimdAsHWIntrinsicFlag` */ -// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// 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_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, 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, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) -SIMD_AS_HWINTRINSIC_ID(Vector2, GetElement, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_GetElement, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -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, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_MultiplyAddEstimate, 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) -SIMD_AS_HWINTRINSIC_ID(Vector2, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector2, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -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, WithElement, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_WithElement, 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} -// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// 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_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 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) -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, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) -SIMD_AS_HWINTRINSIC_ID(Vector3, GetElement, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_GetElement, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -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, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_MultiplyAddEstimate, 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) -SIMD_AS_HWINTRINSIC_ID(Vector3, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector3, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -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, WithElement, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_WithElement, 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} @@ -115,7 +64,7 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32, SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64Native}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_NM(VectorT, CreateBroadcast, ".ctor", 2, {NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(VectorT, Create, 1, {NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, CreateSequence, 2, {NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, Dot, 2, {NI_VectorT_Dot, NI_VectorT_Dot, NI_VectorT_Dot, NI_VectorT_Dot, NI_VectorT_Dot, NI_VectorT_Dot, NI_Illegal, NI_Illegal, NI_VectorT_Dot, NI_VectorT_Dot}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Equals, 2, {NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index f8ccbeb90cb08..4074204e29ea4 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -32,57 +32,6 @@ * Each intrinsic has one or more flags with type of `enum SimdAsHWIntrinsicFlag` */ -// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// 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_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, 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, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector2, GetElement, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_GetElement, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -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, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_MultiplyAddEstimate, 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) -SIMD_AS_HWINTRINSIC_ID(Vector2, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector2, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -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, WithElement, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_WithElement, 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} -// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// 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_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 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) -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, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector3, GetElement, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_GetElement, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -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, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_MultiplyAddEstimate, 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) -SIMD_AS_HWINTRINSIC_ID(Vector3, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector3, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -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, WithElement, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_WithElement, 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} @@ -115,7 +64,7 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32, SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64Native}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_NM(VectorT, CreateBroadcast, ".ctor", 2, {NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(VectorT, Create, 1, {NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create, NI_VectorT_Create}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, CreateSequence, 2, {NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, Dot, 2, {NI_Illegal, NI_Illegal, NI_VectorT_Dot, NI_VectorT_Dot, NI_VectorT_Dot, NI_VectorT_Dot, NI_Illegal, NI_Illegal, NI_VectorT_Dot, NI_VectorT_Dot}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Equals, 2, {NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals, NI_VectorT_Equals}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index 98b2db5e13365..13b94b02fd2cf 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -207,6 +207,16 @@ public static partial class Vector public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AndNot(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector As(this System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Plane AsPlane(this System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Quaternion AsQuaternion(this System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector2 AsVector2(this System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector3 AsVector3(this System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector4 AsVector4(this System.Numerics.Plane value) { throw null; } + public static System.Numerics.Vector4 AsVector4(this System.Numerics.Quaternion value) { throw null; } + public static System.Numerics.Vector4 AsVector4(this System.Numerics.Vector2 value) { throw null; } + public static System.Numerics.Vector4 AsVector4(this System.Numerics.Vector3 value) { throw null; } + public static System.Numerics.Vector4 AsVector4Unsafe(this System.Numerics.Vector2 value) { throw null; } + public static System.Numerics.Vector4 AsVector4Unsafe(this System.Numerics.Vector3 value) { throw null; } public static System.Numerics.Vector AsVectorByte(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector AsVectorDouble(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector AsVectorInt16(System.Numerics.Vector value) { throw null; } @@ -249,6 +259,8 @@ public static partial class Vector public static System.Numerics.Vector ConvertToUInt64(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToUInt64Native(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Create(T value) { throw null; } + public static System.Numerics.Vector Create(System.ReadOnlySpan values) { throw null; } public static System.Numerics.Vector CreateSequence(T start, T step) { throw null; } public static System.Numerics.Vector Divide(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Divide(System.Numerics.Vector left, T right) { throw null; } @@ -426,6 +438,9 @@ public partial struct Vector2 : System.IEquatable, Syst 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; } public static System.Numerics.Vector2 Clamp(System.Numerics.Vector2 value1, System.Numerics.Vector2 min, System.Numerics.Vector2 max) { throw null; } + public static System.Numerics.Vector2 Create(float value) { throw null; } + public static System.Numerics.Vector2 Create(float x, float y) { throw null; } + public static System.Numerics.Vector2 Create(System.ReadOnlySpan values) { throw null; } public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } public readonly void CopyTo(System.Span destination) { } @@ -490,6 +505,10 @@ public partial struct Vector3 : System.IEquatable, Syst 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; } public static System.Numerics.Vector3 Clamp(System.Numerics.Vector3 value1, System.Numerics.Vector3 min, System.Numerics.Vector3 max) { throw null; } + public static System.Numerics.Vector3 Create(float value) { throw null; } + public static System.Numerics.Vector3 Create(System.Numerics.Vector2 vector, float z) { throw null; } + public static System.Numerics.Vector3 Create(float x, float y, float z) { throw null; } + public static System.Numerics.Vector3 Create(System.ReadOnlySpan values) { throw null; } public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } public readonly void CopyTo(System.Span destination) { } @@ -556,6 +575,11 @@ public partial struct Vector4 : System.IEquatable, Syst 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; } public static System.Numerics.Vector4 Clamp(System.Numerics.Vector4 value1, System.Numerics.Vector4 min, System.Numerics.Vector4 max) { throw null; } + public static System.Numerics.Vector4 Create(float value) { throw null; } + public static System.Numerics.Vector4 Create(System.Numerics.Vector2 vector, float z, float w) { throw null; } + public static System.Numerics.Vector4 Create(System.Numerics.Vector3 vector, float w) { throw null; } + public static System.Numerics.Vector4 Create(float x, float y, float z, float w) { throw null; } + public static System.Numerics.Vector4 Create(System.ReadOnlySpan values) { throw null; } public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } public readonly void CopyTo(System.Span destination) { } diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 4d68dc5729e26..77475d432d57a 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -599,6 +599,7 @@ + @@ -2794,4 +2795,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.Impl.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.Impl.cs index 4fb270baa096b..7d270c17cc0de 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.Impl.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.Impl.cs @@ -32,7 +32,7 @@ internal struct Impl : IEquatable [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref Matrix3x2 AsM3x2() => ref Unsafe.As(ref this); - private const float RotationEpsilon = 0.001f * MathF.PI / 180f; // 0.1% of a degree + private const float RotationEpsilon = 0.001f * float.Pi / 180f; // 0.1% of a degree public Vector2 X; public Vector2 Y; @@ -43,9 +43,9 @@ public void Init(float m11, float m12, float m21, float m22, float m31, float m32) { - X = new Vector2(m11, m12); - Y = new Vector2(m21, m22); - Z = new Vector2(m31, m32); + X = Vector2.Create(m11, m12); + Y = Vector2.Create(m21, m22); + Z = Vector2.Create(m31, m32); } public static Impl Identity @@ -146,15 +146,15 @@ readonly get { Impl result; - result.X = new Vector2( + result.X = Vector2.Create( left.X.X * right.X.X + left.X.Y * right.Y.X, left.X.X * right.X.Y + left.X.Y * right.Y.Y ); - result.Y = new Vector2( + result.Y = Vector2.Create( left.Y.X * right.X.X + left.Y.Y * right.Y.X, left.Y.X * right.X.Y + left.Y.Y * right.Y.Y ); - result.Z = new Vector2( + result.Z = Vector2.Create( left.Z.X * right.X.X + left.Z.Y * right.Y.X + right.Z.X, left.Z.X * right.X.Y + left.Z.Y * right.Y.Y + right.Z.Y ); @@ -201,7 +201,7 @@ readonly get [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl CreateRotation(float radians) { - radians = MathF.IEEERemainder(radians, MathF.PI * 2); + radians = float.Ieee754Remainder(radians, float.Tau); float c; float s; @@ -212,19 +212,19 @@ public static Impl CreateRotation(float radians) c = 1; s = 0; } - else if (radians > MathF.PI / 2 - RotationEpsilon && radians < MathF.PI / 2 + RotationEpsilon) + else if (radians > float.Pi / 2 - RotationEpsilon && radians < float.Pi / 2 + RotationEpsilon) { // Exact case for 90 degree rotation. c = 0; s = 1; } - else if (radians < -MathF.PI + RotationEpsilon || radians > MathF.PI - RotationEpsilon) + else if (radians < -float.Pi + RotationEpsilon || radians > float.Pi - RotationEpsilon) { // Exact case for 180 degree rotation. c = -1; s = 0; } - else if (radians > -MathF.PI / 2 - RotationEpsilon && radians < -MathF.PI / 2 + RotationEpsilon) + else if (radians > -float.Pi / 2 - RotationEpsilon && radians < -float.Pi / 2 + RotationEpsilon) { // Exact case for 270 degree rotation. c = 0; @@ -233,8 +233,7 @@ public static Impl CreateRotation(float radians) else { // Arbitrary rotation. - c = MathF.Cos(radians); - s = MathF.Sin(radians); + (s, c) = float.SinCos(radians); } // [ c s ] @@ -243,8 +242,8 @@ public static Impl CreateRotation(float radians) Impl result; - result.X = new Vector2( c, s); - result.Y = new Vector2(-s, c); + result.X = Vector2.Create( c, s); + result.Y = Vector2.Create(-s, c); result.Z = Vector2.Zero; return result; @@ -253,7 +252,7 @@ public static Impl CreateRotation(float radians) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl CreateRotation(float radians, Vector2 centerPoint) { - radians = MathF.IEEERemainder(radians, MathF.PI * 2); + radians = float.Ieee754Remainder(radians, float.Tau); float c, s; @@ -263,19 +262,19 @@ public static Impl CreateRotation(float radians, Vector2 centerPoint) c = 1; s = 0; } - else if (radians > MathF.PI / 2 - RotationEpsilon && radians < MathF.PI / 2 + RotationEpsilon) + else if (radians > float.Pi / 2 - RotationEpsilon && radians < float.Pi / 2 + RotationEpsilon) { // Exact case for 90 degree rotation. c = 0; s = 1; } - else if (radians < -MathF.PI + RotationEpsilon || radians > MathF.PI - RotationEpsilon) + else if (radians < -float.Pi + RotationEpsilon || radians > float.Pi - RotationEpsilon) { // Exact case for 180 degree rotation. c = -1; s = 0; } - else if (radians > -MathF.PI / 2 - RotationEpsilon && radians < -MathF.PI / 2 + RotationEpsilon) + else if (radians > -float.Pi / 2 - RotationEpsilon && radians < -float.Pi / 2 + RotationEpsilon) { // Exact case for 270 degree rotation. c = 0; @@ -284,8 +283,7 @@ public static Impl CreateRotation(float radians, Vector2 centerPoint) else { // Arbitrary rotation. - c = MathF.Cos(radians); - s = MathF.Sin(radians); + (s, c) = float.SinCos(radians); } float x = centerPoint.X * (1 - c) + centerPoint.Y * s; @@ -297,9 +295,9 @@ public static Impl CreateRotation(float radians, Vector2 centerPoint) Impl result; - result.X = new Vector2( c, s); - result.Y = new Vector2(-s, c); - result.Z = new Vector2( x, y); + result.X = Vector2.Create( c, s); + result.Y = Vector2.Create(-s, c); + result.Z = Vector2.Create( x, y); return result; } @@ -309,8 +307,8 @@ public static Impl CreateScale(Vector2 scales) { Impl result; - result.X = new Vector2(scales.X, 0); - result.Y = new Vector2(0, scales.Y); + result.X = Vector2.CreateScalar(scales.X); + result.Y = Vector2.Create(0, scales.Y); result.Z = Vector2.Zero; return result; @@ -321,8 +319,8 @@ public static Impl CreateScale(float scaleX, float scaleY) { Impl result; - result.X = new Vector2(scaleX, 0); - result.Y = new Vector2(0, scaleY); + result.X = Vector2.CreateScalar(scaleX); + result.Y = Vector2.Create(0, scaleY); result.Z = Vector2.Zero; return result; @@ -333,9 +331,9 @@ public static Impl CreateScale(float scaleX, float scaleY, Vector2 centerPoint) { Impl result; - result.X = new Vector2(scaleX, 0); - result.Y = new Vector2(0, scaleY); - result.Z = centerPoint * (Vector2.One - new Vector2(scaleX, scaleY)); + result.X = Vector2.CreateScalar(scaleX); + result.Y = Vector2.Create(0, scaleY); + result.Z = centerPoint * (Vector2.One - Vector2.Create(scaleX, scaleY)); return result; } @@ -345,8 +343,8 @@ public static Impl CreateScale(Vector2 scales, Vector2 centerPoint) { Impl result; - result.X = new Vector2(scales.X, 0); - result.Y = new Vector2(0, scales.Y); + result.X = Vector2.CreateScalar(scales.X); + result.Y = Vector2.Create(0, scales.Y); result.Z = centerPoint * (Vector2.One - scales); return result; @@ -357,8 +355,8 @@ public static Impl CreateScale(float scale) { Impl result; - result.X = new Vector2(scale, 0); - result.Y = new Vector2(0, scale); + result.X = Vector2.CreateScalar(scale); + result.Y = Vector2.Create(0, scale); result.Z = Vector2.Zero; return result; @@ -369,9 +367,9 @@ public static Impl CreateScale(float scale, Vector2 centerPoint) { Impl result; - result.X = new Vector2(scale, 0); - result.Y = new Vector2(0, scale); - result.Z = centerPoint * (Vector2.One - new Vector2(scale)); + result.X = Vector2.CreateScalar(scale); + result.Y = Vector2.Create(0, scale); + result.Z = centerPoint * (Vector2.One - Vector2.Create(scale)); return result; } @@ -381,8 +379,8 @@ public static Impl CreateSkew(float radiansX, float radiansY) { Impl result; - result.X = new Vector2(1, MathF.Tan(radiansY)); - result.Y = new Vector2(MathF.Tan(radiansX), 1); + result.X = Vector2.Create(1, float.Tan(radiansY)); + result.Y = Vector2.Create(float.Tan(radiansX), 1); result.Z = Vector2.Zero; return result; @@ -391,17 +389,17 @@ public static Impl CreateSkew(float radiansX, float radiansY) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl CreateSkew(float radiansX, float radiansY, Vector2 centerPoint) { - float xTan = MathF.Tan(radiansX); - float yTan = MathF.Tan(radiansY); + float xTan = float.Tan(radiansX); + float yTan = float.Tan(radiansY); float tx = -centerPoint.Y * xTan; float ty = -centerPoint.X * yTan; Impl result; - result.X = new Vector2(1, yTan); - result.Y = new Vector2(xTan, 1); - result.Z = new Vector2(tx, ty); + result.X = Vector2.Create(1, yTan); + result.Y = Vector2.Create(xTan, 1); + result.Z = Vector2.Create(tx, ty); return result; } @@ -425,7 +423,7 @@ public static Impl CreateTranslation(float positionX, float positionY) result.X = Vector2.UnitX; result.Y = Vector2.UnitY; - result.Z = new Vector2(positionX, positionY); + result.Z = Vector2.Create(positionX, positionY); return result; } @@ -435,9 +433,9 @@ public static bool Invert(in Impl matrix, out Impl result) { float det = (matrix.X.X * matrix.Y.Y) - (matrix.Y.X * matrix.X.Y); - if (MathF.Abs(det) < float.Epsilon) + if (float.Abs(det) < float.Epsilon) { - Vector2 vNaN = new Vector2(float.NaN); + Vector2 vNaN = Vector2.Create(float.NaN); result.X = vNaN; result.Y = vNaN; @@ -448,15 +446,15 @@ public static bool Invert(in Impl matrix, out Impl result) float invDet = 1.0f / det; - result.X = new Vector2( + result.X = Vector2.Create( +matrix.Y.Y * invDet, -matrix.X.Y * invDet ); - result.Y = new Vector2( + result.Y = Vector2.Create( -matrix.Y.X * invDet, +matrix.X.X * invDet ); - result.Z = new Vector2( + result.Z = Vector2.Create( (matrix.Y.X * matrix.Z.Y - matrix.Z.X * matrix.Y.Y) * invDet, (matrix.Z.X * matrix.X.Y - matrix.X.X * matrix.Z.Y) * invDet ); diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.Impl.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.Impl.cs index 492eda1b452d0..79e96fd05dd5d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.Impl.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.Impl.cs @@ -38,7 +38,7 @@ internal struct Impl : IEquatable public ref Matrix4x4 AsM4x4() => ref Unsafe.As(ref this); private const float BillboardEpsilon = 1e-4f; - private const float BillboardMinAngle = 1.0f - (0.1f * (MathF.PI / 180.0f)); // 0.1 degrees + private const float BillboardMinAngle = 1.0f - (0.1f * (float.Pi / 180.0f)); // 0.1 degrees private const float DecomposeEpsilon = 0.0001f; public Vector4 X; @@ -52,19 +52,19 @@ public void Init(float m11, float m12, float m13, float m14, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44) { - X = new Vector4(m11, m12, m13, m14); - Y = new Vector4(m21, m22, m23, m24); - Z = new Vector4(m31, m32, m33, m34); - W = new Vector4(m41, m42, m43, m44); + X = Vector4.Create(m11, m12, m13, m14); + Y = Vector4.Create(m21, m22, m23, m24); + Z = Vector4.Create(m31, m32, m33, m34); + W = Vector4.Create(m41, m42, m43, m44); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Init(in Matrix3x2.Impl value) { - X = new Vector4(value.X, 0, 0); - Y = new Vector4(value.Y, 0, 0); + X = Vector4.Create(value.X, 0, 0); + Y = Vector4.Create(value.Y, 0, 0); Z = Vector4.UnitZ; - W = new Vector4(value.Z, 0, 1); + W = Vector4.Create(value.Z, 0, 1); } public static Impl Identity @@ -122,12 +122,12 @@ public readonly bool IsIdentity public Vector3 Translation { [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get => new Vector3(W.X, W.Y, W.Z); + readonly get => W.AsVector3(); [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - W = new Vector4(value, W.W); + W = Vector4.Create(value, W.W); } } @@ -245,7 +245,7 @@ public static Impl CreateBillboard(in Vector3 objectPosition, in Vector3 cameraP } else { - axisZ = Vector3.Multiply(axisZ, 1.0f / MathF.Sqrt(norm)); + axisZ = Vector3.Multiply(axisZ, 1.0f / float.Sqrt(norm)); } Vector3 axisX = Vector3.Normalize(Vector3.Cross(cameraUpVector, axisZ)); @@ -253,10 +253,10 @@ public static Impl CreateBillboard(in Vector3 objectPosition, in Vector3 cameraP Impl result; - result.X = new Vector4(axisX, 0); - result.Y = new Vector4(axisY, 0); - result.Z = new Vector4(axisZ, 0); - result.W = new Vector4(objectPosition, 1); + result.X = axisX.AsVector4(); + result.Y = axisY.AsVector4(); + result.Z = axisZ.AsVector4();; + result.W = Vector4.Create(objectPosition, 1); return result; } @@ -274,7 +274,7 @@ public static Impl CreateConstrainedBillboard(in Vector3 objectPosition, in Vect } else { - faceDir = Vector3.Multiply(faceDir, (1.0f / MathF.Sqrt(norm))); + faceDir = Vector3.Multiply(faceDir, (1.0f / float.Sqrt(norm))); } Vector3 axisY = rotateAxis; @@ -282,16 +282,16 @@ public static Impl CreateConstrainedBillboard(in Vector3 objectPosition, in Vect // Treat the case when angle between faceDir and rotateAxis is too close to 0. float dot = Vector3.Dot(axisY, faceDir); - if (MathF.Abs(dot) > BillboardMinAngle) + if (float.Abs(dot) > BillboardMinAngle) { faceDir = objectForwardVector; // Make sure passed values are useful for compute. dot = Vector3.Dot(axisY, faceDir); - if (MathF.Abs(dot) > BillboardMinAngle) + if (float.Abs(dot) > BillboardMinAngle) { - faceDir = (MathF.Abs(axisY.Z) > BillboardMinAngle) ? Vector3.UnitX : new Vector3(0, 0, -1); + faceDir = (float.Abs(axisY.Z) > BillboardMinAngle) ? Vector3.UnitX : Vector3.Create(0, 0, -1); } } @@ -300,10 +300,10 @@ public static Impl CreateConstrainedBillboard(in Vector3 objectPosition, in Vect Impl result; - result.X = new Vector4(axisX, 0); - result.Y = new Vector4(axisY, 0); - result.Z = new Vector4(axisZ, 0); - result.W = new Vector4(objectPosition, 1); + result.X = axisX.AsVector4(); + result.Y = axisY.AsVector4(); + result.Z = axisZ.AsVector4(); + result.W = Vector4.Create(objectPosition, 1); return result; } @@ -341,8 +341,7 @@ public static Impl CreateFromAxisAngle(in Vector3 axis, float angle) float y = axis.Y; float z = axis.Z; - float sa = MathF.Sin(angle); - float ca = MathF.Cos(angle); + (float sa, float ca) = float.SinCos(angle); float xx = x * x; float yy = y * y; @@ -354,19 +353,19 @@ public static Impl CreateFromAxisAngle(in Vector3 axis, float angle) Impl result; - result.X = new Vector4( + result.X = Vector4.Create( xx + ca * (1.0f - xx), xy - ca * xy + sa * z, xz - ca * xz - sa * y, 0 ); - result.Y = new Vector4( + result.Y = Vector4.Create( xy - ca * xy - sa * z, yy + ca * (1.0f - yy), yz - ca * yz + sa * x, 0 ); - result.Z = new Vector4( + result.Z = Vector4.Create( xz - ca * xz + sa * y, yz - ca * yz - sa * x, zz + ca * (1.0f - zz), @@ -393,19 +392,19 @@ public static Impl CreateFromQuaternion(in Quaternion quaternion) Impl result; - result.X = new Vector4( + result.X = Vector4.Create( 1.0f - 2.0f * (yy + zz), 2.0f * (xy + wz), 2.0f * (xz - wy), 0 ); - result.Y = new Vector4( + result.Y = Vector4.Create( 2.0f * (xy - wz), 1.0f - 2.0f * (zz + xx), 2.0f * (yz + wx), 0 ); - result.Z = new Vector4( + result.Z = Vector4.Create( 2.0f * (xz + wy), 2.0f * (yz - wx), 1.0f - 2.0f * (yy + xx), @@ -433,25 +432,25 @@ public static Impl CreateLookTo(in Vector3 cameraPosition, in Vector3 cameraDire Impl result; - result.X = new Vector4( + result.X = Vector4.Create( axisX.X, axisY.X, axisZ.X, 0 ); - result.Y = new Vector4( + result.Y = Vector4.Create( axisX.Y, axisY.Y, axisZ.Y, 0 ); - result.Z = new Vector4( + result.Z = Vector4.Create( axisX.Z, axisY.Z, axisZ.Z, 0 ); - result.W = new Vector4( + result.W = Vector4.Create( Vector3.Dot(axisX, negativeCameraPosition), Vector3.Dot(axisY, negativeCameraPosition), Vector3.Dot(axisZ, negativeCameraPosition), @@ -471,25 +470,25 @@ public static Impl CreateLookToLeftHanded(in Vector3 cameraPosition, in Vector3 Impl result; - result.X = new Vector4( + result.X = Vector4.Create( axisX.X, axisY.X, axisZ.X, 0 ); - result.Y = new Vector4( + result.Y = Vector4.Create( axisX.Y, axisY.Y, axisZ.Y, 0 ); - result.Z = new Vector4( + result.Z = Vector4.Create( axisX.Z, axisY.Z, axisZ.Z, 0 ); - result.W = new Vector4( + result.W = Vector4.Create( Vector3.Dot(axisX, negativeCameraPosition), Vector3.Dot(axisY, negativeCameraPosition), Vector3.Dot(axisZ, negativeCameraPosition), @@ -506,10 +505,10 @@ public static Impl CreateOrthographic(float width, float height, float zNearPlan Impl result; - result.X = new Vector4(2.0f / width, 0, 0, 0); - result.Y = new Vector4(0, 2.0f / height, 0, 0); - result.Z = new Vector4(0, 0, range, 0); - result.W = new Vector4(0, 0, range * zNearPlane, 1); + result.X = Vector4.Create(2.0f / width, 0, 0, 0); + result.Y = Vector4.Create(0, 2.0f / height, 0, 0); + result.Z = Vector4.Create(0, 0, range, 0); + result.W = Vector4.Create(0, 0, range * zNearPlane, 1); return result; } @@ -521,10 +520,10 @@ public static Impl CreateOrthographicLeftHanded(float width, float height, float Impl result; - result.X = new Vector4(2.0f / width, 0, 0, 0); - result.Y = new Vector4(0, 2.0f / height, 0, 0); - result.Z = new Vector4(0, 0, range, 0); - result.W = new Vector4(0, 0, -range * zNearPlane, 1); + result.X = Vector4.Create(2.0f / width, 0, 0, 0); + result.Y = Vector4.Create(0, 2.0f / height, 0, 0); + result.Z = Vector4.Create(0, 0, range, 0); + result.W = Vector4.Create(0, 0, -range * zNearPlane, 1); return result; } @@ -538,10 +537,10 @@ public static Impl CreateOrthographicOffCenter(float left, float right, float bo Impl result; - result.X = new Vector4(reciprocalWidth + reciprocalWidth, 0, 0, 0); - result.Y = new Vector4(0, reciprocalHeight + reciprocalHeight, 0, 0); - result.Z = new Vector4(0, 0, range, 0); - result.W = new Vector4( + result.X = Vector4.Create(reciprocalWidth + reciprocalWidth, 0, 0, 0); + result.Y = Vector4.Create(0, reciprocalHeight + reciprocalHeight, 0, 0); + result.Z = Vector4.Create(0, 0, range, 0); + result.W = Vector4.Create( -(left + right) * reciprocalWidth, -(top + bottom) * reciprocalHeight, range * zNearPlane, @@ -560,10 +559,10 @@ public static Impl CreateOrthographicOffCenterLeftHanded(float left, float right Impl result; - result.X = new Vector4(reciprocalWidth + reciprocalWidth, 0, 0, 0); - result.Y = new Vector4(0, reciprocalHeight + reciprocalHeight, 0, 0); - result.Z = new Vector4(0, 0, range, 0); - result.W = new Vector4( + result.X = Vector4.Create(reciprocalWidth + reciprocalWidth, 0, 0, 0); + result.Y = Vector4.Create(0, reciprocalHeight + reciprocalHeight, 0, 0); + result.Z = Vector4.Create(0, 0, range, 0); + result.W = Vector4.Create( -(left + right) * reciprocalWidth, -(top + bottom) * reciprocalHeight, -range * zNearPlane, @@ -585,10 +584,10 @@ public static Impl CreatePerspective(float width, float height, float nearPlaneD Impl result; - result.X = new Vector4(dblNearPlaneDistance / width, 0, 0, 0); - result.Y = new Vector4(0, dblNearPlaneDistance / height, 0, 0); - result.Z = new Vector4(0, 0, range, -1.0f); - result.W = new Vector4(0, 0, range * nearPlaneDistance, 0); + result.X = Vector4.Create(dblNearPlaneDistance / width, 0, 0, 0); + result.Y = Vector4.Create(0, dblNearPlaneDistance / height, 0, 0); + result.Z = Vector4.Create(0, 0, range, -1.0f); + result.W = Vector4.Create(0, 0, range * nearPlaneDistance, 0); return result; } @@ -605,10 +604,10 @@ public static Impl CreatePerspectiveLeftHanded(float width, float height, float Impl result; - result.X = new Vector4(dblNearPlaneDistance / width, 0, 0, 0); - result.Y = new Vector4(0, dblNearPlaneDistance / height, 0, 0); - result.Z = new Vector4(0, 0, range, 1.0f); - result.W = new Vector4(0, 0, -range * nearPlaneDistance, 0); + result.X = Vector4.Create(dblNearPlaneDistance / width, 0, 0, 0); + result.Y = Vector4.Create(0, dblNearPlaneDistance / height, 0, 0); + result.Z = Vector4.Create(0, 0, range, 1.0f); + result.W = Vector4.Create(0, 0, -range * nearPlaneDistance, 0); return result; } @@ -623,16 +622,16 @@ public static Impl CreatePerspectiveFieldOfView(float fieldOfView, float aspectR ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(farPlaneDistance, 0.0f); ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(nearPlaneDistance, farPlaneDistance); - float height = 1.0f / MathF.Tan(fieldOfView * 0.5f); + float height = 1.0f / float.Tan(fieldOfView * 0.5f); float width = height / aspectRatio; float range = float.IsPositiveInfinity(farPlaneDistance) ? -1.0f : farPlaneDistance / (nearPlaneDistance - farPlaneDistance); Impl result; - result.X = new Vector4(width, 0, 0, 0); - result.Y = new Vector4(0, height, 0, 0); - result.Z = new Vector4(0, 0, range, -1.0f); - result.W = new Vector4(0, 0, range * nearPlaneDistance, 0); + result.X = Vector4.Create(width, 0, 0, 0); + result.Y = Vector4.Create(0, height, 0, 0); + result.Z = Vector4.Create(0, 0, range, -1.0f); + result.W = Vector4.Create(0, 0, range * nearPlaneDistance, 0); return result; } @@ -647,16 +646,16 @@ public static Impl CreatePerspectiveFieldOfViewLeftHanded(float fieldOfView, flo ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(farPlaneDistance, 0.0f); ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(nearPlaneDistance, farPlaneDistance); - float height = 1.0f / MathF.Tan(fieldOfView * 0.5f); + float height = 1.0f / float.Tan(fieldOfView * 0.5f); float width = height / aspectRatio; float range = float.IsPositiveInfinity(farPlaneDistance) ? 1.0f : farPlaneDistance / (farPlaneDistance - nearPlaneDistance); Impl result; - result.X = new Vector4(width, 0, 0, 0); - result.Y = new Vector4(0, height, 0, 0); - result.Z = new Vector4(0, 0, range, 1.0f); - result.W = new Vector4(0, 0, -range * nearPlaneDistance, 0); + result.X = Vector4.Create(width, 0, 0, 0); + result.Y = Vector4.Create(0, height, 0, 0); + result.Z = Vector4.Create(0, 0, range, 1.0f); + result.W = Vector4.Create(0, 0, -range * nearPlaneDistance, 0); return result; } @@ -675,15 +674,15 @@ public static Impl CreatePerspectiveOffCenter(float left, float right, float bot Impl result; - result.X = new Vector4(dblNearPlaneDistance * reciprocalWidth, 0, 0, 0); - result.Y = new Vector4(0, dblNearPlaneDistance * reciprocalHeight, 0, 0); - result.Z = new Vector4( + result.X = Vector4.Create(dblNearPlaneDistance * reciprocalWidth, 0, 0, 0); + result.Y = Vector4.Create(0, dblNearPlaneDistance * reciprocalHeight, 0, 0); + result.Z = Vector4.Create( (left + right) * reciprocalWidth, (top + bottom) * reciprocalHeight, range, -1.0f ); - result.W = new Vector4(0, 0, range * nearPlaneDistance, 0); + result.W = Vector4.Create(0, 0, range * nearPlaneDistance, 0); return result; } @@ -702,15 +701,15 @@ public static Impl CreatePerspectiveOffCenterLeftHanded(float left, float right, Impl result; - result.X = new Vector4(dblNearPlaneDistance * reciprocalWidth, 0, 0, 0); - result.Y = new Vector4(0, dblNearPlaneDistance * reciprocalHeight, 0, 0); - result.Z = new Vector4( + result.X = Vector4.Create(dblNearPlaneDistance * reciprocalWidth, 0, 0, 0); + result.Y = Vector4.Create(0, dblNearPlaneDistance * reciprocalHeight, 0, 0); + result.Z = Vector4.Create( -(left + right) * reciprocalWidth, -(top + bottom) * reciprocalHeight, range, 1.0f ); - result.W = new Vector4(0, 0, -range * nearPlaneDistance, 0); + result.W = Vector4.Create(0, 0, -range * nearPlaneDistance, 0); return result; } @@ -723,10 +722,10 @@ public static Impl CreateReflection(in Plane value) Impl result; - result.X = new Vector4(f * p.Normal.X, 0) + Vector4.UnitX; - result.Y = new Vector4(f * p.Normal.Y, 0) + Vector4.UnitY; - result.Z = new Vector4(f * p.Normal.Z, 0) + Vector4.UnitZ; - result.W = new Vector4(f * p.D, 1); + result.X = (f * p.Normal.X).AsVector4() + Vector4.UnitX; + result.Y = (f * p.Normal.Y).AsVector4() + Vector4.UnitY; + result.Z = (f * p.Normal.Z).AsVector4() + Vector4.UnitZ; + result.W = Vector4.Create(f * p.D, 1); return result; } @@ -734,8 +733,7 @@ public static Impl CreateReflection(in Plane value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl CreateRotationX(float radians) { - float c = MathF.Cos(radians); - float s = MathF.Sin(radians); + (float s, float c) = float.SinCos(radians); // [ 1 0 0 0 ] // [ 0 c s 0 ] @@ -745,8 +743,8 @@ public static Impl CreateRotationX(float radians) Impl result; result.X = Vector4.UnitX; - result.Y = new Vector4(0, c, s, 0); - result.Z = new Vector4(0, -s, c, 0); + result.Y = Vector4.Create(0, c, s, 0); + result.Z = Vector4.Create(0, -s, c, 0); result.W = Vector4.UnitW; return result; @@ -755,8 +753,7 @@ public static Impl CreateRotationX(float radians) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl CreateRotationX(float radians, in Vector3 centerPoint) { - float c = MathF.Cos(radians); - float s = MathF.Sin(radians); + (float s, float c) = float.SinCos(radians); float y = centerPoint.Y * (1 - c) + centerPoint.Z * s; float z = centerPoint.Z * (1 - c) - centerPoint.Y * s; @@ -769,9 +766,9 @@ public static Impl CreateRotationX(float radians, in Vector3 centerPoint) Impl result; result.X = Vector4.UnitX; - result.Y = new Vector4(0, c, s, 0); - result.Z = new Vector4(0, -s, c, 0); - result.W = new Vector4(0, y, z, 1); + result.Y = Vector4.Create(0, c, s, 0); + result.Z = Vector4.Create(0, -s, c, 0); + result.W = Vector4.Create(0, y, z, 1); return result; } @@ -779,8 +776,7 @@ public static Impl CreateRotationX(float radians, in Vector3 centerPoint) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl CreateRotationY(float radians) { - float c = MathF.Cos(radians); - float s = MathF.Sin(radians); + (float s, float c) = float.SinCos(radians); // [ c 0 -s 0 ] // [ 0 1 0 0 ] @@ -789,9 +785,9 @@ public static Impl CreateRotationY(float radians) Impl result; - result.X = new Vector4(c, 0, -s, 0); + result.X = Vector4.Create(c, 0, -s, 0); result.Y = Vector4.UnitY; - result.Z = new Vector4(s, 0, c, 0); + result.Z = Vector4.Create(s, 0, c, 0); result.W = Vector4.UnitW; return result; @@ -800,8 +796,7 @@ public static Impl CreateRotationY(float radians) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl CreateRotationY(float radians, in Vector3 centerPoint) { - float c = MathF.Cos(radians); - float s = MathF.Sin(radians); + (float s, float c) = float.SinCos(radians); float x = centerPoint.X * (1 - c) - centerPoint.Z * s; float z = centerPoint.Z * (1 - c) + centerPoint.X * s; @@ -813,10 +808,10 @@ public static Impl CreateRotationY(float radians, in Vector3 centerPoint) Impl result; - result.X = new Vector4(c, 0, -s, 0); + result.X = Vector4.Create(c, 0, -s, 0); result.Y = Vector4.UnitY; - result.Z = new Vector4(s, 0, c, 0); - result.W = new Vector4(x, 0, z, 1); + result.Z = Vector4.Create(s, 0, c, 0); + result.W = Vector4.Create(x, 0, z, 1); return result; } @@ -824,9 +819,7 @@ public static Impl CreateRotationY(float radians, in Vector3 centerPoint) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl CreateRotationZ(float radians) { - - float c = MathF.Cos(radians); - float s = MathF.Sin(radians); + (float s, float c) = float.SinCos(radians); // [ c s 0 0 ] // [ -s c 0 0 ] @@ -835,8 +828,8 @@ public static Impl CreateRotationZ(float radians) Impl result; - result.X = new Vector4( c, s, 0, 0); - result.Y = new Vector4(-s, c, 0, 0); + result.X = Vector4.Create( c, s, 0, 0); + result.Y = Vector4.Create(-s, c, 0, 0); result.Z = Vector4.UnitZ; result.W = Vector4.UnitW; @@ -846,8 +839,7 @@ public static Impl CreateRotationZ(float radians) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl CreateRotationZ(float radians, in Vector3 centerPoint) { - float c = MathF.Cos(radians); - float s = MathF.Sin(radians); + (float s, float c) = float.SinCos(radians); float x = centerPoint.X * (1 - c) + centerPoint.Y * s; float y = centerPoint.Y * (1 - c) - centerPoint.X * s; @@ -859,10 +851,10 @@ public static Impl CreateRotationZ(float radians, in Vector3 centerPoint) Impl result; - result.X = new Vector4( c, s, 0, 0); - result.Y = new Vector4(-s, c, 0, 0); + result.X = Vector4.Create( c, s, 0, 0); + result.Y = Vector4.Create(-s, c, 0, 0); result.Z = Vector4.UnitZ; - result.W = new Vector4(x, y, 0, 1); + result.W = Vector4.Create(x, y, 0, 1); return result; } @@ -872,9 +864,9 @@ public static Impl CreateScale(float scaleX, float scaleY, float scaleZ) { Impl result; - result.X = new Vector4(scaleX, 0, 0, 0); - result.Y = new Vector4(0, scaleY, 0, 0); - result.Z = new Vector4(0, 0, scaleZ, 0); + result.X = Vector4.Create(scaleX, 0, 0, 0); + result.Y = Vector4.Create(0, scaleY, 0, 0); + result.Z = Vector4.Create(0, 0, scaleZ, 0); result.W = Vector4.UnitW; return result; @@ -885,10 +877,10 @@ public static Impl CreateScale(float scaleX, float scaleY, float scaleZ, in Vect { Impl result; - result.X = new Vector4(scaleX, 0, 0, 0); - result.Y = new Vector4(0, scaleY, 0, 0); - result.Z = new Vector4(0, 0, scaleZ, 0); - result.W = new Vector4(centerPoint * (Vector3.One - new Vector3(scaleX, scaleY, scaleZ)), 1); + result.X = Vector4.Create(scaleX, 0, 0, 0); + result.Y = Vector4.Create(0, scaleY, 0, 0); + result.Z = Vector4.Create(0, 0, scaleZ, 0); + result.W = Vector4.Create(centerPoint * (Vector3.One - Vector3.Create(scaleX, scaleY, scaleZ)), 1); return result; } @@ -898,9 +890,9 @@ public static Impl CreateScale(in Vector3 scales) { Impl result; - result.X = new Vector4(scales.X, 0, 0, 0); - result.Y = new Vector4(0, scales.Y, 0, 0); - result.Z = new Vector4(0, 0, scales.Z, 0); + result.X = Vector4.Create(scales.X, 0, 0, 0); + result.Y = Vector4.Create(0, scales.Y, 0, 0); + result.Z = Vector4.Create(0, 0, scales.Z, 0); result.W = Vector4.UnitW; return result; @@ -911,10 +903,10 @@ public static Impl CreateScale(in Vector3 scales, in Vector3 centerPoint) { Impl result; - result.X = new Vector4(scales.X, 0, 0, 0); - result.Y = new Vector4(0, scales.Y, 0, 0); - result.Z = new Vector4(0, 0, scales.Z, 0); - result.W = new Vector4(centerPoint * (Vector3.One - scales), 1); + result.X = Vector4.Create(scales.X, 0, 0, 0); + result.Y = Vector4.Create(0, scales.Y, 0, 0); + result.Z = Vector4.Create(0, 0, scales.Z, 0); + result.W = Vector4.Create(centerPoint * (Vector3.One - scales), 1); return result; } @@ -924,9 +916,9 @@ public static Impl CreateScale(float scale) { Impl result; - result.X = new Vector4(scale, 0, 0, 0); - result.Y = new Vector4(0, scale, 0, 0); - result.Z = new Vector4(0, 0, scale, 0); + result.X = Vector4.Create(scale, 0, 0, 0); + result.Y = Vector4.Create(0, scale, 0, 0); + result.Z = Vector4.Create(0, 0, scale, 0); result.W = Vector4.UnitW; return result; @@ -937,10 +929,10 @@ public static Impl CreateScale(float scale, in Vector3 centerPoint) { Impl result; - result.X = new Vector4(scale, 0, 0, 0); - result.Y = new Vector4(0, scale, 0, 0); - result.Z = new Vector4(0, 0, scale, 0); - result.W = new Vector4(centerPoint * (Vector3.One - new Vector3(scale)), 1); + result.X = Vector4.Create(scale, 0, 0, 0); + result.Y = Vector4.Create(0, scale, 0, 0); + result.Z = Vector4.Create(0, 0, scale, 0); + result.W = Vector4.Create(centerPoint * (Vector3.One - Vector3.Create(scale)), 1); return result; } @@ -955,10 +947,10 @@ public static Impl CreateShadow(in Vector3 lightDirection, in Plane plane) Impl result; - result.X = new Vector4(lightDirection * normal.X, 0) + new Vector4(dot, 0, 0, 0); - result.Y = new Vector4(lightDirection * normal.Y, 0) + new Vector4(0, dot, 0, 0); - result.Z = new Vector4(lightDirection * normal.Z, 0) + new Vector4(0, 0, dot, 0); - result.W = new Vector4(lightDirection * -p.D, dot); + result.X = (lightDirection * normal.X).AsVector4() + Vector4.CreateScalar(dot); + result.Y = (lightDirection * normal.Y).AsVector4() + Vector4.Create(0, dot, 0, 0); + result.Z = (lightDirection * normal.Z).AsVector4() + Vector4.Create(0, 0, dot, 0); + result.W = Vector4.Create(lightDirection * -p.D, dot); return result; } @@ -971,7 +963,7 @@ public static Impl CreateTranslation(in Vector3 position) result.X = Vector4.UnitX; result.Y = Vector4.UnitY; result.Z = Vector4.UnitZ; - result.W = new Vector4(position, 1); + result.W = Vector4.Create(position, 1); return result; } @@ -984,7 +976,7 @@ public static Impl CreateTranslation(float positionX, float positionY, float pos result.X = Vector4.UnitX; result.Y = Vector4.UnitY; result.Z = Vector4.UnitZ; - result.W = new Vector4(positionX, positionY, positionZ, 1); + result.W = Vector4.Create(positionX, positionY, positionZ, 1); return result; } @@ -996,13 +988,13 @@ public static Impl CreateViewport(float x, float y, float width, float height, f Impl result; // 4x SIMD fields to get a lot better codegen - result.W = new Vector4(width, height, 0f, 0f); - result.W *= new Vector4(0.5f, 0.5f, 0f, 0f); + result.W = Vector4.Create(width, height, 0f, 0f); + result.W *= Vector4.Create(0.5f, 0.5f, 0f, 0f); - result.X = new Vector4(result.W.X, 0f, 0f, 0f); - result.Y = new Vector4(0f, -result.W.Y, 0f, 0f); - result.Z = new Vector4(0f, 0f, minDepth - maxDepth, 0f); - result.W += new Vector4(x, y, minDepth, 1f); + result.X = Vector4.Create(result.W.X, 0f, 0f, 0f); + result.Y = Vector4.Create(0f, -result.W.Y, 0f, 0f); + result.Z = Vector4.Create(0f, 0f, minDepth - maxDepth, 0f); + result.W += Vector4.Create(x, y, minDepth, 1f); return result; } @@ -1013,13 +1005,13 @@ public static Impl CreateViewportLeftHanded(float x, float y, float width, float Impl result; // 4x SIMD fields to get a lot better codegen - result.W = new Vector4(width, height, 0f, 0f); - result.W *= new Vector4(0.5f, 0.5f, 0f, 0f); + result.W = Vector4.Create(width, height, 0f, 0f); + result.W *= Vector4.Create(0.5f, 0.5f, 0f, 0f); - result.X = new Vector4(result.W.X, 0f, 0f, 0f); - result.Y = new Vector4(0f, -result.W.Y, 0f, 0f); - result.Z = new Vector4(0f, 0f, maxDepth - minDepth, 0f); - result.W += new Vector4(x, y, minDepth, 1f); + result.X = Vector4.Create(result.W.X, 0f, 0f, 0f); + result.Y = Vector4.Create(0f, -result.W.Y, 0f, 0f); + result.Z = Vector4.Create(0f, 0f, maxDepth - minDepth, 0f); + result.W += Vector4.Create(x, y, minDepth, 1f); return result; } @@ -1033,10 +1025,10 @@ public static Impl CreateWorld(in Vector3 position, in Vector3 forward, in Vecto Impl result; - result.X = new Vector4(axisX, 0); - result.Y = new Vector4(axisY, 0); - result.Z = new Vector4(axisZ, 0); - result.W = new Vector4(position, 1); + result.X = axisX.AsVector4(); + result.Y = axisY.AsVector4(); + result.Z = axisZ.AsVector4(); + result.W = Vector4.Create(position, 1); return result; } @@ -1058,22 +1050,19 @@ public static unsafe bool Decompose(in Impl matrix, out Vector3 scale, out Quate CanonicalBasis canonicalBasis = default; Vector3* pCanonicalBasis = &canonicalBasis.Row0; - canonicalBasis.Row0 = new Vector3(1.0f, 0.0f, 0.0f); - canonicalBasis.Row1 = new Vector3(0.0f, 1.0f, 0.0f); - canonicalBasis.Row2 = new Vector3(0.0f, 0.0f, 1.0f); + canonicalBasis.Row0 = Vector3.UnitX; + canonicalBasis.Row1 = Vector3.UnitY; + canonicalBasis.Row2 = Vector3.UnitZ; - translation = new Vector3( - matrix.W.X, - matrix.W.Y, - matrix.W.Z); + translation = matrix.W.AsVector3(); pVectorBasis[0] = (Vector3*)&matTemp.X; pVectorBasis[1] = (Vector3*)&matTemp.Y; pVectorBasis[2] = (Vector3*)&matTemp.Z; - *(pVectorBasis[0]) = new Vector3(matrix.X.X, matrix.X.Y, matrix.X.Z); - *(pVectorBasis[1]) = new Vector3(matrix.Y.X, matrix.Y.Y, matrix.Y.Z); - *(pVectorBasis[2]) = new Vector3(matrix.Z.X, matrix.Z.Y, matrix.Z.Z); + *(pVectorBasis[0]) = matrix.X.AsVector3(); + *(pVectorBasis[1]) = matrix.Y.AsVector3(); + *(pVectorBasis[2]) = matrix.Z.AsVector3(); scale.X = pVectorBasis[0]->Length(); scale.Y = pVectorBasis[1]->Length(); @@ -1148,9 +1137,9 @@ public static unsafe bool Decompose(in Impl matrix, out Vector3 scale, out Quate uint cc; float fAbsX, fAbsY, fAbsZ; - fAbsX = MathF.Abs(pVectorBasis[a]->X); - fAbsY = MathF.Abs(pVectorBasis[a]->Y); - fAbsZ = MathF.Abs(pVectorBasis[a]->Z); + fAbsX = float.Abs(pVectorBasis[a]->X); + fAbsY = float.Abs(pVectorBasis[a]->Y); + fAbsZ = float.Abs(pVectorBasis[a]->Z); #region Ranking if (fAbsX < fAbsY) @@ -1387,9 +1376,9 @@ static bool SseImpl(in Impl matrix, out Impl result) float det = Vector4.Dot(C0.AsVector4(), row1.AsVector4()); // Check determinate is not zero - if (MathF.Abs(det) < float.Epsilon) + if (float.Abs(det) < float.Epsilon) { - Vector4 vNaN = new Vector4(float.NaN); + Vector4 vNaN = Vector4.Create(float.NaN); result.X = vNaN; result.Y = vNaN; @@ -1546,9 +1535,9 @@ static bool SoftwareFallback(in Impl matrix, out Impl result) float det = a * a11 + b * a12 + c * a13 + d * a14; - if (MathF.Abs(det) < float.Epsilon) + if (float.Abs(det) < float.Epsilon) { - Vector4 vNaN = new Vector4(float.NaN); + Vector4 vNaN = Vector4.Create(float.NaN); result.X = vNaN; result.Y = vNaN; @@ -1645,25 +1634,25 @@ public static Impl Transform(in Impl value, in Quaternion rotation) Impl result; - result.X = new Vector4( + result.X = Vector4.Create( value.X.X * q11 + value.X.Y * q21 + value.X.Z * q31, value.X.X * q12 + value.X.Y * q22 + value.X.Z * q32, value.X.X * q13 + value.X.Y * q23 + value.X.Z * q33, value.X.W ); - result.Y = new Vector4( + result.Y = Vector4.Create( value.Y.X * q11 + value.Y.Y * q21 + value.Y.Z * q31, value.Y.X * q12 + value.Y.Y * q22 + value.Y.Z * q32, value.Y.X * q13 + value.Y.Y * q23 + value.Y.Z * q33, value.Y.W ); - result.Z = new Vector4( + result.Z = Vector4.Create( value.Z.X * q11 + value.Z.Y * q21 + value.Z.Z * q31, value.Z.X * q12 + value.Z.Y * q22 + value.Z.Z * q32, value.Z.X * q13 + value.Z.Y * q23 + value.Z.Z * q33, value.Z.W ); - result.W = new Vector4( + result.W = Vector4.Create( value.W.X * q11 + value.W.Y * q21 + value.W.Z * q31, value.W.X * q12 + value.W.Y * q22 + value.W.Z * q32, value.W.X * q13 + value.W.Y * q23 + value.W.Z * q33, @@ -1717,10 +1706,10 @@ public static Impl Transpose(in Impl matrix) } else { - result.X = new Vector4(matrix.X.X, matrix.Y.X, matrix.Z.X, matrix.W.X); - result.Y = new Vector4(matrix.X.Y, matrix.Y.Y, matrix.Z.Y, matrix.W.Y); - result.Z = new Vector4(matrix.X.Z, matrix.Y.Z, matrix.Z.Z, matrix.W.Z); - result.W = new Vector4(matrix.X.W, matrix.Y.W, matrix.Z.W, matrix.W.W); + result.X = Vector4.Create(matrix.X.X, matrix.Y.X, matrix.Z.X, matrix.W.X); + result.Y = Vector4.Create(matrix.X.Y, matrix.Y.Y, matrix.Z.Y, matrix.W.Y); + result.Z = Vector4.Create(matrix.X.Z, matrix.Y.Z, matrix.Z.Z, matrix.W.Z); + result.W = Vector4.Create(matrix.X.W, matrix.Y.W, matrix.Z.W, matrix.W.W); } return result; diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs index 3834877ae44a8..55404a6008455 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs @@ -380,7 +380,7 @@ public static Matrix4x4 CreatePerspectiveLeftHanded(float width, float height, f /// The right-handed perspective projection matrix. /// is less than or equal to zero. /// -or- - /// is greater than or equal to . + /// is greater than or equal to . /// is less than or equal to zero. /// -or- /// is less than or equal to zero. @@ -397,7 +397,7 @@ public static Matrix4x4 CreatePerspectiveFieldOfView(float fieldOfView, float as /// The left-handed perspective projection matrix. /// is less than or equal to zero. /// -or- - /// is greater than or equal to . + /// is greater than or equal to . /// is less than or equal to zero. /// -or- /// is less than or equal to zero. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.Extensions.cs new file mode 100644 index 0000000000000..867e4d15222e6 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.Extensions.cs @@ -0,0 +1,25 @@ +// 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; +using System.Runtime.Intrinsics; + +namespace System.Numerics +{ + public static unsafe partial class Vector + { + /// Reinterprets a as a new . + /// The plane to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + public static Vector4 AsVector4(this Plane value) + { +#if MONO + return Unsafe.As(ref value); +#else + return Unsafe.BitCast(value); +#endif + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs index 09d19a137f917..55f4522800316 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs @@ -30,7 +30,7 @@ public struct Plane : IEquatable [Intrinsic] public Plane(float x, float y, float z, float d) { - this = Vector128.Create(x, y, z, d).AsPlane(); + this = Create(x, y, z, d); } /// Creates a object from a specified normal and the distance along the normal from the origin. @@ -39,7 +39,7 @@ public Plane(float x, float y, float z, float d) [Intrinsic] public Plane(Vector3 normal, float d) { - this = new Vector4(normal, d).AsPlane(); + this = Create(normal, d); } /// Creates a object from a specified four-dimensional vector. @@ -50,6 +50,22 @@ public Plane(Vector4 value) this = value.AsPlane(); } + /// Creates a object from the X, Y, and Z components of its normal, and its distance from the origin on that normal. + /// The X component of the normal. + /// The Y component of the normal. + /// The Z component of the normal. + /// The distance of the plane along its normal from the origin. + /// A new object from the X, Y, and Z components of its normal, and its distance from the origin on that normal. + [Intrinsic] + internal static Plane Create(float x, float y, float z, float d) => Vector128.Create(x, y, z, d).AsPlane(); + + /// Creates a object from a specified normal and the distance along the normal from the origin. + /// The plane's normal vector. + /// The plane's distance from the origin along its normal vector.\ + /// A new object from a specified normal and the distance along the normal from the origin. + [Intrinsic] + internal static Plane Create(Vector3 normal, float d) => Vector4.Create(normal, d).AsPlane(); + /// Creates a object that contains three specified points. /// The first point defining the plane. /// The second point defining the plane. @@ -70,7 +86,7 @@ public static Plane CreateFromVertices(Vector3 point1, Vector3 point2, Vector3 p // D = - Dot(N, point1) float d = -Vector3.Dot(normal, point1); - return new Plane(normal, d); + return Create(normal, d); } else { @@ -89,16 +105,17 @@ public static Plane CreateFromVertices(Vector3 point1, Vector3 point2, Vector3 p // Normalize(N) float ls = nx * nx + ny * ny + nz * nz; - float invNorm = 1.0f / MathF.Sqrt(ls); + float invNorm = 1.0f / float.Sqrt(ls); - Vector3 normal = new Vector3( + Vector3 normal = Vector3.Create( nx * invNorm, ny * invNorm, nz * invNorm); - return new Plane( + return Create( normal, - -(normal.X * point1.X + normal.Y * point1.Y + normal.Z * point1.Z)); + -(normal.X * point1.X + normal.Y * point1.Y + normal.Z * point1.Z) + ); } } @@ -130,13 +147,13 @@ public static Plane Normalize(Plane value) { float normalLengthSquared = value.Normal.LengthSquared(); - if (MathF.Abs(normalLengthSquared - 1.0f) < NormalizeEpsilon) + if (float.Abs(normalLengthSquared - 1.0f) < NormalizeEpsilon) { // It already normalized, so we don't need to farther process. return value; } - return (value.AsVector128() / MathF.Sqrt(normalLengthSquared)).AsPlane(); + return (value.AsVector128() / float.Sqrt(normalLengthSquared)).AsPlane(); } /// Transforms a normalized plane by a 4x4 matrix. @@ -151,11 +168,12 @@ public static Plane Transform(Plane plane, Matrix4x4 matrix) float x = plane.Normal.X, y = plane.Normal.Y, z = plane.Normal.Z, w = plane.D; - return new Plane( + return Create( x * m.M11 + y * m.M12 + z * m.M13 + w * m.M14, x * m.M21 + y * m.M22 + z * m.M23 + w * m.M24, x * m.M31 + y * m.M32 + z * m.M33 + w * m.M34, - x * m.M41 + y * m.M42 + z * m.M43 + w * m.M44); + x * m.M41 + y * m.M42 + z * m.M43 + w * m.M44 + ); } /// Transforms a normalized plane by a Quaternion rotation. @@ -195,11 +213,12 @@ public static Plane Transform(Plane plane, Quaternion rotation) float x = plane.Normal.X, y = plane.Normal.Y, z = plane.Normal.Z; - return new Plane( + return Create( x * m11 + y * m21 + z * m31, x * m12 + y * m22 + z * m32, x * m13 + y * m23 + z * m33, - plane.D); + plane.D + ); } /// Returns a value that indicates whether two planes are equal. 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 index 42ac2e3d0dfc3..b42487e3f6303 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs @@ -9,43 +9,17 @@ namespace System.Numerics { public static unsafe partial class Vector { - /// Gets the element at the specified index. - /// The quaternion to get the element from. - /// The index of the element to get. - /// The value of the element at . - /// was less than zero or greater than the number of elements. + /// Reinterprets a as a new . + /// The quaternion to reinterpret. + /// reinterpreted as a new . [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static float GetElement(this Quaternion quaternion, int index) + public static Vector4 AsVector4(this Quaternion value) { - return quaternion.AsVector128().GetElement(index); - } - - /// Creates a new 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. - /// The quaternion to get the remaining elements from. - /// The index of the element to set. - /// The value to set the element to. - /// A with the value of the element at set to and the remaining elements set to the same value as that in . - /// was less than zero or greater than the number of elements. - [Intrinsic] - internal static Quaternion WithElement(this Quaternion quaternion, int index, float value) - { - return quaternion.AsVector128().WithElement(index, value).AsQuaternion(); - } - - [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; +#if MONO + return Unsafe.As(ref value); +#else + return Unsafe.BitCast(value); +#endif } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 4ec7f536ed43f..b14a70e68106b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -38,7 +38,7 @@ public struct Quaternion : IEquatable [Intrinsic] public Quaternion(float x, float y, float z, float w) { - this = Vector128.Create(x, y, z, w).AsQuaternion(); + this = Create(x, y, z, w); } /// Creates a quaternion from the specified vector and rotation parts. @@ -47,7 +47,7 @@ public Quaternion(float x, float y, float z, float w) [Intrinsic] public Quaternion(Vector3 vectorPart, float scalarPart) { - this = new Vector4(vectorPart, scalarPart).AsQuaternion(); + this = Create(vectorPart, scalarPart); } /// Gets a quaternion that represents a zero. @@ -63,7 +63,7 @@ public static Quaternion Zero public static Quaternion Identity { [Intrinsic] - get => new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + get => Create(0.0f, 0.0f, 0.0f, 1.0f); } /// Gets or sets the element at the specified index. @@ -73,9 +73,13 @@ public static Quaternion Identity public float this[int index] { [Intrinsic] - readonly get => this.GetElement(index); + readonly get => this.AsVector128().GetElement(index); - set => this = this.WithElement(index, value); + [Intrinsic] + set + { + this = this.AsVector128().WithElement(index, value).AsQuaternion(); + } } /// Gets a value that indicates whether the current instance is the identity quaternion. @@ -161,10 +165,10 @@ public float this[int index] { if (Vector128.IsHardwareAccelerated) { - var left = value1.AsVector128(); - var right = value2.AsVector128(); + Vector128 left = value1.AsVector128(); + Vector128 right = value2.AsVector128(); - var result = right * left.GetElementUnsafe(3); + Vector128 result = right * left.GetElementUnsafe(3); result += (Vector128.Shuffle(right, Vector128.Create(3, 2, 1, 0)) * left.GetElementUnsafe(0)) * Vector128.Create(+1.0f, -1.0f, +1.0f, -1.0f); result += (Vector128.Shuffle(right, Vector128.Create(2, 3, 0, 1)) * left.GetElementUnsafe(1)) * Vector128.Create(+1.0f, +1.0f, -1.0f, -1.0f); result += (Vector128.Shuffle(right, Vector128.Create(1, 0, 3, 2)) * left.GetElementUnsafe(2)) * Vector128.Create(-1.0f, +1.0f, +1.0f, -1.0f); @@ -275,6 +279,22 @@ public static Quaternion Concatenate(Quaternion value1, Quaternion value2) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Conjugate(Quaternion value) => (value.AsVector128() * Vector128.Create(-1.0f, -1.0f, -1.0f, 1.0f)).AsQuaternion(); + /// Creates a quaternion from the specified components. + /// The value to assign to the X component of the quaternion. + /// The value to assign to the Y component of the quaternion. + /// The value to assign to the Z component of the quaternion. + /// The value to assign to the W component of the quaternion. + /// A new quaternion created from the specified components.> + [Intrinsic] + internal static Quaternion Create(float x, float y, float z, float w) => Vector128.Create(x, y, z, w).AsQuaternion(); + + /// Creates a quaternion from the specified vector and rotation parts. + /// The vector part of the quaternion. + /// The rotation part of the quaternion. + /// A new quaternion created from the specified vector and rotation parts. + [Intrinsic] + internal static Quaternion Create(Vector3 vectorPart, float scalarPart) => Vector4.Create(vectorPart, scalarPart).AsQuaternion(); + /// Creates a quaternion from a unit vector and an angle to rotate around the vector. /// The unit vector to rotate around. /// The angle, in radians, to rotate around the vector. @@ -284,9 +304,7 @@ public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle) { Quaternion ans; - float halfAngle = angle * 0.5f; - float s = MathF.Sin(halfAngle); - float c = MathF.Cos(halfAngle); + (float s, float c) = float.SinCos(angle * 0.5f); ans.X = axis.X * s; ans.Y = axis.Y * s; @@ -307,7 +325,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix4x4 matrix) if (trace > 0.0f) { - float s = MathF.Sqrt(trace + 1.0f); + float s = float.Sqrt(trace + 1.0f); q.W = s * 0.5f; s = 0.5f / s; q.X = (matrix.M23 - matrix.M32) * s; @@ -318,7 +336,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix4x4 matrix) { if (matrix.M11 >= matrix.M22 && matrix.M11 >= matrix.M33) { - float s = MathF.Sqrt(1.0f + matrix.M11 - matrix.M22 - matrix.M33); + float s = float.Sqrt(1.0f + matrix.M11 - matrix.M22 - matrix.M33); float invS = 0.5f / s; q.X = 0.5f * s; q.Y = (matrix.M12 + matrix.M21) * invS; @@ -327,7 +345,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix4x4 matrix) } else if (matrix.M22 > matrix.M33) { - float s = MathF.Sqrt(1.0f + matrix.M22 - matrix.M11 - matrix.M33); + float s = float.Sqrt(1.0f + matrix.M22 - matrix.M11 - matrix.M33); float invS = 0.5f / s; q.X = (matrix.M21 + matrix.M12) * invS; q.Y = 0.5f * s; @@ -336,7 +354,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix4x4 matrix) } else { - float s = MathF.Sqrt(1.0f + matrix.M33 - matrix.M11 - matrix.M22); + float s = float.Sqrt(1.0f + matrix.M33 - matrix.M11 - matrix.M22); float invS = 0.5f / s; q.X = (matrix.M31 + matrix.M13) * invS; q.Y = (matrix.M32 + matrix.M23) * invS; @@ -357,19 +375,9 @@ public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float ro { // Roll first, about axis the object is facing, then // pitch upward, then yaw to face into the new heading - float sr, cr, sp, cp, sy, cy; - - float halfRoll = roll * 0.5f; - sr = MathF.Sin(halfRoll); - cr = MathF.Cos(halfRoll); - - float halfPitch = pitch * 0.5f; - sp = MathF.Sin(halfPitch); - cp = MathF.Cos(halfPitch); - - float halfYaw = yaw * 0.5f; - sy = MathF.Sin(halfYaw); - cy = MathF.Cos(halfYaw); + (float sr, float cr) = float.SinCos(roll * 0.5f); + (float sp, float cp) = float.SinCos(pitch * 0.5f); + (float sy, float cy) = float.SinCos(yaw * 0.5f); Quaternion result; @@ -441,7 +449,7 @@ public static Quaternion Lerp(Quaternion quaternion1, Quaternion quaternion2, fl // Normalize it. float ls = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W; - float invNorm = 1.0f / MathF.Sqrt(ls); + float invNorm = 1.0f / float.Sqrt(ls); r.X *= invNorm; r.Y *= invNorm; @@ -507,13 +515,13 @@ public static Quaternion Slerp(Quaternion quaternion1, Quaternion quaternion2, f } else { - float omega = MathF.Acos(cosOmega); - float invSinOmega = 1 / MathF.Sin(omega); + float omega = float.Acos(cosOmega); + float invSinOmega = 1 / float.Sin(omega); - s1 = MathF.Sin((1.0f - t) * omega) * invSinOmega; + s1 = float.Sin((1.0f - t) * omega) * invSinOmega; s2 = (flip) - ? -MathF.Sin(t * omega) * invSinOmega - : MathF.Sin(t * omega) * invSinOmega; + ? -float.Sin(t * omega) * invSinOmega + : float.Sin(t * omega) * invSinOmega; } Quaternion ans; @@ -553,7 +561,7 @@ public static Quaternion Slerp(Quaternion quaternion1, Quaternion quaternion2, f /// Calculates the length of the quaternion. /// The computed length of the quaternion. [Intrinsic] - public readonly float Length() => MathF.Sqrt(LengthSquared()); + public readonly float Length() => float.Sqrt(LengthSquared()); /// Calculates the squared length of the quaternion. /// The length squared of the quaternion. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index 536fd43e8cac7..0e8e2b6bf2bf6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; @@ -209,7 +210,7 @@ public static Vector As(this Vector vector) /// Computes the ceiling of each element in a vector. /// The vector that will have its ceiling computed. /// A vector whose elements are the ceiling of the elements in . - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector Ceiling(Vector value) @@ -228,7 +229,7 @@ public static Vector Ceiling(Vector value) /// Computes the ceiling of each element in a vector. /// The vector that will have its ceiling computed. /// A vector whose elements are the ceiling of the elements in . - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector Ceiling(Vector value) @@ -486,6 +487,72 @@ public static Vector ConvertToUInt64Native(Vector value) return result; } + /// Creates a new instance with all elements initialized to the specified value. + /// The type of the elements in the vector. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + /// The type of () is not supported. + [Intrinsic] + public static Vector Create(T value) + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// Creates a new from a given readonly span. + /// The type of the elements in the vector. + /// The readonly span from which the vector is created. + /// A new with its elements set to the first elements from . + /// The length of is less than . + /// The type of () is not supported. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Create(ReadOnlySpan values) + { + if (values.Length < Vector.Count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values); + } + return Unsafe.ReadUnaligned>(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The type of the elements in the vector. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + /// The type of () is not supported. + [Intrinsic] + internal static unsafe Vector CreateScalar(T value) + { + Vector result = Vector.Zero; + result.SetElementUnsafe(0, value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The type of the elements in the vector. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + /// The type of () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector CreateScalarUnsafe(T value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + ThrowHelper.ThrowForUnsupportedNumericsVectorBaseType(); + Unsafe.SkipInit(out Vector result); + + result.SetElementUnsafe(0, value); + return result; + } + /// Creates a new instance where the elements begin at a specified value and which are spaced apart according to another specified value. /// The type of the elements in the vector. /// The value that element 0 will be initialized to. @@ -493,7 +560,7 @@ public static Vector ConvertToUInt64Native(Vector value) /// A new instance with the first element initialized to and each subsequent element initialized to the the value of the previous element plus . [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector CreateSequence(T start, T step) => (Vector.Indices * step) + new Vector(start); + public static Vector CreateSequence(T start, T step) => (Vector.Indices * step) + Create(start); /// Divides two vectors to compute their quotient. /// The vector that will be divided by . @@ -598,7 +665,7 @@ public static bool EqualsAny(Vector left, Vector right) /// Computes the floor of each element in a vector. /// The vector that will have its floor computed. /// A vector whose elements are the floor of the elements in . - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector Floor(Vector value) @@ -617,7 +684,7 @@ public static Vector Floor(Vector value) /// Computes the floor of each element in a vector. /// The vector that will have its floor computed. /// A vector whose elements are the floor of the elements in . - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector Floor(Vector value) 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 index 5b57163ecad5f..21e3defd777a4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs @@ -3,60 +3,22 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; namespace System.Numerics { public static unsafe partial class Vector { - /// Gets the element at the specified index. - /// The vector to get the element from. - /// The index of the element to get. - /// The value of the element at . - /// was less than zero or greater than the number of elements. + /// Reinterprets a to a new with the new elements zeroed. + /// The vector to reinterpret. + /// reinterpreted to a new with the new elements zeroed. [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static float GetElement(this Vector2 vector, int index) - { - if ((uint)(index) >= (uint)(Vector2.Count)) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } + public static Vector4 AsVector4(this Vector2 value) => value.AsVector128().AsVector4(); - return vector.GetElementUnsafe(index); - } - - /// Creates a new 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. - /// The vector to get the remaining elements from. - /// The index of the element to set. - /// The value to set the element to. - /// A with the value of the element at set to and the remaining elements set to the same value as that in . - /// was less than zero or greater than the number of elements. + /// Reinterprets a to a new with the new elements undefined. + /// The vector to reinterpret. + /// reinterpreted to a new with the new elements undefined. [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; - } + public static Vector4 AsVector4Unsafe(this Vector2 value) => value.AsVector128Unsafe().AsVector4(); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 931cbf5eca86b..7eb79bf3524a7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -28,8 +28,9 @@ public partial struct Vector2 : IEquatable, IFormattable /// Creates a new object whose two elements have the same value. /// The value to assign to both elements. [Intrinsic] - public Vector2(float value) : this(value, value) + public Vector2(float value) { + this = Create(value); } /// Creates a vector whose elements have the specified values. @@ -38,20 +39,15 @@ public Vector2(float value) : this(value, value) [Intrinsic] public Vector2(float x, float y) { - X = x; - Y = y; + this = Create(x, y); } /// Constructs a vector from the given . The span must contain at least 2 elements. /// The span of elements to assign to the vector. + [Intrinsic] public Vector2(ReadOnlySpan values) { - if (values.Length < 2) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values); - } - - this = Unsafe.ReadUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + this = Create(values); } /// Returns a vector whose 2 elements are equal to zero. @@ -67,7 +63,7 @@ public static Vector2 Zero public static Vector2 One { [Intrinsic] - get => new Vector2(1.0f); + get => Create(1.0f); } /// Gets the vector (1,0). @@ -75,7 +71,7 @@ public static Vector2 One public static Vector2 UnitX { [Intrinsic] - get => new Vector2(1.0f, 0.0f); + get => CreateScalar(1.0f); } /// Gets the vector (0,1). @@ -83,7 +79,7 @@ public static Vector2 UnitX public static Vector2 UnitY { [Intrinsic] - get => new Vector2(0.0f, 1.0f); + get => Create(0.0f, 1.0f); } /// Gets or sets the element at the specified index. @@ -93,9 +89,24 @@ public static Vector2 UnitY public float this[int index] { [Intrinsic] - readonly get => this.GetElement(index); + readonly get + { + if ((uint)index >= Count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + return this.AsVector128Unsafe().GetElement(index); + } - set => this = this.WithElement(index, value); + [Intrinsic] + set + { + if ((uint)index >= Count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + this = this.AsVector128Unsafe().WithElement(index, value).AsVector2(); + } } /// Adds two vectors together. @@ -105,13 +116,7 @@ public float this[int index] /// The method defines the addition operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 operator +(Vector2 left, Vector2 right) - { - return new Vector2( - left.X + right.X, - left.Y + right.Y - ); - } + public static Vector2 operator +(Vector2 left, Vector2 right) => (left.AsVector128Unsafe() + right.AsVector128Unsafe()).AsVector2(); /// Divides the first vector by the second. /// The first vector. @@ -120,13 +125,7 @@ public float this[int index] /// The method defines the division operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 operator /(Vector2 left, Vector2 right) - { - return new Vector2( - left.X / right.X, - left.Y / right.Y - ); - } + public static Vector2 operator /(Vector2 left, Vector2 right) => (left.AsVector128Unsafe() / right.AsVector128Unsafe()).AsVector2(); /// Divides the specified vector by a specified scalar value. /// The vector. @@ -134,7 +133,7 @@ public float this[int index] /// The result of the division. /// The method defines the division operation for objects. [Intrinsic] - public static Vector2 operator /(Vector2 value1, float value2) => value1 / new Vector2(value2); + public static Vector2 operator /(Vector2 value1, float value2) => (value1.AsVector128Unsafe() / value2).AsVector2(); /// Returns a value that indicates whether each pair of elements in two specified vectors is equal. /// The first vector to compare. @@ -143,11 +142,7 @@ public float this[int index] /// Two objects are equal if each value in is equal to the corresponding value in . [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Vector2 left, Vector2 right) - { - return (left.X == right.X) - && (left.Y == right.Y); - } + public static bool operator ==(Vector2 left, Vector2 right) => left.AsVector128() == right.AsVector128(); /// Returns a value that indicates whether two specified vectors are not equal. /// The first vector to compare. @@ -163,13 +158,7 @@ public float this[int index] /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 operator *(Vector2 left, Vector2 right) - { - return new Vector2( - left.X * right.X, - left.Y * right.Y - ); - } + public static Vector2 operator *(Vector2 left, Vector2 right) => (left.AsVector128Unsafe() * right.AsVector128Unsafe()).AsVector2(); /// Multiplies the specified vector by the specified scalar value. /// The vector. @@ -177,7 +166,7 @@ public float this[int index] /// The scaled vector. /// The method defines the multiplication operation for objects. [Intrinsic] - public static Vector2 operator *(Vector2 left, float right) => left * new Vector2(right); + public static Vector2 operator *(Vector2 left, float right) => (left.AsVector128Unsafe() * right).AsVector2(); /// Multiplies the scalar value by the specified vector. /// The vector. @@ -194,33 +183,21 @@ public float this[int index] /// The method defines the subtraction operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 operator -(Vector2 left, Vector2 right) - { - return new Vector2( - left.X - right.X, - left.Y - right.Y - ); - } + public static Vector2 operator -(Vector2 left, Vector2 right) => (left.AsVector128Unsafe() - right.AsVector128Unsafe()).AsVector2(); /// Negates the specified vector. /// The vector to negate. /// The negated vector. /// The method defines the unary negation operation for objects. [Intrinsic] - public static Vector2 operator -(Vector2 value) => Zero - value; + public static Vector2 operator -(Vector2 value) => (-value.AsVector128Unsafe()).AsVector2(); /// Returns a vector whose elements are the absolute values of each of the specified vector's elements. /// A vector. /// The absolute value vector. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 Abs(Vector2 value) - { - return new Vector2( - MathF.Abs(value.X), - MathF.Abs(value.Y) - ); - } + public static Vector2 Abs(Vector2 value) => Vector128.Abs(value.AsVector128Unsafe()).AsVector2(); /// Adds two vectors together. /// The first vector to add. @@ -241,12 +218,49 @@ public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max) return Min(Max(value1, min), max); } + /// Creates a new object whose two elements have the same value. + /// The value to assign to all two elements. + /// A new whose two elements have the same value. + [Intrinsic] + public static Vector2 Create(float value) => Vector128.Create(value).AsVector2(); + + /// Creates a vector whose elements have the specified values. + /// The value to assign to the field. + /// The value to assign to the field. + /// A new whose elements have the specified values. + [Intrinsic] + public static Vector2 Create(float x, float y) => Vector128.Create(x, y, 0, 0).AsVector2(); + + /// Constructs a vector from the given . The span must contain at least 2 elements. + /// The span of elements to assign to the vector. + [Intrinsic] + public static Vector2 Create(ReadOnlySpan values) + { + if (values.Length < Count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values); + } + return Unsafe.ReadUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + } + + /// Creates a vector with initialized to the specified value and the remaining elements initialized to zero. + /// The value to assign to the field. + /// A new with initialized and the remaining elements initialized to zero. + [Intrinsic] + internal static Vector2 CreateScalar(float x) => Vector128.CreateScalar(x).AsVector2(); + + /// Creates a vector with initialized to the specified value and the remaining elements left uninitialized. + /// The value to assign to the field. + /// A new with initialized and the remaining elements left uninitialized. + [Intrinsic] + internal static Vector2 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector2(); + /// Computes the Euclidean distance between the two given points. /// The first point. /// The second point. /// The distance. [Intrinsic] - public static float Distance(Vector2 value1, Vector2 value2) => MathF.Sqrt(DistanceSquared(value1, value2)); + public static float Distance(Vector2 value1, Vector2 value2) => float.Sqrt(DistanceSquared(value1, value2)); /// Returns the Euclidean distance squared between two specified points. /// The first point. @@ -275,22 +289,12 @@ public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max) /// The dot product. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Dot(Vector2 value1, Vector2 value2) - { - return (value1.X * value2.X) - + (value1.Y * value2.Y); - } + public static float Dot(Vector2 value1, Vector2 value2) => Vector128.Dot(value1.AsVector128(), value2.AsVector128()); /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 FusedMultiplyAdd(Vector2 left, Vector2 right, Vector2 addend) - { - return new Vector2( - float.FusedMultiplyAdd(left.X, right.X, addend.X), - float.FusedMultiplyAdd(left.Y, right.Y, addend.Y) - ); - } + public static Vector2 FusedMultiplyAdd(Vector2 left, Vector2 right, Vector2 addend) => Vector128.FusedMultiplyAdd(left.AsVector128Unsafe(), right.AsVector128Unsafe(), addend.AsVector128Unsafe()).AsVector2(); /// Performs a linear interpolation between two vectors based on the given weighting. /// The first vector. @@ -310,13 +314,7 @@ public static Vector2 FusedMultiplyAdd(Vector2 left, Vector2 right, Vector2 adde /// The maximized vector. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 Max(Vector2 value1, Vector2 value2) - { - return new Vector2( - (value1.X > value2.X) ? value1.X : value2.X, - (value1.Y > value2.Y) ? value1.Y : value2.Y - ); - } + public static Vector2 Max(Vector2 value1, Vector2 value2) => Vector128.Max(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); /// Returns a vector whose elements are the minimum of each of the pairs of elements in two specified vectors. /// The first vector. @@ -324,13 +322,7 @@ public static Vector2 Max(Vector2 value1, Vector2 value2) /// The minimized vector. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 Min(Vector2 value1, Vector2 value2) - { - return new Vector2( - (value1.X < value2.X) ? value1.X : value2.X, - (value1.Y < value2.Y) ? value1.Y : value2.Y - ); - } + public static Vector2 Min(Vector2 value1, Vector2 value2) => Vector128.Min(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); /// Returns a new vector whose values are the product of each pair of elements in two specified vectors. /// The first vector. @@ -356,13 +348,7 @@ public static Vector2 Min(Vector2 value1, Vector2 value2) /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 MultiplyAddEstimate(Vector2 left, Vector2 right, Vector2 addend) - { - return new Vector2( - float.MultiplyAddEstimate(left.X, right.X, addend.X), - float.MultiplyAddEstimate(left.Y, right.Y, addend.Y) - ); - } + public static Vector2 MultiplyAddEstimate(Vector2 left, Vector2 right, Vector2 addend) => Vector128.MultiplyAddEstimate(left.AsVector128Unsafe(), right.AsVector128Unsafe(), addend.AsVector128Unsafe()).AsVector2(); /// Negates a specified vector. /// The vector to negate. @@ -388,13 +374,7 @@ public static Vector2 MultiplyAddEstimate(Vector2 left, Vector2 right, Vector2 a /// The square root vector. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 SquareRoot(Vector2 value) - { - return new Vector2( - MathF.Sqrt(value.X), - MathF.Sqrt(value.Y) - ); - } + public static Vector2 SquareRoot(Vector2 value) => Vector128.Sqrt(value.AsVector128Unsafe()).AsVector2(); /// Subtracts the second vector from the first. /// The first vector. @@ -444,7 +424,7 @@ public static Vector2 Transform(Vector2 value, Quaternion rotation) float yy2 = rotation.Y * y2; float zz2 = rotation.Z * z2; - return new Vector2( + return Create( value.X * (1.0f - yy2 - zz2) + value.Y * (xy2 - wz2), value.X * (xy2 + wz2) + value.Y * (1.0f - xx2 - zz2) ); @@ -569,28 +549,7 @@ public readonly bool TryCopyTo(Span destination) /// if the two vectors are equal; otherwise, . /// Two vectors are equal if their and elements are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Equals(Vector2 other) - { - // This function needs to account for floating-point equality around NaN - // and so must behave equivalently to the underlying float/double.Equals - - if (Vector64.IsHardwareAccelerated) - { - return Vector64.LoadUnsafe(ref Unsafe.AsRef(in X)).Equals(Vector64.LoadUnsafe(ref other.X)); - } - else if (Vector128.IsHardwareAccelerated) - { - return this.AsVector128().Equals(other.AsVector128()); - } - - return SoftwareFallback(in this, other); - - static bool SoftwareFallback(in Vector2 self, Vector2 other) - { - return self.X.Equals(other.X) - && self.Y.Equals(other.Y); - } - } + public readonly bool Equals(Vector2 other) => this.AsVector128().Equals(other.AsVector128()); /// Returns the hash code for this instance. /// The hash code. @@ -600,7 +559,7 @@ static bool SoftwareFallback(in Vector2 self, Vector2 other) /// The vector's length. /// [Intrinsic] - public readonly float Length() => MathF.Sqrt(LengthSquared()); + public readonly float Length() => float.Sqrt(LengthSquared()); /// Returns the length of the vector squared. /// The vector's length squared. 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 index 2eb006eeda745..ba7457ba8310a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs @@ -3,60 +3,22 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; namespace System.Numerics { public static unsafe partial class Vector { - /// Gets the element at the specified index. - /// The vector to get the element from. - /// The index of the element to get. - /// The value of the element at . - /// was less than zero or greater than the number of elements. + /// Converts a to a new with the new elements zeroed. + /// The vector to convert. + /// converted to a new with the new elements zeroed. [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static float GetElement(this Vector3 vector, int index) - { - if ((uint)(index) >= (uint)(Vector3.Count)) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } + public static Vector4 AsVector4(this Vector3 value) => value.AsVector128().AsVector4(); - return vector.GetElementUnsafe(index); - } - - /// Creates a new 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. - /// The vector to get the remaining elements from. - /// The index of the element to set. - /// The value to set the element to. - /// A with the value of the element at set to and the remaining elements set to the same value as that in . - /// was less than zero or greater than the number of elements. + /// Converts a to a new with the new elements undefined. + /// The vector to convert. + /// converted to a new with the new elements undefined. [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; - } + public static Vector4 AsVector4Unsafe(this Vector3 value) => value.AsVector128Unsafe().AsVector4(); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 7dc4994040eaa..29efe6d702831 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -31,16 +31,18 @@ public partial struct Vector3 : IEquatable, IFormattable /// Creates a new object whose three elements have the same value. /// The value to assign to all three elements. [Intrinsic] - public Vector3(float value) : this(value, value, value) + public Vector3(float value) { + this = Create(value); } /// Creates a new object from the specified object and the specified value. /// The vector with two elements. /// The additional value to assign to the field. [Intrinsic] - public Vector3(Vector2 value, float z) : this(value.X, value.Y, z) + public Vector3(Vector2 value, float z) { + this = Create(value, z); } /// Creates a vector whose elements have the specified values. @@ -50,21 +52,15 @@ public Vector3(Vector2 value, float z) : this(value.X, value.Y, z) [Intrinsic] public Vector3(float x, float y, float z) { - X = x; - Y = y; - Z = z; + this = Create(x, y, z); } /// Constructs a vector from the given . The span must contain at least 3 elements. /// The span of elements to assign to the vector. + [Intrinsic] public Vector3(ReadOnlySpan values) { - if (values.Length < 3) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values); - } - - this = Unsafe.ReadUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + this = Create(values); } /// Gets a vector whose 3 elements are equal to zero. @@ -80,7 +76,7 @@ public static Vector3 Zero public static Vector3 One { [Intrinsic] - get => new Vector3(1.0f); + get => Create(1.0f); } /// Gets the vector (1,0,0). @@ -88,7 +84,7 @@ public static Vector3 One public static Vector3 UnitX { [Intrinsic] - get => new Vector3(1.0f, 0.0f, 0.0f); + get => CreateScalar(1.0f); } /// Gets the vector (0,1,0). @@ -96,7 +92,7 @@ public static Vector3 UnitX public static Vector3 UnitY { [Intrinsic] - get => new Vector3(0.0f, 1.0f, 0.0f); + get => Create(0.0f, 1.0f, 0.0f); } /// Gets the vector (0,0,1). @@ -104,7 +100,7 @@ public static Vector3 UnitY public static Vector3 UnitZ { [Intrinsic] - get => new Vector3(0.0f, 0.0f, 1.0f); + get => Create(0.0f, 0.0f, 1.0f); } /// Gets or sets the element at the specified index. @@ -114,9 +110,24 @@ public static Vector3 UnitZ public float this[int index] { [Intrinsic] - readonly get => this.GetElement(index); + readonly get + { + if ((uint)index >= Count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + return this.AsVector128Unsafe().GetElement(index); + } - set => this = this.WithElement(index, value); + [Intrinsic] + set + { + if ((uint)index >= Count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + this = this.AsVector128Unsafe().WithElement(index, value).AsVector3(); + } } /// Adds two vectors together. @@ -126,14 +137,7 @@ public float this[int index] /// The method defines the addition operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 operator +(Vector3 left, Vector3 right) - { - return new Vector3( - left.X + right.X, - left.Y + right.Y, - left.Z + right.Z - ); - } + public static Vector3 operator +(Vector3 left, Vector3 right) => (left.AsVector128Unsafe() + right.AsVector128Unsafe()).AsVector3(); /// Divides the first vector by the second. /// The first vector. @@ -142,14 +146,7 @@ public float this[int index] /// The method defines the division operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 operator /(Vector3 left, Vector3 right) - { - return new Vector3( - left.X / right.X, - left.Y / right.Y, - left.Z / right.Z - ); - } + public static Vector3 operator /(Vector3 left, Vector3 right) => (left.AsVector128Unsafe() / right.AsVector128Unsafe()).AsVector3(); /// Divides the specified vector by a specified scalar value. /// The vector. @@ -157,7 +154,7 @@ public float this[int index] /// The result of the division. /// The method defines the division operation for objects. [Intrinsic] - public static Vector3 operator /(Vector3 value1, float value2) => value1 / new Vector3(value2); + public static Vector3 operator /(Vector3 value1, float value2) => (value1.AsVector128Unsafe() / value2).AsVector3(); /// Returns a value that indicates whether each pair of elements in two specified vectors is equal. /// The first vector to compare. @@ -166,12 +163,7 @@ public float this[int index] /// Two objects are equal if each element in is equal to the corresponding element in . [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Vector3 left, Vector3 right) - { - return (left.X == right.X) - && (left.Y == right.Y) - && (left.Z == right.Z); - } + public static bool operator ==(Vector3 left, Vector3 right) => left.AsVector128() == right.AsVector128(); /// Returns a value that indicates whether two specified vectors are not equal. /// The first vector to compare. @@ -187,14 +179,7 @@ public float this[int index] /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 operator *(Vector3 left, Vector3 right) - { - return new Vector3( - left.X * right.X, - left.Y * right.Y, - left.Z * right.Z - ); - } + public static Vector3 operator *(Vector3 left, Vector3 right) => (left.AsVector128Unsafe() * right.AsVector128Unsafe()).AsVector3(); /// Multiplies the specified vector by the specified scalar value. /// The vector. @@ -202,7 +187,7 @@ public float this[int index] /// The scaled vector. /// The method defines the multiplication operation for objects. [Intrinsic] - public static Vector3 operator *(Vector3 left, float right) => left * new Vector3(right); + public static Vector3 operator *(Vector3 left, float right) => (left.AsVector128Unsafe() * right).AsVector3(); /// Multiplies the scalar value by the specified vector. /// The vector. @@ -219,35 +204,21 @@ public float this[int index] /// The method defines the subtraction operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 operator -(Vector3 left, Vector3 right) - { - return new Vector3( - left.X - right.X, - left.Y - right.Y, - left.Z - right.Z - ); - } + public static Vector3 operator -(Vector3 left, Vector3 right) => (left.AsVector128Unsafe() - right.AsVector128Unsafe()).AsVector3(); /// Negates the specified vector. /// The vector to negate. /// The negated vector. /// The method defines the unary negation operation for objects. [Intrinsic] - public static Vector3 operator -(Vector3 value) => Zero - value; + public static Vector3 operator -(Vector3 value) => (-value.AsVector128Unsafe()).AsVector3(); /// Returns a vector whose elements are the absolute values of each of the specified vector's elements. /// A vector. /// The absolute value vector. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 Abs(Vector3 value) - { - return new Vector3( - MathF.Abs(value.X), - MathF.Abs(value.Y), - MathF.Abs(value.Z) - ); - } + public static Vector3 Abs(Vector3 value) => Vector128.Abs(value.AsVector128Unsafe()).AsVector3(); /// Adds two vectors together. /// The first vector to add. @@ -268,6 +239,56 @@ public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max) return Min(Max(value1, min), max); } + /// Creates a new object whose three elements have the same value. + /// The value to assign to all three elements. + /// A new whose three elements have the same value. + [Intrinsic] + public static Vector3 Create(float value) => Vector128.Create(value).AsVector3(); + + /// Creates a new object from the specified object and a Z and a W component. + /// The vector to use for the X and Y components. + /// The Z component. + /// A new from the specified object and a Z and a W component. + [Intrinsic] + public static Vector3 Create(Vector2 vector, float z) + { + return vector.AsVector128Unsafe() + .WithElement(2, z) + .AsVector3(); + } + + /// Creates a vector whose elements have the specified values. + /// The value to assign to the field. + /// The value to assign to the field. + /// The value to assign to the field. + /// A new whose elements have the specified values. + [Intrinsic] + public static Vector3 Create(float x, float y, float z) => Vector128.Create(x, y, z, 0).AsVector3(); + + /// Constructs a vector from the given . The span must contain at least 3 elements. + /// The span of elements to assign to the vector. + [Intrinsic] + public static Vector3 Create(ReadOnlySpan values) + { + if (values.Length < Count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values); + } + return Unsafe.ReadUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + } + + /// Creates a vector with initialized to the specified value and the remaining elements initialized to zero. + /// The value to assign to the field. + /// A new with initialized and the remaining elements initialized to zero. + [Intrinsic] + internal static Vector3 CreateScalar(float x) => Vector128.CreateScalar(x).AsVector3(); + + /// Creates a vector with initialized to the specified value and the remaining elements left uninitialized. + /// The value to assign to the field. + /// A new with initialized and the remaining elements left uninitialized. + [Intrinsic] + internal static Vector3 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector3(); + /// Computes the cross product of two vectors. /// The first vector. /// The second vector. @@ -275,7 +296,7 @@ public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Cross(Vector3 vector1, Vector3 vector2) { - return new Vector3( + return Create( (vector1.Y * vector2.Z) - (vector1.Z * vector2.Y), (vector1.Z * vector2.X) - (vector1.X * vector2.Z), (vector1.X * vector2.Y) - (vector1.Y * vector2.X) @@ -287,7 +308,7 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) /// The second point. /// The distance. [Intrinsic] - public static float Distance(Vector3 value1, Vector3 value2) => MathF.Sqrt(DistanceSquared(value1, value2)); + public static float Distance(Vector3 value1, Vector3 value2) => float.Sqrt(DistanceSquared(value1, value2)); /// Returns the Euclidean distance squared between two specified points. /// The first point. @@ -316,24 +337,12 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) /// The dot product. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Dot(Vector3 vector1, Vector3 vector2) - { - return (vector1.X * vector2.X) - + (vector1.Y * vector2.Y) - + (vector1.Z * vector2.Z); - } + public static float Dot(Vector3 vector1, Vector3 vector2) => Vector128.Dot(vector1.AsVector128(), vector2.AsVector128()); /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 FusedMultiplyAdd(Vector3 left, Vector3 right, Vector3 addend) - { - return new Vector3( - float.FusedMultiplyAdd(left.X, right.X, addend.X), - float.FusedMultiplyAdd(left.Y, right.Y, addend.Y), - float.FusedMultiplyAdd(left.Z, right.Z, addend.Z) - ); - } + public static Vector3 FusedMultiplyAdd(Vector3 left, Vector3 right, Vector3 addend) => Vector128.FusedMultiplyAdd(left.AsVector128Unsafe(), right.AsVector128Unsafe(), addend.AsVector128Unsafe()).AsVector3(); /// Performs a linear interpolation between two vectors based on the given weighting. /// The first vector. @@ -350,14 +359,7 @@ public static Vector3 FusedMultiplyAdd(Vector3 left, Vector3 right, Vector3 adde /// The maximized vector. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 Max(Vector3 value1, Vector3 value2) - { - return new Vector3( - (value1.X > value2.X) ? value1.X : value2.X, - (value1.Y > value2.Y) ? value1.Y : value2.Y, - (value1.Z > value2.Z) ? value1.Z : value2.Z - ); - } + public static Vector3 Max(Vector3 value1, Vector3 value2) => Vector128.Max(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); /// Returns a vector whose elements are the minimum of each of the pairs of elements in two specified vectors. /// The first vector. @@ -365,14 +367,7 @@ public static Vector3 Max(Vector3 value1, Vector3 value2) /// The minimized vector. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 Min(Vector3 value1, Vector3 value2) - { - return new Vector3( - (value1.X < value2.X) ? value1.X : value2.X, - (value1.Y < value2.Y) ? value1.Y : value2.Y, - (value1.Z < value2.Z) ? value1.Z : value2.Z - ); - } + public static Vector3 Min(Vector3 value1, Vector3 value2) => Vector128.Min(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); /// Returns a new vector whose values are the product of each pair of elements in two specified vectors. /// The first vector. @@ -398,14 +393,7 @@ public static Vector3 Min(Vector3 value1, Vector3 value2) /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 MultiplyAddEstimate(Vector3 left, Vector3 right, Vector3 addend) - { - return new Vector3( - float.MultiplyAddEstimate(left.X, right.X, addend.X), - float.MultiplyAddEstimate(left.Y, right.Y, addend.Y), - float.MultiplyAddEstimate(left.Z, right.Z, addend.Z) - ); - } + public static Vector3 MultiplyAddEstimate(Vector3 left, Vector3 right, Vector3 addend) => Vector128.MultiplyAddEstimate(left.AsVector128Unsafe(), right.AsVector128Unsafe(), addend.AsVector128Unsafe()).AsVector3(); /// Negates a specified vector. /// The vector to negate. @@ -431,14 +419,7 @@ public static Vector3 MultiplyAddEstimate(Vector3 left, Vector3 right, Vector3 a /// The square root vector. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 SquareRoot(Vector3 value) - { - return new Vector3( - MathF.Sqrt(value.X), - MathF.Sqrt(value.Y), - MathF.Sqrt(value.Z) - ); - } + public static Vector3 SquareRoot(Vector3 value) => Vector128.Sqrt(value.AsVector128Unsafe()).AsVector3(); /// Subtracts the second vector from the first. /// The first vector. @@ -475,7 +456,7 @@ public static Vector3 Transform(Vector3 value, Quaternion rotation) float yz2 = rotation.Y * z2; float zz2 = rotation.Z * z2; - return new Vector3( + return Create( value.X * (1.0f - yy2 - zz2) + value.Y * (xy2 - wz2) + value.Z * (xz2 + wy2), value.X * (xy2 + wz2) + value.Y * (1.0f - xx2 - zz2) + value.Z * (yz2 - wx2), value.X * (xz2 - wy2) + value.Y * (yz2 + wx2) + value.Z * (1.0f - xx2 - yy2) @@ -587,25 +568,7 @@ public readonly bool TryCopyTo(Span destination) /// if the two vectors are equal; otherwise, . /// Two vectors are equal if their , , and elements are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Equals(Vector3 other) - { - // This function needs to account for floating-point equality around NaN - // and so must behave equivalently to the underlying float/double.Equals - - if (Vector128.IsHardwareAccelerated) - { - return this.AsVector128().Equals(other.AsVector128()); - } - - return SoftwareFallback(in this, other); - - static bool SoftwareFallback(in Vector3 self, Vector3 other) - { - return self.X.Equals(other.X) - && self.Y.Equals(other.Y) - && self.Z.Equals(other.Z); - } - } + public readonly bool Equals(Vector3 other) => this.AsVector128().Equals(other.AsVector128()); /// Returns the hash code for this instance. /// The hash code. @@ -615,7 +578,7 @@ static bool SoftwareFallback(in Vector3 self, Vector3 other) /// The vector's length. /// [Intrinsic] - public readonly float Length() => MathF.Sqrt(LengthSquared()); + public readonly float Length() => float.Sqrt(LengthSquared()); /// Returns the length of the vector squared. /// The vector's length squared. 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 index 5e276425a0e53..8e243636d96e4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs @@ -12,7 +12,8 @@ public static unsafe partial class Vector /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . - internal static Plane AsPlane(this Vector4 value) + [Intrinsic] + public static Plane AsPlane(this Vector4 value) { #if MONO return Unsafe.As(ref value); @@ -24,7 +25,8 @@ internal static Plane AsPlane(this Vector4 value) /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . - internal static Quaternion AsQuaternion(this Vector4 value) + [Intrinsic] + public static Quaternion AsQuaternion(this Vector4 value) { #if MONO return Unsafe.As(ref value); @@ -33,37 +35,16 @@ internal static Quaternion AsQuaternion(this Vector4 value) #endif } - /// Gets the element at the specified index. - /// The vector to get the element from. - /// The index of the element to get. - /// The value of the element at . - /// was less than zero or greater than the number of elements. + /// Reinterprets a as a new . + /// The vector to reinterpret. + /// reinterpreted as a new . [Intrinsic] - internal static float GetElement(this Vector4 vector, int index) => vector.AsVector128().GetElement(index); + public static Vector2 AsVector2(this Vector4 value) => value.AsVector128().AsVector2(); - /// Creates a new 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. - /// The vector to get the remaining elements from. - /// The index of the element to set. - /// The value to set the element to. - /// A with the value of the element at set to and the remaining elements set to the same value as that in . - /// was less than zero or greater than the number of elements. + /// Reinterprets a as a new . + /// The vector to reinterpret. + /// reinterpreted as a new . [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector4 WithElement(this Vector4 vector, int index, float value) => vector.AsVector128().WithElement(index, value).AsVector4(); - - [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; - } + public static Vector3 AsVector3(this Vector4 value) => value.AsVector128().AsVector3(); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index f6893396cc4fc..65ae809ba6bc3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -37,7 +37,7 @@ public partial struct Vector4 : IEquatable, IFormattable [Intrinsic] public Vector4(float value) { - this = Vector128.Create(value).AsVector4(); + this = Create(value); } /// Creates a new object from the specified object and a Z and a W component. @@ -47,10 +47,7 @@ public Vector4(float value) [Intrinsic] public Vector4(Vector2 value, float z, float w) { - this = value.AsVector128() - .WithElement(2, z) - .WithElement(3, w) - .AsVector4(); + this = Create(value, z, w); } /// Constructs a new object from the specified object and a W component. @@ -59,9 +56,7 @@ public Vector4(Vector2 value, float z, float w) [Intrinsic] public Vector4(Vector3 value, float w) { - this = value.AsVector128() - .WithElement(3, w) - .AsVector4(); + this = Create(value, w); } /// Creates a vector whose elements have the specified values. @@ -72,14 +67,15 @@ public Vector4(Vector3 value, float w) [Intrinsic] public Vector4(float x, float y, float z, float w) { - this = Vector128.Create(x, y, z, w).AsVector4(); + this = Create(x, y, z, w); } /// Constructs a vector from the given . The span must contain at least 4 elements. /// The span of elements to assign to the vector. + [Intrinsic] public Vector4(ReadOnlySpan values) { - this = Vector128.Create(values).AsVector4(); + this = Create(values); } /// Gets a vector whose 4 elements are equal to zero. @@ -96,7 +92,7 @@ public static Vector4 Zero public static Vector4 One { [Intrinsic] - get => new Vector4(1); + get => Create(1); } /// Gets the vector (1,0,0,0). @@ -104,7 +100,7 @@ public static Vector4 One public static Vector4 UnitX { [Intrinsic] - get => new Vector4(1.0f, 0.0f, 0.0f, 0.0f); + get => CreateScalar(1.0f); } /// Gets the vector (0,1,0,0). @@ -112,7 +108,7 @@ public static Vector4 UnitX public static Vector4 UnitY { [Intrinsic] - get => new Vector4(0.0f, 1.0f, 0.0f, 0.0f); + get => Create(0.0f, 1.0f, 0.0f, 0.0f); } /// Gets the vector (0,0,1,0). @@ -120,7 +116,7 @@ public static Vector4 UnitY public static Vector4 UnitZ { [Intrinsic] - get => new Vector4(0.0f, 0.0f, 1.0f, 0.0f); + get => Create(0.0f, 0.0f, 1.0f, 0.0f); } /// Gets the vector (0,0,0,1). @@ -128,7 +124,7 @@ public static Vector4 UnitZ public static Vector4 UnitW { [Intrinsic] - get => new Vector4(0.0f, 0.0f, 0.0f, 1.0f); + get => Create(0.0f, 0.0f, 0.0f, 1.0f); } /// Gets or sets the element at the specified index. @@ -138,9 +134,13 @@ public static Vector4 UnitW public float this[int index] { [Intrinsic] - readonly get => this.GetElement(index); + readonly get => this.AsVector128().GetElement(index); - set => this = this.WithElement(index, value); + [Intrinsic] + set + { + this = this.AsVector128().WithElement(index, value).AsVector4(); + } } /// Adds two vectors together. @@ -167,7 +167,7 @@ public float this[int index] /// The result of the division. /// The method defines the division operation for objects. [Intrinsic] - public static Vector4 operator /(Vector4 value1, float value2) => value1 / new Vector4(value2); + public static Vector4 operator /(Vector4 value1, float value2) => (value1.AsVector128() / value2).AsVector4(); /// Returns a value that indicates whether each pair of elements in two specified vectors is equal. /// The first vector to compare. @@ -200,7 +200,7 @@ public float this[int index] /// The scaled vector. /// The method defines the multiplication operation for objects. [Intrinsic] - public static Vector4 operator *(Vector4 left, float right) => left * new Vector4(right); + public static Vector4 operator *(Vector4 left, float right) => (left.AsVector128() * right).AsVector4(); /// Multiplies the scalar value by the specified vector. /// The vector. @@ -253,12 +253,70 @@ public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max) return Min(Max(value1, min), max); } + /// Creates a new object whose four elements have the same value. + /// The value to assign to all four elements. + /// A new whose four elements have the same value. + [Intrinsic] + public static Vector4 Create(float value) => Vector128.Create(value).AsVector4(); + + /// Creates a new object from the specified object and a Z and a W component. + /// The vector to use for the X and Y components. + /// The Z component. + /// The W component. + /// A new from the specified object and a Z and a W component. + [Intrinsic] + public static Vector4 Create(Vector2 vector, float z, float w) + { + return vector.AsVector128Unsafe() + .WithElement(2, z) + .WithElement(3, w) + .AsVector4(); + } + + /// Constructs a new object from the specified object and a W component. + /// The vector to use for the X, Y, and Z components. + /// The W component. + /// A new from the specified object and a W component. + [Intrinsic] + public static Vector4 Create(Vector3 vector, float w) + { + return vector.AsVector128Unsafe() + .WithElement(3, w) + .AsVector4(); + } + + /// Creates a vector whose elements have the specified values. + /// The value to assign to the field. + /// The value to assign to the field. + /// The value to assign to the field. + /// The value to assign to the field. + /// A new whose elements have the specified values. + [Intrinsic] + public static Vector4 Create(float x, float y, float z, float w) => Vector128.Create(x, y, z, w).AsVector4(); + + /// Constructs a vector from the given . The span must contain at least 4 elements. + /// The span of elements to assign to the vector. + [Intrinsic] + public static Vector4 Create(ReadOnlySpan values) => Vector128.Create(values).AsVector4(); + + /// Creates a vector with initialized to the specified value and the remaining elements initialized to zero. + /// The value to assign to the field. + /// A new with initialized and the remaining elements initialized to zero. + [Intrinsic] + internal static Vector4 CreateScalar(float x) => Vector128.CreateScalar(x).AsVector4(); + + /// Creates a vector with initialized to the specified value and the remaining elements left uninitialized. + /// The value to assign to the field. + /// A new with initialized and the remaining elements left uninitialized. + [Intrinsic] + internal static Vector4 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector4(); + /// Computes the Euclidean distance between the two given points. /// The first point. /// The second point. /// The distance. [Intrinsic] - public static float Distance(Vector4 value1, Vector4 value2) => MathF.Sqrt(DistanceSquared(value1, value2)); + public static float Distance(Vector4 value1, Vector4 value2) => float.Sqrt(DistanceSquared(value1, value2)); /// Returns the Euclidean distance squared between two specified points. /// The first point. @@ -412,7 +470,7 @@ public static Vector4 Transform(Vector2 value, Quaternion rotation) float yz2 = rotation.Y * z2; float zz2 = rotation.Z * z2; - return new Vector4( + return Create( value.X * (1.0f - yy2 - zz2) + value.Y * (xy2 - wz2), value.X * (xy2 + wz2) + value.Y * (1.0f - xx2 - zz2), value.X * (xz2 - wy2) + value.Y * (yz2 + wx2), @@ -459,7 +517,7 @@ public static Vector4 Transform(Vector3 value, Quaternion rotation) float yz2 = rotation.Y * z2; float zz2 = rotation.Z * z2; - return new Vector4( + return Create( value.X * (1.0f - yy2 - zz2) + value.Y * (xy2 - wz2) + value.Z * (xz2 + wy2), value.X * (xy2 + wz2) + value.Y * (1.0f - xx2 - zz2) + value.Z * (yz2 - wx2), value.X * (xz2 - wy2) + value.Y * (yz2 + wx2) + value.Z * (1.0f - xx2 - yy2), @@ -506,7 +564,7 @@ public static Vector4 Transform(Vector4 value, Quaternion rotation) float yz2 = rotation.Y * z2; float zz2 = rotation.Z * z2; - return new Vector4( + return Create( value.X * (1.0f - yy2 - zz2) + value.Y * (xy2 - wz2) + value.Z * (xz2 + wy2), value.X * (xy2 + wz2) + value.Y * (1.0f - xx2 - zz2) + value.Z * (yz2 - wx2), value.X * (xz2 - wy2) + value.Y * (yz2 + wx2) + value.Z * (1.0f - xx2 - yy2), @@ -564,7 +622,7 @@ public static Vector4 Transform(Vector4 value, Quaternion rotation) /// The vector's length. /// [Intrinsic] - public readonly float Length() => MathF.Sqrt(LengthSquared()); + public readonly float Length() => float.Sqrt(LengthSquared()); /// Returns the length of the vector squared. /// The vector's length squared. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_1.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_1.cs index 4009387a4f796..1c47d03b513cd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_1.cs @@ -133,7 +133,7 @@ public Vector(Span values) : this((ReadOnlySpan)values) public static Vector AllBitsSet { [Intrinsic] - get => new Vector(Scalar.AllBitsSet); + get => Vector.Create(Scalar.AllBitsSet); } #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') @@ -195,7 +195,7 @@ public static bool IsSupported public static Vector One { [Intrinsic] - get => new Vector(Scalar.One); + get => Vector.Create(Scalar.One); } /// Gets a new with all elements initialized to zero. @@ -506,7 +506,7 @@ public T this[int index] /// The scalar to multiply with . /// The product of and . [Intrinsic] - public static Vector operator *(Vector value, T factor) => value * new Vector(factor); + public static Vector operator *(Vector value, T factor) => value * Vector.Create(factor); /// Multiplies a vector by a scalar to compute their product. /// The scalar to multiply with . diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index ea2446090399d..c92fa6a706b73 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -173,6 +173,7 @@ public static Vector128 As(this Vector128 vector) /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . + [Intrinsic] internal static Plane AsPlane(this Vector128 value) { #if MONO @@ -185,6 +186,7 @@ internal static Plane AsPlane(this Vector128 value) /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . + [Intrinsic] internal static Quaternion AsQuaternion(this Vector128 value) { #if MONO @@ -264,17 +266,17 @@ internal static Vector128 AsVector128(this Quaternion value) #endif } - /// Reinterprets a as a new . + /// Reinterprets a as a new with the new elements zeroed. /// The vector to reinterpret. - /// reinterpreted as a new . + /// reinterpreted as a new with the new elements zeroed. [Intrinsic] - public static Vector128 AsVector128(this Vector2 value) => new Vector4(value.X, value.Y, 0.0f, 0.0f).AsVector128(); + public static Vector128 AsVector128(this Vector2 value) => Vector4.Create(value, 0, 0).AsVector128(); - /// Reinterprets a as a new . + /// Reinterprets a as a new with the new elements zeroed. /// The vector to reinterpret. - /// reinterpreted as a new . + /// reinterpreted as a new with the new elements zeroed. [Intrinsic] - public static Vector128 AsVector128(this Vector3 value) => new Vector4(value.X, value.Y, value.Z, 0.0f).AsVector128(); + public static Vector128 AsVector128(this Vector3 value) => Vector4.Create(value, 0).AsVector128(); /// Reinterprets a as a new . /// The vector to reinterpret. @@ -305,6 +307,34 @@ public static Vector128 AsVector128(this Vector value) return Unsafe.ReadUnaligned>(ref address); } + /// Reinterprets a as a new , leaving the new elements undefined. + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + public static Vector128 AsVector128Unsafe(this Vector2 value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + Unsafe.SkipInit(out Vector128 result); + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Reinterprets a as a new , leaving the new elements undefined. + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + public static Vector128 AsVector128Unsafe(this Vector3 value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + Unsafe.SkipInit(out Vector128 result); + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . @@ -1109,6 +1139,14 @@ public static unsafe Vector128 Create(ulong e0, ulong e1) ); } + /// Creates a new instance with the lower and upper 64-bits initialized to a specified value. + /// The type of the elements in the vector. + /// The value that the lower and upper 64-bits will be initialized to. + /// A new with the lower and upper 64-bits initialized to . + /// The type of () is not supported. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 Create(Vector64 value) => Create(value, value); + /// Creates a new instance from two instances. /// The type of the elements in the vector. /// The value that the lower 64-bits will be initialized to. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index 4779812149be0..73d021ffc4447 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -1046,6 +1046,22 @@ public static Vector256 Create(ulong e0, ulong e1, ulong e2, ulong e3) ); } + /// Creates a new instance with all 64-bit parts initialized to a specified value. + /// The type of the elements in the vector. + /// The value that the 64-bit parts will be initialized to. + /// A new with the 64-bit parts initialized to . + /// The type of () is not supported. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Create(Vector64 value) => Create(Vector128.Create(value, value)); + + /// Creates a new instance with the lower and upper 128-bits initialized to a specified value. + /// The type of the elements in the vector. + /// The value that the lower and upper 128-bits will be initialized to. + /// A new with the lower and upper 128-bits initialized to . + /// The type of () is not supported. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Create(Vector128 value) => Create(value, value); + /// Creates a new instance from two instances. /// The type of the elements in the vector. /// The value that the lower 128-bits will be initialized to. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs index 4e534e8ac3947..7a80c3c393783 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs @@ -1108,6 +1108,30 @@ public static Vector512 Create(ulong e0, ulong e1, ulong e2, ulong e3, ul ); } + /// Creates a new instance with all 64-bit parts initialized to a specified value. + /// The type of the elements in the vector. + /// The value that the 64-bit parts will be initialized to. + /// A new with the 64-bit parts initialized to . + /// The type of () is not supported. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Create(Vector64 value) => Create(Vector128.Create(value, value)); + + /// Creates a new instance with all 128-bit parts initialized to a specified value. + /// The type of the elements in the vector. + /// The value that the 128-bit parts will be initialized to. + /// A new with the 128-bit parts initialized to . + /// The type of () is not supported. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Create(Vector128 value) => Create(Vector256.Create(value, value)); + + /// Creates a new instance with the lower and upper 256-bits initialized to a specified value. + /// The type of the elements in the vector. + /// The value that the lower and upper 256-bits will be initialized to. + /// A new with the lower and upper 256-bits initialized to . + /// The type of () is not supported. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Create(Vector256 value) => Create(value, value); + /// Creates a new instance from two instances. /// The type of the elements in the vector. /// The value that the lower 256-bits will be initialized to. diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/IndexOfAnyAsciiSearcher.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/IndexOfAnyAsciiSearcher.cs index deccdddb8fece..42e0fcc2a65e7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/IndexOfAnyAsciiSearcher.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/IndexOfAnyAsciiSearcher.cs @@ -17,7 +17,7 @@ internal static class IndexOfAnyAsciiSearcher { public struct AsciiState(Vector128 bitmap, BitVector256 lookup) { - public Vector256 Bitmap = Vector256.Create(bitmap, bitmap); + public Vector256 Bitmap = Vector256.Create(bitmap); public BitVector256 Lookup = lookup; public readonly AsciiState CreateInverse() => @@ -26,8 +26,8 @@ public readonly AsciiState CreateInverse() => public struct AnyByteState(Vector128 bitmap0, Vector128 bitmap1, BitVector256 lookup) { - public Vector256 Bitmap0 = Vector256.Create(bitmap0, bitmap0); - public Vector256 Bitmap1 = Vector256.Create(bitmap1, bitmap1); + public Vector256 Bitmap0 = Vector256.Create(bitmap0); + public Vector256 Bitmap1 = Vector256.Create(bitmap1); public BitVector256 Lookup = lookup; } @@ -146,7 +146,7 @@ private static unsafe bool TryIndexOfAny(ref short searchSpace, int se { // Only initializing the bitmap here is okay as we can only get here if the search space is long enough // and we support vectorization, so the IndexOfAnyVectorized implementation will never touch state.Lookup. - state.Bitmap = Vector256.Create(state.Bitmap._lower, state.Bitmap._lower); + state.Bitmap = Vector256.Create(state.Bitmap.GetLower()); index = (Ssse3.IsSupported || PackedSimd.IsSupported) && needleContainsZero ? IndexOfAny(ref searchSpace, searchSpaceLength, ref state) @@ -173,7 +173,7 @@ private static unsafe bool TryLastIndexOfAny(ref short searchSpace, in { // Only initializing the bitmap here is okay as we can only get here if the search space is long enough // and we support vectorization, so the LastIndexOfAnyVectorized implementation will never touch state.Lookup. - state.Bitmap = Vector256.Create(state.Bitmap._lower, state.Bitmap._lower); + state.Bitmap = Vector256.Create(state.Bitmap.GetLower()); index = (Ssse3.IsSupported || PackedSimd.IsSupported) && needleContainsZero ? LastIndexOfAny(ref searchSpace, searchSpaceLength, ref state) diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs index 3c93ad6cd46d4..3211c0c320f83 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs @@ -411,7 +411,7 @@ private static int IndexOfAnyVectorizedAvx512(ref char searchS if (searchSpaceLength > 32) { - Vector512 charMap512 = Vector512.Create(charMap256, charMap256); + Vector512 charMap512 = Vector512.Create(charMap256); if (searchSpaceLength > 64) { @@ -499,8 +499,8 @@ private static int IndexOfAnyVectorized(ref char searchSpace, if (Avx2.IsSupported && searchSpaceLength >= 32) #pragma warning restore IntrinsicsInSystemPrivateCoreLibAttributeNotSpecificEnough { - Vector256 charMapLower256 = Vector256.Create(charMapLower, charMapLower); - Vector256 charMapUpper256 = Vector256.Create(charMapUpper, charMapUpper); + Vector256 charMapLower256 = Vector256.Create(charMapLower); + Vector256 charMapUpper256 = Vector256.Create(charMapUpper); ref char lastStartVectorAvx2 = ref Unsafe.Subtract(ref searchSpaceEnd, 32); @@ -586,7 +586,7 @@ private static int LastIndexOfAnyVectorizedAvx512(ref char sea if (searchSpaceLength > 32) { - Vector512 charMap512 = Vector512.Create(charMap256, charMap256); + Vector512 charMap512 = Vector512.Create(charMap256); if (searchSpaceLength > 64) { @@ -676,8 +676,8 @@ private static int LastIndexOfAnyVectorized(ref char searchSpa if (Avx2.IsSupported && searchSpaceLength >= 32) #pragma warning restore IntrinsicsInSystemPrivateCoreLibAttributeNotSpecificEnough { - Vector256 charMapLower256 = Vector256.Create(charMapLower, charMapLower); - Vector256 charMapUpper256 = Vector256.Create(charMapUpper, charMapUpper); + Vector256 charMapLower256 = Vector256.Create(charMapLower); + Vector256 charMapUpper256 = Vector256.Create(charMapUpper); ref char lastStartVectorAvx2 = ref Unsafe.Add(ref searchSpace, 32); diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/Strings/Helpers/TeddyBucketizer.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/Strings/Helpers/TeddyBucketizer.cs index c277e6a8f72af..666889e4383e2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/Strings/Helpers/TeddyBucketizer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/Strings/Helpers/TeddyBucketizer.cs @@ -35,7 +35,7 @@ public static (Vector512 Low, Vector512 High) GenerateNonBucketizedF high.SetElementUnsafe(highNibble, (byte)(high.GetElementUnsafe(highNibble) | bit)); } - return (DuplicateTo512(low), DuplicateTo512(high)); + return (Vector512.Create(low), Vector512.Create(high)); } // We can have up to 8 buckets, and their positions are encoded by 1 bit each. @@ -69,14 +69,7 @@ public static (Vector512 Low, Vector512 High) GenerateBucketizedFing } } - return (DuplicateTo512(low), DuplicateTo512(high)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector512 DuplicateTo512(Vector128 vector) - { - Vector256 vector256 = Vector256.Create(vector, vector); - return Vector512.Create(vector256, vector256); + return (Vector512.Create(low), Vector512.Create(high)); } public static string[][] Bucketize(ReadOnlySpan values, int bucketCount, int n) diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs index 9ef07d114da67..ced611ec012a9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs @@ -65,7 +65,7 @@ public static unsafe void Fill(ref T refData, nuint numElements, T value) } else if (Vector.Count == 32) { - vector = Vector256.Create(vec128, vec128).AsVector(); + vector = Vector256.Create(vec128).AsVector(); } else { diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index a8be59ed29889..44e3fe8e05fe4 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -34,6 +34,8 @@ public static partial class Vector128 public static System.Runtime.Intrinsics.Vector128 AsVector128(this System.Numerics.Vector2 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsVector128(this System.Numerics.Vector3 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsVector128(this System.Numerics.Vector4 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AsVector128Unsafe(this System.Numerics.Vector2 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AsVector128Unsafe(this System.Numerics.Vector3 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsVector128(this System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector2 AsVector2(this System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Numerics.Vector3 AsVector3(this System.Runtime.Intrinsics.Vector128 value) { throw null; } @@ -152,6 +154,7 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static System.Runtime.Intrinsics.Vector128 CreateScalarUnsafe(T value) { throw null; } public static System.Runtime.Intrinsics.Vector128 CreateSequence(T start, T step) { throw null; } public static System.Runtime.Intrinsics.Vector128 Create(System.ReadOnlySpan values) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Create(System.Runtime.Intrinsics.Vector64 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 Create(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) { throw null; } public static System.Runtime.Intrinsics.Vector128 Create(T value) { throw null; } public static System.Runtime.Intrinsics.Vector128 Create(T[] values) { throw null; } @@ -497,6 +500,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static System.Runtime.Intrinsics.Vector256 CreateScalarUnsafe(T value) { throw null; } public static System.Runtime.Intrinsics.Vector256 CreateSequence(T start, T step) { throw null; } public static System.Runtime.Intrinsics.Vector256 Create(System.ReadOnlySpan values) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Create(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Create(System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector256 Create(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) { throw null; } public static System.Runtime.Intrinsics.Vector256 Create(T value) { throw null; } public static System.Runtime.Intrinsics.Vector256 Create(T[] values) { throw null; } @@ -842,6 +847,9 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static System.Runtime.Intrinsics.Vector512 CreateScalarUnsafe(T value) { throw null; } public static System.Runtime.Intrinsics.Vector512 CreateSequence(T start, T step) { throw null; } public static System.Runtime.Intrinsics.Vector512 Create(System.ReadOnlySpan values) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Create(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Create(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Create(System.Runtime.Intrinsics.Vector256 value) { throw null; } public static System.Runtime.Intrinsics.Vector512 Create(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) { throw null; } public static System.Runtime.Intrinsics.Vector512 Create(T value) { throw null; } public static System.Runtime.Intrinsics.Vector512 Create(T[] values) { throw null; }