diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index d467d903c8ab4..08307977ac692 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3292,6 +3292,31 @@ class Compiler CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdIsNaNNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdIsNegativeNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdIsPositiveNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdIsPositiveInfinityNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdIsZeroNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + GenTree* gtNewSimdLoadNode( var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize); @@ -3307,18 +3332,33 @@ class Compiler CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdMaxNativeNode(var_types type, + GenTree* op1, + GenTree* op2, + CorInfoType simdBaseJitType, + unsigned simdSize); + GenTree* gtNewSimdMinNode(var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdMinNativeNode(var_types type, + GenTree* op1, + GenTree* op2, + CorInfoType simdBaseJitType, + unsigned simdSize); + GenTree* gtNewSimdNarrowNode(var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdRoundNode( + var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdShuffleNode(var_types type, GenTree* op1, GenTree* op2, @@ -3356,6 +3396,9 @@ class Compiler CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdTruncNode( + var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdUnOpNode(genTreeOps op, var_types type, GenTree* op1, diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 4093f3b796bdf..dc766772d1bfe 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -20671,15 +20671,13 @@ GenTree* Compiler::gtNewSimdAbsNode(var_types type, GenTree* op1, CorInfoType si { GenTree* tmp; GenTree* op1Dup1 = fgMakeMultiUse(&op1); - GenTree* op1Dup2 = fgMakeMultiUse(&op1Dup1); + GenTree* op1Dup2 = gtCloneExpr(op1Dup1); - // op1 = op1 < Zero - tmp = gtNewZeroConNode(type); - op1 = gtNewSimdCmpOpNode(GT_LT, type, op1, tmp, simdBaseJitType, simdSize); + // op1 = IsNegative(op1) + op1 = gtNewSimdIsNegativeNode(type, op1, simdBaseJitType, simdSize); - // tmp = Zero - op1Dup1 - tmp = gtNewZeroConNode(type); - tmp = gtNewSimdBinOpNode(GT_SUB, type, tmp, op1Dup1, simdBaseJitType, simdSize); + // tmp = -op1Dup1 + tmp = gtNewSimdUnOpNode(GT_NEG, type, op1Dup1, simdBaseJitType, simdSize); // result = ConditionalSelect(op1, tmp, op1Dup2) return gtNewSimdCndSelNode(type, op1, tmp, op1Dup2, simdBaseJitType, simdSize); @@ -21417,9 +21415,8 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, // mask1 contains the output either 0xFFFFFFFF or 0. // FixupVal zeros out any NaN values in the input by ANDing input with mask1. GenTree* op1Clone1 = fgMakeMultiUse(&op1); - GenTree* op1Clone2 = fgMakeMultiUse(&op1); - GenTree* mask1 = gtNewSimdCmpOpNode(GT_EQ, type, op1, op1Clone1, simdSourceBaseJitType, simdSize); - fixupVal = gtNewSimdBinOpNode(GT_AND, type, op1Clone2, mask1, simdSourceBaseJitType, simdSize); + GenTree* mask1 = gtNewSimdIsNaNNode(type, op1, simdSourceBaseJitType, simdSize); + fixupVal = gtNewSimdBinOpNode(GT_AND_NOT, type, op1Clone1, mask1, simdSourceBaseJitType, simdSize); } if (varTypeIsSigned(simdTargetBaseType)) @@ -21766,6 +21763,7 @@ GenTree* Compiler::gtNewSimdCmpOpNode( case GT_GE: case GT_LE: + case GT_NE: { needsConvertMaskToVector = (simdSize == 64) || (varTypeIsIntegral(simdBaseType) && canUseEvexEncoding()); break; @@ -21780,7 +21778,7 @@ GenTree* Compiler::gtNewSimdCmpOpNode( default: { - break; + unreached(); } } #endif // TARGET_XARCH @@ -21852,12 +21850,12 @@ GenTree* Compiler::gtNewSimdCmpOpNode( if (op == GT_GE) { // EQ(Max(op1, op2), op1) - op1 = gtNewSimdMaxNode(type, op1, op2, simdBaseJitType, simdSize); + op1 = gtNewSimdMaxNativeNode(type, op1, op2, simdBaseJitType, simdSize); } else { // EQ(Min(op1, op2), op1) - op1 = gtNewSimdMinNode(type, op1, op2, simdBaseJitType, simdSize); + op1 = gtNewSimdMinNativeNode(type, op1, op2, simdBaseJitType, simdSize); } return gtNewSimdCmpOpNode(GT_EQ, type, op1, op1Dup, simdBaseJitType, simdSize); } @@ -22017,10 +22015,10 @@ GenTree* Compiler::gtNewSimdCmpOpNode( // result = BitwiseOr(op1, op2) GenTree* op1Dup1 = fgMakeMultiUse(&op1); - GenTree* op1Dup2 = fgMakeMultiUse(&op1Dup1); + GenTree* op1Dup2 = gtCloneExpr(op1Dup1); GenTree* op2Dup1 = fgMakeMultiUse(&op2); - GenTree* op2Dup2 = fgMakeMultiUse(&op2Dup1); + GenTree* op2Dup2 = gtCloneExpr(op2Dup1); GenTree* t = gtNewSimdCmpOpNode(op, type, op1, op2, CORINFO_TYPE_INT, simdSize); GenTree* u = gtNewSimdCmpOpNode(GT_EQ, type, op1Dup1, op2Dup1, CORINFO_TYPE_INT, simdSize); @@ -22043,6 +22041,17 @@ GenTree* Compiler::gtNewSimdCmpOpNode( } #endif // TARGET_XARCH + case GT_NE: + { +#if defined(TARGET_XARCH) + assert(varTypeIsIntegral(simdBaseType)); + assert(!canUseEvexEncodingDebugOnly()); +#endif // TARGET_XARCH + + GenTree* result = gtNewSimdCmpOpNode(GT_EQ, type, op1, op2, simdBaseJitType, simdSize); + return gtNewSimdUnOpNode(GT_NOT, type, result, simdBaseJitType, simdSize); + } + default: { unreached(); @@ -23340,6 +23349,187 @@ GenTree* Compiler::gtNewSimdGetUpperNode(var_types type, GenTree* op1, CorInfoTy return gtNewSimdHWIntrinsicNode(type, op1, intrinsicId, simdBaseJitType, simdSize); } +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsNaNNode: Creates a new simd IsNaN node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for NaNs +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsNaN node +// +GenTree* Compiler::gtNewSimdIsNaNNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + if (varTypeIsFloating(simdBaseType)) + { + GenTree* op1Dup = fgMakeMultiUse(&op1); + return gtNewSimdCmpOpNode(GT_NE, type, op1, op1Dup, simdBaseJitType, simdSize); + } + return gtNewZeroConNode(type); +} + +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsNegativeNode: Creates a new simd IsNegative node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for Negatives +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsNegative node +// +GenTree* Compiler::gtNewSimdIsNegativeNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + if (simdBaseJitType == CORINFO_TYPE_FLOAT) + { + simdBaseJitType = CORINFO_TYPE_INT; + } + else if (simdBaseJitType == CORINFO_TYPE_DOUBLE) + { + simdBaseJitType = CORINFO_TYPE_LONG; + } + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsIntegral(simdBaseType)); + + if (varTypeIsUnsigned(simdBaseType)) + { + return gtNewZeroConNode(type); + } + return gtNewSimdCmpOpNode(GT_LT, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize); +} + +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsPositiveNode: Creates a new simd IsPositive node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for Positives +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsPositive node +// +GenTree* Compiler::gtNewSimdIsPositiveNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + if (simdBaseJitType == CORINFO_TYPE_FLOAT) + { + simdBaseJitType = CORINFO_TYPE_INT; + } + else if (simdBaseJitType == CORINFO_TYPE_DOUBLE) + { + simdBaseJitType = CORINFO_TYPE_LONG; + } + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsIntegral(simdBaseType)); + + if (varTypeIsUnsigned(simdBaseType)) + { + return gtNewAllBitsSetConNode(type); + } + return gtNewSimdCmpOpNode(GT_GE, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize); +} + +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsPositiveInfinityNode: Creates a new simd IsPositiveInfinity node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for PositiveInfinities +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsPositiveInfinity node +// +GenTree* Compiler::gtNewSimdIsPositiveInfinityNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + if (varTypeIsFloating(simdBaseType)) + { + double infinity = BitOperations::UInt64BitsToDouble(0x7FF0000000000000); + GenTree* cnsNode = gtNewDconNode(infinity, simdBaseType); + cnsNode = gtNewSimdCreateBroadcastNode(type, cnsNode, simdBaseJitType, simdSize); + return gtNewSimdCmpOpNode(GT_EQ, type, op1, cnsNode, simdBaseJitType, simdSize); + } + return gtNewZeroConNode(type); +} + +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsZeroNode: Creates a new simd IsZero node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for Zeroes +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsZero node +// +GenTree* Compiler::gtNewSimdIsZeroNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + return gtNewSimdCmpOpNode(GT_EQ, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize); +} + //---------------------------------------------------------------------------------------------- // Compiler::gtNewSimdLoadNode: Creates a new simd Load node // @@ -23543,6 +23733,50 @@ GenTree* Compiler::gtNewSimdMaxNode( var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); assert(varTypeIsArithmetic(simdBaseType)); +#if defined(TARGET_XARCH) + if (varTypeIsFloating(simdBaseType)) + { + GenTree* op1Dup1 = fgMakeMultiUse(&op1); + GenTree* op1Dup2 = gtCloneExpr(op1Dup1); + GenTree* op1Dup3 = gtCloneExpr(op1Dup2); + + GenTree* op2Dup1 = fgMakeMultiUse(&op2); + GenTree* op2Dup2 = gtCloneExpr(op2Dup1); + GenTree* op2Dup3 = gtCloneExpr(op2Dup2); + + GenTree* equalsMask = gtNewSimdCmpOpNode(GT_EQ, type, op1, op2, simdBaseJitType, simdSize); + GenTree* isNegativeMask = gtNewSimdIsNegativeNode(type, op2Dup1, simdBaseJitType, simdSize); + GenTree* isNaNMask = gtNewSimdIsNaNNode(type, op1Dup1, simdBaseJitType, simdSize); + GenTree* lessThanMask = gtNewSimdCmpOpNode(GT_LT, type, op2Dup2, op1Dup2, simdBaseJitType, simdSize); + + GenTree* mask = gtNewSimdBinOpNode(GT_AND, type, equalsMask, isNegativeMask, simdBaseJitType, simdSize); + mask = gtNewSimdBinOpNode(GT_OR, type, mask, isNaNMask, simdBaseJitType, simdSize); + mask = gtNewSimdBinOpNode(GT_OR, type, mask, lessThanMask, simdBaseJitType, simdSize); + + return gtNewSimdCndSelNode(type, mask, op1Dup3, op2Dup3, simdBaseJitType, simdSize); + } +#endif // TARGET_XARCH + + return gtNewSimdMaxNativeNode(type, op1, op2, simdBaseJitType, simdSize); +} + +GenTree* Compiler::gtNewSimdMaxNativeNode( + var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + assert(op2 != nullptr); + assert(op2->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + NamedIntrinsic intrinsic = NI_Illegal; #if defined(TARGET_XARCH) @@ -23658,7 +23892,7 @@ GenTree* Compiler::gtNewSimdMaxNode( op2 = gtNewSimdBinOpNode(fixupOp1, type, op2, vecCon2, opJitType, simdSize); // op1 = Max(op1, op2) - op1 = gtNewSimdMaxNode(type, op1, op2, simdBaseJitType, simdSize); + op1 = gtNewSimdMaxNativeNode(type, op1, op2, simdBaseJitType, simdSize); // result = op1 + constVector // -or- @@ -23758,6 +23992,50 @@ GenTree* Compiler::gtNewSimdMinNode( var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); assert(varTypeIsArithmetic(simdBaseType)); +#if defined(TARGET_XARCH) + if (varTypeIsFloating(simdBaseType)) + { + GenTree* op1Dup1 = fgMakeMultiUse(&op1); + GenTree* op1Dup2 = gtCloneExpr(op1Dup1); + GenTree* op1Dup3 = gtCloneExpr(op1Dup2); + GenTree* op1Dup4 = gtCloneExpr(op1Dup3); + + GenTree* op2Dup1 = fgMakeMultiUse(&op2); + GenTree* op2Dup2 = gtCloneExpr(op2Dup1); + + GenTree* equalsMask = gtNewSimdCmpOpNode(GT_EQ, type, op1, op2, simdBaseJitType, simdSize); + GenTree* isNegativeMask = gtNewSimdIsNegativeNode(type, op1Dup1, simdBaseJitType, simdSize); + GenTree* isNaNMask = gtNewSimdIsNaNNode(type, op1Dup2, simdBaseJitType, simdSize); + GenTree* lessThanMask = gtNewSimdCmpOpNode(GT_LT, type, op1Dup3, op2Dup1, simdBaseJitType, simdSize); + + GenTree* mask = gtNewSimdBinOpNode(GT_AND, type, equalsMask, isNegativeMask, simdBaseJitType, simdSize); + mask = gtNewSimdBinOpNode(GT_OR, type, mask, isNaNMask, simdBaseJitType, simdSize); + mask = gtNewSimdBinOpNode(GT_OR, type, mask, lessThanMask, simdBaseJitType, simdSize); + + return gtNewSimdCndSelNode(type, mask, op1Dup4, op2Dup2, simdBaseJitType, simdSize); + } +#endif // TARGET_XARCH + + return gtNewSimdMinNativeNode(type, op1, op2, simdBaseJitType, simdSize); +} + +GenTree* Compiler::gtNewSimdMinNativeNode( + var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + assert(op2 != nullptr); + assert(op2->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + NamedIntrinsic intrinsic = NI_Illegal; #if defined(TARGET_XARCH) @@ -23856,7 +24134,7 @@ GenTree* Compiler::gtNewSimdMinNode( GenTree* constVector = gtNewSimdCreateBroadcastNode(type, constVal, CORINFO_TYPE_INT, simdSize); GenTree* constVectorDup1 = fgMakeMultiUse(&constVector); - GenTree* constVectorDup2 = fgMakeMultiUse(&constVectorDup1); + GenTree* constVectorDup2 = gtCloneExpr(constVectorDup1); // op1 = op1 - constVector // -or- @@ -23869,7 +24147,7 @@ GenTree* Compiler::gtNewSimdMinNode( op2 = gtNewSimdBinOpNode(fixupOp1, type, op2, constVectorDup1, opJitType, simdSize); // op1 = Min(op1, op2) - op1 = gtNewSimdMinNode(type, op1, op2, simdBaseJitType, simdSize); + op1 = gtNewSimdMinNativeNode(type, op1, op2, simdBaseJitType, simdSize); // result = op1 + constVectorDup2 // -or- @@ -24477,6 +24755,67 @@ GenTree* Compiler::gtNewSimdNarrowNode( #endif // !TARGET_XARCH && !TARGET_ARM64 } +//------------------------------------------------------------------------ +// gtNewSimdRoundNode: Creates a new simd Round node +// +// Arguments: +// type -- The type of the node +// op1 -- The node to round +// simdBaseJitType -- the base jit type of the node +// simdSize -- the simd size of the node +// +// Return Value: +// The round node +// +GenTree* Compiler::gtNewSimdRoundNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsFloating(simdBaseType)); + + NamedIntrinsic intrinsic = NI_Illegal; + +#if defined(TARGET_XARCH) + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + intrinsic = NI_AVX_RoundToNearestInteger; + } + else if (simdSize == 64) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX512F)); + GenTree* op2 = gtNewIconNode(static_cast(FloatRoundingMode::ToNearestInteger)); + return gtNewSimdHWIntrinsicNode(type, op1, op2, NI_AVX512F_RoundScale, simdBaseJitType, simdSize); + } + else + { + assert(compIsaSupportedDebugOnly(InstructionSet_SSE41)); + intrinsic = NI_SSE41_RoundToNearestInteger; + } +#elif defined(TARGET_ARM64) + if (simdBaseType == TYP_DOUBLE) + { + intrinsic = (simdSize == 8) ? NI_AdvSimd_RoundToNearestScalar : NI_AdvSimd_Arm64_RoundToNearest; + } + else + { + intrinsic = NI_AdvSimd_RoundToNearest; + } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + assert(intrinsic != NI_Illegal); + return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize); +} + GenTree* Compiler::gtNewSimdShuffleNode( var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) { @@ -25416,6 +25755,67 @@ GenTree* Compiler::gtNewSimdToScalarNode(var_types type, GenTree* op1, CorInfoTy return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize); } +//------------------------------------------------------------------------ +// gtNewSimdTruncNode: Creates a new simd Truncate node +// +// Arguments: +// type -- The type of the node +// op1 -- The node to truncate +// simdBaseJitType -- the base jit type of the node +// simdSize -- the simd size of the node +// +// Return Value: +// The truncate node +// +GenTree* Compiler::gtNewSimdTruncNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsFloating(simdBaseType)); + + NamedIntrinsic intrinsic = NI_Illegal; + +#if defined(TARGET_XARCH) + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + intrinsic = NI_AVX_RoundToZero; + } + else if (simdSize == 64) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX512F)); + GenTree* op2 = gtNewIconNode(static_cast(FloatRoundingMode::ToZero)); + return gtNewSimdHWIntrinsicNode(type, op1, op2, NI_AVX512F_RoundScale, simdBaseJitType, simdSize); + } + else + { + assert(compIsaSupportedDebugOnly(InstructionSet_SSE41)); + intrinsic = NI_SSE41_RoundToZero; + } +#elif defined(TARGET_ARM64) + if (simdBaseType == TYP_DOUBLE) + { + intrinsic = (simdSize == 8) ? NI_AdvSimd_RoundToZeroScalar : NI_AdvSimd_Arm64_RoundToZero; + } + else + { + intrinsic = NI_AdvSimd_RoundToZero; + } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + assert(intrinsic != NI_Illegal); + return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize); +} + GenTree* Compiler::gtNewSimdUnOpNode( genTreeOps op, var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 8f52fe617a9f7..2827565569e42 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -1585,6 +1585,61 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_IsNaN: + case NI_Vector128_IsNaN: + { + assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsNaNNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector64_IsNegative: + case NI_Vector128_IsNegative: + { + assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsNegativeNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector64_IsPositive: + case NI_Vector128_IsPositive: + { + assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsPositiveNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector64_IsPositiveInfinity: + case NI_Vector128_IsPositiveInfinity: + { + assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsPositiveInfinityNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector64_IsZero: + case NI_Vector128_IsZero: + { + assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsZeroNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_LessThan: case NI_Vector128_LessThan: { @@ -1756,6 +1811,23 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_MaxNative: + case NI_Vector128_MaxNative: + { + assert(sig->numArgs == 2); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + retNode = gtNewSimdMaxNativeNode(retType, op1, op2, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_Min: case NI_Vector128_Min: { @@ -1768,6 +1840,23 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_MinNative: + case NI_Vector128_MinNative: + { + assert(sig->numArgs == 2); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + retNode = gtNewSimdMinNativeNode(retType, op1, op2, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_op_Multiply: case NI_Vector128_op_Multiply: { @@ -1792,24 +1881,34 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_MultiplyAddEstimate: { assert(sig->numArgs == 3); - assert(varTypeIsFloating(simdBaseType)); if (BlockNonDeterministicIntrinsics(mustExpand)) { break; } - impSpillSideEffect(true, verCurrentState.esStackDepth - - 3 DEBUGARG("Spilling op1 side effects for MultiplyAddEstimate")); + if (varTypeIsFloating(simdBaseType)) + { + impSpillSideEffect(true, verCurrentState.esStackDepth - + 3 DEBUGARG("Spilling op1 side effects for MultiplyAddEstimate")); - impSpillSideEffect(true, verCurrentState.esStackDepth - - 2 DEBUGARG("Spilling op2 side effects for MultiplyAddEstimate")); + impSpillSideEffect(true, verCurrentState.esStackDepth - + 2 DEBUGARG("Spilling op2 side effects for MultiplyAddEstimate")); + } op3 = impSIMDPopStack(); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); - retNode = gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); + if (varTypeIsFloating(simdBaseType)) + { + retNode = gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); + } + else + { + GenTree* mulNode = gtNewSimdBinOpNode(GT_MUL, retType, op1, op2, simdBaseJitType, simdSize); + retNode = gtNewSimdBinOpNode(GT_ADD, retType, mulNode, op3, simdBaseJitType, simdSize); + } break; } @@ -1913,6 +2012,25 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_Round: + case NI_Vector128_Round: + { + if (sig->numArgs != 1) + { + break; + } + + if (!varTypeIsFloating(simdBaseType)) + { + retNode = impSIMDPopStack(); + break; + } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdRoundNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_Shuffle: case NI_Vector128_Shuffle: { @@ -2255,6 +2373,22 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_Truncate: + case NI_Vector128_Truncate: + { + assert(sig->numArgs == 1); + + if (!varTypeIsFloating(simdBaseType)) + { + retNode = impSIMDPopStack(); + break; + } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdTruncNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_WidenLower: case NI_Vector128_WidenLower: { diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 1881a70c041f1..6f3130264e7d7 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -60,6 +60,11 @@ HARDWARE_INTRINSIC(Vector64, GreaterThanAny, HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqual, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, IsNaN, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsNegative, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsPositive, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsPositiveInfinity, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsZero, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, LessThan, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, LessThanAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, LessThanAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -70,9 +75,12 @@ HARDWARE_INTRINSIC(Vector64, LoadAligned, HARDWARE_INTRINSIC(Vector64, LoadAlignedNonTemporal, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, LoadUnsafe, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, Max, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, MaxNative, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, Min, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, MinNative, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, MultiplyAddEstimate, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, Narrow, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Round, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, Shuffle, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector64, Sqrt, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -82,6 +90,7 @@ HARDWARE_INTRINSIC(Vector64, Sum, HARDWARE_INTRINSIC(Vector64, ToScalar, 8, 1, true, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector64, ToVector128, 8, 1, true, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector64, ToVector128Unsafe, 8, 1, true, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector64, Truncate, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, WidenLower, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, WidenUpper, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, WithElement, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport) @@ -164,6 +173,11 @@ HARDWARE_INTRINSIC(Vector128, GreaterThanAny, HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, IsNaN, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsNegative, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsPositive, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsPositiveInfinity, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsZero, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -174,9 +188,12 @@ HARDWARE_INTRINSIC(Vector128, LoadAligned, HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LoadUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Max, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, MaxNative, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Min, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, MinNative, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, MultiplyAddEstimate, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Narrow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Round, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -184,6 +201,7 @@ HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, true, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector128, Truncate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, WidenLower, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, WidenUpper, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, WithElement, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport) diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index 58c51a2a6bcdd..4513494d6dd02 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -80,6 +80,11 @@ HARDWARE_INTRINSIC(Vector128, GreaterThanAny, HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, IsNaN, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsNegative, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsPositive, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsPositiveInfinity, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsZero, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -90,9 +95,12 @@ HARDWARE_INTRINSIC(Vector128, LoadAligned, HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LoadUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Max, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, MaxNative, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Min, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, MinNative, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, MultiplyAddEstimate, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Narrow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Round, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -103,6 +111,7 @@ HARDWARE_INTRINSIC(Vector128, ToScalar, HARDWARE_INTRINSIC(Vector128, ToVector256, 16, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector256Unsafe, 16, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector512, 16, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Vector128, Truncate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, WidenLower, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, WidenUpper, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, WithElement, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) @@ -181,6 +190,11 @@ HARDWARE_INTRINSIC(Vector256, GreaterThanAny, HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqual, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, IsNaN, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsNegative, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsPositive, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsPositiveInfinity, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsZero, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, LessThan, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, LessThanAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, LessThanAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -191,9 +205,12 @@ HARDWARE_INTRINSIC(Vector256, LoadAligned, HARDWARE_INTRINSIC(Vector256, LoadAlignedNonTemporal, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, LoadUnsafe, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, Max, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, MaxNative, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, Min, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, MinNative, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, MultiplyAddEstimate, 32, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, Narrow, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Round, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, Shuffle, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector256, Sqrt, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) @@ -203,6 +220,7 @@ HARDWARE_INTRINSIC(Vector256, Sum, HARDWARE_INTRINSIC(Vector256, ToScalar, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, ToVector512, 32, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, ToVector512Unsafe, 32, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, Truncate, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, WidenLower, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, WidenUpper, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, WithElement, 32, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) @@ -283,6 +301,11 @@ HARDWARE_INTRINSIC(Vector512, GreaterThanAny, HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, IsNaN, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsNegative, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsPositive, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsPositiveInfinity, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsZero, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, LessThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, LessThanAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, LessThanAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -293,9 +316,12 @@ HARDWARE_INTRINSIC(Vector512, LoadAligned, HARDWARE_INTRINSIC(Vector512, LoadAlignedNonTemporal, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, LoadUnsafe, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, Max, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, MaxNative, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, Min, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, MinNative, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, MultiplyAddEstimate, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, Narrow, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Round, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, Shuffle, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector512, Sqrt, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, StoreAligned, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -303,6 +329,7 @@ HARDWARE_INTRINSIC(Vector512, StoreAlignedNonTemporal, HARDWARE_INTRINSIC(Vector512, StoreUnsafe, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, Sum, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ToScalar, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, Truncate, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, WidenLower, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, WidenUpper, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, WithElement, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index a09fb4950f506..64adeadcab50a 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -2795,6 +2795,72 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_IsNaN: + case NI_Vector256_IsNaN: + case NI_Vector512_IsNaN: + { + assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsNaNNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector128_IsNegative: + case NI_Vector256_IsNegative: + case NI_Vector512_IsNegative: + { + assert(sig->numArgs == 1); + + if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsNegativeNode(retType, op1, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_IsPositive: + case NI_Vector256_IsPositive: + case NI_Vector512_IsPositive: + { + assert(sig->numArgs == 1); + + if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsPositiveNode(retType, op1, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_IsPositiveInfinity: + case NI_Vector256_IsPositiveInfinity: + case NI_Vector512_IsPositiveInfinity: + { + assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsPositiveInfinityNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector128_IsZero: + case NI_Vector256_IsZero: + case NI_Vector512_IsZero: + { + assert(sig->numArgs == 1); + var_types simdType = getSIMDTypeForSize(simdSize); + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsZeroNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector128_LessThan: case NI_Vector256_LessThan: case NI_Vector512_LessThan: @@ -2991,6 +3057,28 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_MaxNative: + case NI_Vector256_MaxNative: + case NI_Vector512_MaxNative: + { + assert(sig->numArgs == 2); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || + compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + retNode = gtNewSimdMaxNativeNode(retType, op1, op2, simdBaseJitType, simdSize); + } + break; + } + case NI_Vector128_Min: case NI_Vector256_Min: case NI_Vector512_Min: @@ -3008,6 +3096,28 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_MinNative: + case NI_Vector256_MinNative: + case NI_Vector512_MinNative: + { + assert(sig->numArgs == 2); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || + compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + retNode = gtNewSimdMinNativeNode(retType, op1, op2, simdBaseJitType, simdSize); + } + break; + } + case NI_Vector128_op_Multiply: case NI_Vector256_op_Multiply: case NI_Vector512_op_Multiply: @@ -3066,7 +3176,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector512_MultiplyAddEstimate: { assert(sig->numArgs == 3); - assert(varTypeIsFloating(simdBaseType)); if (BlockNonDeterministicIntrinsics(mustExpand)) { @@ -3077,7 +3186,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); - if (compExactlyDependsOn(InstructionSet_FMA)) + if (varTypeIsFloating(simdBaseType) && compExactlyDependsOn(InstructionSet_FMA)) { retNode = gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); } @@ -3265,6 +3374,32 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_Round: + case NI_Vector256_Round: + case NI_Vector512_Round: + { + if (sig->numArgs != 1) + { + break; + } + + if (!varTypeIsFloating(simdBaseType)) + { + retNode = impSIMDPopStack(); + break; + } + + if ((simdSize < 32) && !compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + // Round is only supported for floating-point types on SSE4.1 or later + break; + } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdRoundNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector128_Shuffle: case NI_Vector256_Shuffle: case NI_Vector512_Shuffle: @@ -3496,6 +3631,29 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_Truncate: + case NI_Vector256_Truncate: + case NI_Vector512_Truncate: + { + assert(sig->numArgs == 1); + + if (!varTypeIsFloating(simdBaseType)) + { + retNode = impSIMDPopStack(); + break; + } + + if ((simdSize < 32) && !compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + // Truncate is only supported for floating-point types on SSE4.1 or later + break; + } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdTruncNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector256_GetLower: { assert(sig->numArgs == 1); diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index cfdca6e34677e..7c36076fa90c8 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -447,6 +447,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, switch (intrinsic) { case NI_VectorT_ConvertToInt32Native: + case NI_VectorT_MaxNative: + case NI_VectorT_MinNative: { if (BlockNonDeterministicIntrinsics(mustExpand)) { @@ -908,6 +910,31 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdFloorNode(retType, op1, simdBaseJitType, simdSize); } + case NI_VectorT_IsNaN: + { + return gtNewSimdIsNaNNode(retType, op1, simdBaseJitType, simdSize); + } + + case NI_VectorT_IsNegative: + { + return gtNewSimdIsNegativeNode(retType, op1, simdBaseJitType, simdSize); + } + + case NI_VectorT_IsPositive: + { + return gtNewSimdIsPositiveNode(retType, op1, simdBaseJitType, simdSize); + } + + case NI_VectorT_IsPositiveInfinity: + { + return gtNewSimdIsPositiveInfinityNode(retType, op1, simdBaseJitType, simdSize); + } + + case NI_VectorT_IsZero: + { + return gtNewSimdIsZeroNode(retType, op1, simdBaseJitType, simdSize); + } + case NI_VectorT_LoadUnsafe: { if (op1->OperIs(GT_CAST) && op1->gtGetOp1()->TypeIs(TYP_BYREF)) @@ -1343,11 +1370,21 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdMaxNode(retType, op1, op2, simdBaseJitType, simdSize); } + case NI_VectorT_MaxNative: + { + return gtNewSimdMaxNativeNode(retType, op1, op2, simdBaseJitType, simdSize); + } + case NI_VectorT_Min: { return gtNewSimdMinNode(retType, op1, op2, simdBaseJitType, simdSize); } + case NI_VectorT_MinNative: + { + return gtNewSimdMinNativeNode(retType, op1, op2, simdBaseJitType, simdSize); + } + case NI_VectorT_op_Multiply: { return gtNewSimdBinOpNode(GT_MUL, retType, op1, op2, simdBaseJitType, simdSize); diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index efb3107930b03..6bbea32494f31 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -82,6 +82,11 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, GreaterThanAny, SIMD_AS_HWINTRINSIC_ID(VectorT, GreaterThanOrEqual, 2, {NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, GreaterThanOrEqualAll, 2, {NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, GreaterThanOrEqualAny, 2, {NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsNaN, 1, {NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsNegative, 1, {NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsPositive, 1, {NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsPositiveInfinity, 1, {NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsZero, 1, {NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, LessThan, 2, {NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, LessThanAll, 2, {NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, LessThanAny, 2, {NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny}, SimdAsHWIntrinsicFlag::None) @@ -93,7 +98,9 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, LoadAlignedNonTemporal, SIMD_AS_HWINTRINSIC_ID(VectorT, LoadUnsafe, 1, {NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe}, SimdAsHWIntrinsicFlag::KeepBaseTypeFromRet) SIMD_AS_HWINTRINSIC_NM(VectorT, LoadUnsafeIndex, "LoadUnsafe", 2, {NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex}, SimdAsHWIntrinsicFlag::KeepBaseTypeFromRet) SIMD_AS_HWINTRINSIC_ID(VectorT, Max, 2, {NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, MaxNative, 2, {NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Min, 2, {NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, MinNative, 2, {NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_MultiplyAddEstimate, NI_VectorT_MultiplyAddEstimate}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Narrow, 2, {NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow}, SimdAsHWIntrinsicFlag::KeepBaseTypeFromRet) SIMD_AS_HWINTRINSIC_ID(VectorT, op_Addition, 2, {NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 4074204e29ea4..1d769f27e4f97 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -82,6 +82,11 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, GreaterThanAny, SIMD_AS_HWINTRINSIC_ID(VectorT, GreaterThanOrEqual, 2, {NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual, NI_VectorT_GreaterThanOrEqual}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, GreaterThanOrEqualAll, 2, {NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll, NI_VectorT_GreaterThanOrEqualAll}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, GreaterThanOrEqualAny, 2, {NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny, NI_VectorT_GreaterThanOrEqualAny}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsNaN, 1, {NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN, NI_VectorT_IsNaN}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsNegative, 1, {NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative, NI_VectorT_IsNegative}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsPositive, 1, {NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive, NI_VectorT_IsPositive}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsPositiveInfinity, 1, {NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity, NI_VectorT_IsPositiveInfinity}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, IsZero, 1, {NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero, NI_VectorT_IsZero}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, LessThan, 2, {NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan, NI_VectorT_LessThan}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, LessThanAll, 2, {NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll, NI_VectorT_LessThanAll}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, LessThanAny, 2, {NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny, NI_VectorT_LessThanAny}, SimdAsHWIntrinsicFlag::None) @@ -93,7 +98,9 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, LoadAlignedNonTemporal, SIMD_AS_HWINTRINSIC_ID(VectorT, LoadUnsafe, 1, {NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe, NI_VectorT_LoadUnsafe}, SimdAsHWIntrinsicFlag::KeepBaseTypeFromRet) SIMD_AS_HWINTRINSIC_NM(VectorT, LoadUnsafeIndex, "LoadUnsafe", 2, {NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex, NI_VectorT_LoadUnsafeIndex}, SimdAsHWIntrinsicFlag::KeepBaseTypeFromRet) SIMD_AS_HWINTRINSIC_ID(VectorT, Max, 2, {NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, MaxNative, 2, {NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative, NI_VectorT_MaxNative}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Min, 2, {NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, MinNative, 2, {NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative, NI_VectorT_MinNative}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_MultiplyAddEstimate, NI_VectorT_MultiplyAddEstimate}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Narrow, 2, {NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow}, SimdAsHWIntrinsicFlag::KeepBaseTypeFromRet) SIMD_AS_HWINTRINSIC_ID(VectorT, op_Addition, 2, {NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition, NI_VectorT_op_Addition}, SimdAsHWIntrinsicFlag::None) @@ -106,7 +113,7 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, op_Explicit, SIMD_AS_HWINTRINSIC_ID(VectorT, op_Inequality, 2, {NI_VectorT_op_Inequality, NI_VectorT_op_Inequality, NI_VectorT_op_Inequality, NI_VectorT_op_Inequality, NI_VectorT_op_Inequality, NI_VectorT_op_Inequality, NI_VectorT_op_Inequality, NI_VectorT_op_Inequality, NI_VectorT_op_Inequality, NI_VectorT_op_Inequality}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, op_LeftShift, 2, {NI_Illegal, NI_Illegal, NI_VectorT_op_LeftShift, NI_VectorT_op_LeftShift, NI_VectorT_op_LeftShift, NI_VectorT_op_LeftShift, NI_VectorT_op_LeftShift, NI_VectorT_op_LeftShift, NI_VectorT_op_LeftShift, NI_VectorT_op_LeftShift}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_VectorT_op_Multiply, NI_VectorT_op_Multiply, NI_VectorT_op_Multiply, NI_VectorT_op_Multiply, NI_Illegal, NI_Illegal, NI_VectorT_op_Multiply, NI_VectorT_op_Multiply}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(VectorT, op_OnesComplement, 2, {NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, op_OnesComplement, 1, {NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement, NI_VectorT_op_OnesComplement}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, op_RightShift, 2, {NI_Illegal, NI_Illegal, NI_VectorT_op_RightShift, NI_VectorT_op_RightShift, NI_VectorT_op_RightShift, NI_VectorT_op_RightShift, NI_VectorT_op_RightShift, NI_VectorT_op_RightShift, NI_VectorT_op_RightShift, NI_VectorT_op_RightShift}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, op_Subtraction, 2, {NI_VectorT_op_Subtraction, NI_VectorT_op_Subtraction, NI_VectorT_op_Subtraction, NI_VectorT_op_Subtraction, NI_VectorT_op_Subtraction, NI_VectorT_op_Subtraction, NI_VectorT_op_Subtraction, NI_VectorT_op_Subtraction, NI_VectorT_op_Subtraction, NI_VectorT_op_Subtraction}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, op_UnaryNegation, 1, {NI_VectorT_op_UnaryNegation, NI_VectorT_op_UnaryNegation, NI_VectorT_op_UnaryNegation, NI_VectorT_op_UnaryNegation, NI_VectorT_op_UnaryNegation, NI_VectorT_op_UnaryNegation, NI_VectorT_op_UnaryNegation, NI_VectorT_op_UnaryNegation, NI_VectorT_op_UnaryNegation, NI_VectorT_op_UnaryNegation}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/Common/tests/System/GenericMathTestMemberData.cs b/src/libraries/Common/tests/System/GenericMathTestMemberData.cs new file mode 100644 index 0000000000000..2e40a0940fc5a --- /dev/null +++ b/src/libraries/Common/tests/System/GenericMathTestMemberData.cs @@ -0,0 +1,1687 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Xunit; + +namespace System.Tests +{ + internal static class GenericMathTestMemberData + { + // binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this + // is slightly too accurate when writing tests meant to run against libm implementations + // for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. + // + // The tests themselves will take CrossPlatformMachineEpsilon and adjust it according to the expected result + // so that the delta used for comparison will compare the most significant digits and ignore + // any digits that are outside the double precision range (15-17 digits). + // + // For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use + // CrossPlatformMachineEpsilon for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx + // will use CrossPlatformMachineEpsilon / 10 and expected result in the format of x.xxxxxxxxxxxxxxxx will + // use CrossPlatformMachineEpsilon * 10. + internal const double DoubleCrossPlatformMachineEpsilon = 8.8817841970012523e-16; + + // binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this + // is slightly too accurate when writing tests meant to run against libm implementations + // for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. + // + // The tests themselves will take CrossPlatformMachineEpsilon and adjust it according to the expected result + // so that the delta used for comparison will compare the most significant digits and ignore + // any digits that are outside the single precision range (6-9 digits). + // + // For example, a test with an expect result in the format of 0.xxxxxxxxx will use + // CrossPlatformMachineEpsilon for the variance, while an expected result in the format of 0.0xxxxxxxxx + // will use CrossPlatformMachineEpsilon / 10 and expected result in the format of x.xxxxxx will + // use CrossPlatformMachineEpsilon * 10. + private const float SingleCrossPlatformMachineEpsilon = 4.76837158e-07f; + + internal const double MinNormalDouble = 2.2250738585072014E-308; + internal const float MinNormalSingle = 1.17549435E-38f; + + internal const double MaxSubnormalDouble = 2.2250738585072009E-308; + internal const float MaxSubnormalSingle = 1.17549421E-38f; + + public static IEnumerable ClampDouble + { + get + { + yield return new object[] { double.NegativeInfinity, 1.0f, 63.0f, 1.0f }; + yield return new object[] { double.MinValue, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -1.0f, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -MinNormalDouble, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -MaxSubnormalDouble, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -double.Epsilon, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -0.0f, 1.0f, 63.0f, 1.0f }; + yield return new object[] { double.NaN, 1.0f, 63.0f, double.NaN }; + yield return new object[] { 0.0f, 1.0f, 63.0f, 1.0f }; + yield return new object[] { double.Epsilon, 1.0f, 63.0f, 1.0f }; + yield return new object[] { MaxSubnormalDouble, 1.0f, 63.0f, 1.0f }; + yield return new object[] { MinNormalDouble, 1.0f, 63.0f, 1.0f }; + yield return new object[] { 1.0f, 1.0f, 63.0f, 1.0f }; + yield return new object[] { double.MaxValue, 1.0f, 63.0f, 63.0f }; + yield return new object[] { double.PositiveInfinity, 1.0f, 63.0f, 63.0f }; + } + } + + public static IEnumerable ClampSingle + { + get + { + yield return new object[] { float.NegativeInfinity, 1.0f, 63.0f, 1.0f }; + yield return new object[] { float.MinValue, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -1.0f, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -MinNormalSingle, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -MaxSubnormalSingle, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -float.Epsilon, 1.0f, 63.0f, 1.0f }; + yield return new object[] { -0.0f, 1.0f, 63.0f, 1.0f }; + yield return new object[] { float.NaN, 1.0f, 63.0f, float.NaN }; + yield return new object[] { 0.0f, 1.0f, 63.0f, 1.0f }; + yield return new object[] { float.Epsilon, 1.0f, 63.0f, 1.0f }; + yield return new object[] { MaxSubnormalSingle, 1.0f, 63.0f, 1.0f }; + yield return new object[] { MinNormalSingle, 1.0f, 63.0f, 1.0f }; + yield return new object[] { 1.0f, 1.0f, 63.0f, 1.0f }; + yield return new object[] { float.MaxValue, 1.0f, 63.0f, 63.0f }; + yield return new object[] { float.PositiveInfinity, 1.0f, 63.0f, 63.0f }; + } + } + + public static IEnumerable CopySignDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { double.NegativeInfinity, -3.1415926535897932, double.NegativeInfinity }; + yield return new object[] { double.NegativeInfinity, -0.0, double.NegativeInfinity }; + yield return new object[] { double.NegativeInfinity, double.NaN, double.NegativeInfinity }; + yield return new object[] { double.NegativeInfinity, 0.0, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, 3.1415926535897932, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { -3.1415926535897932, double.NegativeInfinity, -3.1415926535897932 }; + yield return new object[] { -3.1415926535897932, -3.1415926535897932, -3.1415926535897932 }; + yield return new object[] { -3.1415926535897932, -0.0, -3.1415926535897932 }; + yield return new object[] { -3.1415926535897932, double.NaN, -3.1415926535897932 }; + yield return new object[] { -3.1415926535897932, 0.0, 3.1415926535897932 }; + yield return new object[] { -3.1415926535897932, 3.1415926535897932, 3.1415926535897932 }; + yield return new object[] { -3.1415926535897932, double.PositiveInfinity, 3.1415926535897932 }; + yield return new object[] { -0.0, double.NegativeInfinity, -0.0 }; + yield return new object[] { -0.0, -3.1415926535897932, -0.0 }; + yield return new object[] { -0.0, -0.0, -0.0 }; + yield return new object[] { -0.0, double.NaN, -0.0 }; + yield return new object[] { -0.0, 0.0, 0.0 }; + yield return new object[] { -0.0, 3.1415926535897932, 0.0 }; + yield return new object[] { -0.0, double.PositiveInfinity, 0.0 }; + yield return new object[] { double.NaN, double.NegativeInfinity, double.NaN }; + yield return new object[] { double.NaN, -3.1415926535897932, double.NaN }; + yield return new object[] { double.NaN, -0.0, double.NaN }; + yield return new object[] { double.NaN, double.NaN, double.NaN }; + yield return new object[] { double.NaN, 0.0, double.NaN }; + yield return new object[] { double.NaN, 3.1415926535897932, double.NaN }; + yield return new object[] { double.NaN, double.PositiveInfinity, double.NaN }; + yield return new object[] { 0.0, double.NegativeInfinity, -0.0 }; + yield return new object[] { 0.0, -3.1415926535897932, -0.0 }; + yield return new object[] { 0.0, -0.0, -0.0 }; + yield return new object[] { 0.0, double.NaN, -0.0 }; + yield return new object[] { 0.0, 0.0, 0.0 }; + yield return new object[] { 0.0, 3.1415926535897932, 0.0 }; + yield return new object[] { 0.0, double.PositiveInfinity, 0.0 }; + yield return new object[] { 3.1415926535897932, double.NegativeInfinity, -3.1415926535897932 }; + yield return new object[] { 3.1415926535897932, -3.1415926535897932, -3.1415926535897932 }; + yield return new object[] { 3.1415926535897932, -0.0, -3.1415926535897932 }; + yield return new object[] { 3.1415926535897932, double.NaN, -3.1415926535897932 }; + yield return new object[] { 3.1415926535897932, 0.0, 3.1415926535897932 }; + yield return new object[] { 3.1415926535897932, 3.1415926535897932, 3.1415926535897932 }; + yield return new object[] { 3.1415926535897932, double.PositiveInfinity, 3.1415926535897932 }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, -3.1415926535897932, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, -0.0, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, double.NaN, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, 0.0, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, 3.1415926535897932, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity }; + } + } + + public static IEnumerable CopySignSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { float.NegativeInfinity, -3.14159265f, float.NegativeInfinity }; + yield return new object[] { float.NegativeInfinity, -0.0f, float.NegativeInfinity }; + yield return new object[] { float.NegativeInfinity, float.NaN, float.NegativeInfinity }; + yield return new object[] { float.NegativeInfinity, 0.0f, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, 3.14159265f, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { -3.14159265f, float.NegativeInfinity, -3.14159265f }; + yield return new object[] { -3.14159265f, -3.14159265f, -3.14159265f }; + yield return new object[] { -3.14159265f, -0.0f, -3.14159265f }; + yield return new object[] { -3.14159265f, float.NaN, -3.14159265f }; + yield return new object[] { -3.14159265f, 0.0f, 3.14159265f }; + yield return new object[] { -3.14159265f, 3.14159265f, 3.14159265f }; + yield return new object[] { -3.14159265f, float.PositiveInfinity, 3.14159265f }; + yield return new object[] { -0.0f, float.NegativeInfinity, -0.0f }; + yield return new object[] { -0.0f, -3.14159265f, -0.0f }; + yield return new object[] { -0.0f, -0.0f, -0.0f }; + yield return new object[] { -0.0f, float.NaN, -0.0f }; + yield return new object[] { -0.0f, 0.0f, 0.0f }; + yield return new object[] { -0.0f, 3.14159265f, 0.0f }; + yield return new object[] { -0.0f, float.PositiveInfinity, 0.0f }; + yield return new object[] { float.NaN, float.NegativeInfinity, float.NaN }; + yield return new object[] { float.NaN, -3.14159265f, float.NaN }; + yield return new object[] { float.NaN, -0.0f, float.NaN }; + yield return new object[] { float.NaN, float.NaN, float.NaN }; + yield return new object[] { float.NaN, 0.0f, float.NaN }; + yield return new object[] { float.NaN, 3.14159265f, float.NaN }; + yield return new object[] { float.NaN, float.PositiveInfinity, float.NaN }; + yield return new object[] { 0.0f, float.NegativeInfinity, -0.0f }; + yield return new object[] { 0.0f, -3.14159265f, -0.0f }; + yield return new object[] { 0.0f, -0.0f, -0.0f }; + yield return new object[] { 0.0f, float.NaN, -0.0f }; + yield return new object[] { 0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, 3.14159265f, 0.0f }; + yield return new object[] { 0.0f, float.PositiveInfinity, 0.0f }; + yield return new object[] { 3.14159265f, float.NegativeInfinity, -3.14159265f }; + yield return new object[] { 3.14159265f, -3.14159265f, -3.14159265f }; + yield return new object[] { 3.14159265f, -0.0f, -3.14159265f }; + yield return new object[] { 3.14159265f, float.NaN, -3.14159265f }; + yield return new object[] { 3.14159265f, 0.0f, 3.14159265f }; + yield return new object[] { 3.14159265f, 3.14159265f, 3.14159265f }; + yield return new object[] { 3.14159265f, float.PositiveInfinity, 3.14159265f }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, -3.14159265f, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, -0.0f, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, float.NaN, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, 0.0f, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, 3.14159265f, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity }; + } + } + + public static IEnumerable DegreesToRadiansDouble + { + get + { + yield return new object[] { double.NaN, double.NaN, 0.0 }; + yield return new object[] { 0.0, 0.0, 0.0 }; + yield return new object[] { 0.31830988618379067, 0.005555555555555556, DoubleCrossPlatformMachineEpsilon }; // value: (1 / pi) + yield return new object[] { 0.43429448190325183, 0.007579868632454674, DoubleCrossPlatformMachineEpsilon }; // value: (log10(e)) + yield return new object[] { 0.5, 0.008726646259971648, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.63661977236758134, 0.011111111111111112, DoubleCrossPlatformMachineEpsilon }; // value: (2 / pi) + yield return new object[] { 0.69314718055994531, 0.01209770050168668, DoubleCrossPlatformMachineEpsilon }; // value: (ln(2)) + yield return new object[] { 0.70710678118654752, 0.012341341494884351, DoubleCrossPlatformMachineEpsilon }; // value: (1 / sqrt(2)) + yield return new object[] { 0.78539816339744831, 0.013707783890401885, DoubleCrossPlatformMachineEpsilon }; // value: (pi / 4) + yield return new object[] { 1.0, 0.017453292519943295, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 1.1283791670955126, 0.019693931676727953, DoubleCrossPlatformMachineEpsilon }; // value: (2 / sqrt(pi)) + yield return new object[] { 1.4142135623730950, 0.024682682989768702, DoubleCrossPlatformMachineEpsilon }; // value: (sqrt(2)) + yield return new object[] { 1.4426950408889634, 0.02517977856570663, DoubleCrossPlatformMachineEpsilon }; // value: (log2(e)) + yield return new object[] { 1.5, 0.02617993877991494, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 1.5707963267948966, 0.02741556778080377, DoubleCrossPlatformMachineEpsilon }; // value: (pi / 2) + yield return new object[] { 2.0, 0.03490658503988659, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 2.3025850929940457, 0.040187691180085916, DoubleCrossPlatformMachineEpsilon }; // value: (ln(10)) + yield return new object[] { 2.5, 0.04363323129985824, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 2.7182818284590452, 0.047442967903742035, DoubleCrossPlatformMachineEpsilon }; // value: (e) + yield return new object[] { 3.0, 0.05235987755982988, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 3.1415926535897932, 0.05483113556160754, DoubleCrossPlatformMachineEpsilon }; // value: (pi) + yield return new object[] { 3.5, 0.061086523819801536, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable DegreesToRadiansSingle + { + get + { + yield return new object[] { float.NaN, float.NaN, 0.0f }; + yield return new object[] { 0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.318309886f, 0.0055555557f, SingleCrossPlatformMachineEpsilon }; // value: (1 / pi) + yield return new object[] { 0.434294482f, 0.007579869f, SingleCrossPlatformMachineEpsilon }; // value: (log10(e)) + yield return new object[] { 0.5f, 0.008726646f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.636619772f, 0.011111111f, SingleCrossPlatformMachineEpsilon }; // value: (2 / pi) + yield return new object[] { 0.693147181f, 0.0120977005f, SingleCrossPlatformMachineEpsilon }; // value: (ln(2)) + yield return new object[] { 0.707106781f, 0.012341342f, SingleCrossPlatformMachineEpsilon }; // value: (1 / sqrt(2)) + yield return new object[] { 0.785398163f, 0.013707785f, SingleCrossPlatformMachineEpsilon }; // value: (pi / 4) + yield return new object[] { 1.0f, 0.017453292f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 1.12837917f, 0.019693933f, SingleCrossPlatformMachineEpsilon }; // value: (2 / sqrt(pi)) + yield return new object[] { 1.41421356f, 0.024682684f, SingleCrossPlatformMachineEpsilon }; // value: (sqrt(2)) + yield return new object[] { 1.44269504f, 0.025179777f, SingleCrossPlatformMachineEpsilon }; // value: (log2(e)) + yield return new object[] { 1.5f, 0.02617994f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 1.57079633f, 0.02741557f, SingleCrossPlatformMachineEpsilon }; // value: (pi / 2) + yield return new object[] { 2.0f, 0.034906585f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 2.30258509f, 0.040187694f, SingleCrossPlatformMachineEpsilon }; // value: (ln(10)) + yield return new object[] { 2.5f, 0.043633234f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 2.71828183f, 0.047442965f, SingleCrossPlatformMachineEpsilon }; // value: (e) + yield return new object[] { 3.0f, 0.05235988f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 3.14159265f, 0.05483114f, SingleCrossPlatformMachineEpsilon }; // value: (pi) + yield return new object[] { 3.5f, 0.061086528f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; + } + } + + public static IEnumerable ExpDouble + { + get + { + yield return new object[] { double.NegativeInfinity, 0.0, 0.0 }; + yield return new object[] { -3.1415926535897932, 0.043213918263772250, DoubleCrossPlatformMachineEpsilon / 10 }; // value: -(pi) + yield return new object[] { -2.7182818284590452, 0.065988035845312537, DoubleCrossPlatformMachineEpsilon / 10 }; // value: -(e) + yield return new object[] { -2.3025850929940457, 0.1, DoubleCrossPlatformMachineEpsilon }; // value: -(ln(10)) + yield return new object[] { -1.5707963267948966, 0.20787957635076191, DoubleCrossPlatformMachineEpsilon }; // value: -(pi / 2) + yield return new object[] { -1.4426950408889634, 0.23629008834452270, DoubleCrossPlatformMachineEpsilon }; // value: -(log2(e)) + yield return new object[] { -1.4142135623730950, 0.24311673443421421, DoubleCrossPlatformMachineEpsilon }; // value: -(sqrt(2)) + yield return new object[] { -1.1283791670955126, 0.32355726390307110, DoubleCrossPlatformMachineEpsilon }; // value: -(2 / sqrt(pi)) + yield return new object[] { -1.0, 0.36787944117144232, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { -0.78539816339744831, 0.45593812776599624, DoubleCrossPlatformMachineEpsilon }; // value: -(pi / 4) + yield return new object[] { -0.70710678118654752, 0.49306869139523979, DoubleCrossPlatformMachineEpsilon }; // value: -(1 / sqrt(2)) + yield return new object[] { -0.69314718055994531, 0.5, 0.0 }; // value: -(ln(2)) + yield return new object[] { -0.63661977236758134, 0.52907780826773535, DoubleCrossPlatformMachineEpsilon }; // value: -(2 / pi) + yield return new object[] { -0.43429448190325183, 0.64772148514180065, DoubleCrossPlatformMachineEpsilon }; // value: -(log10(e)) + yield return new object[] { -0.31830988618379067, 0.72737734929521647, DoubleCrossPlatformMachineEpsilon }; // value: -(1 / pi) + yield return new object[] { -0.0, 1.0, 0.0 }; + yield return new object[] { double.NaN, double.NaN, 0.0 }; + yield return new object[] { 0.0, 1.0, 0.0 }; + yield return new object[] { 0.31830988618379067, 1.3748022274393586, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi) + yield return new object[] { 0.43429448190325183, 1.5438734439711811, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e)) + yield return new object[] { 0.63661977236758134, 1.8900811645722220, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (2 / pi) + yield return new object[] { 0.69314718055994531, 2.0, 0.0 }; // value: (ln(2)) + yield return new object[] { 0.70710678118654752, 2.0281149816474725, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (1 / sqrt(2)) + yield return new object[] { 0.78539816339744831, 2.1932800507380155, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 4) + yield return new object[] { 1.0, 2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 1.1283791670955126, 3.0906430223107976, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (2 / sqrt(pi)) + yield return new object[] { 1.4142135623730950, 4.1132503787829275, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (sqrt(2)) + yield return new object[] { 1.4426950408889634, 4.2320861065570819, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (log2(e)) + yield return new object[] { 1.5707963267948966, 4.8104773809653517, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 2) + yield return new object[] { 2.3025850929940457, 10.0, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (ln(10)) + yield return new object[] { 2.7182818284590452, 15.154262241479264, DoubleCrossPlatformMachineEpsilon * 100 }; // value: (e) + yield return new object[] { 3.1415926535897932, 23.140692632779269, DoubleCrossPlatformMachineEpsilon * 100 }; // value: (pi) + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable ExpSingle + { + get + { + yield return new object[] { float.NegativeInfinity, 0.0f, 0.0f }; + yield return new object[] { -3.14159265f, 0.0432139183f, SingleCrossPlatformMachineEpsilon / 10 }; // value: -(pi) + yield return new object[] { -2.71828183f, 0.0659880358f, SingleCrossPlatformMachineEpsilon / 10 }; // value: -(e) + yield return new object[] { -2.30258509f, 0.1f, SingleCrossPlatformMachineEpsilon }; // value: -(ln(10)) + yield return new object[] { -1.57079633f, 0.207879576f, SingleCrossPlatformMachineEpsilon }; // value: -(pi / 2) + yield return new object[] { -1.44269504f, 0.236290088f, SingleCrossPlatformMachineEpsilon }; // value: -(log2(e)) + yield return new object[] { -1.41421356f, 0.243116734f, SingleCrossPlatformMachineEpsilon }; // value: -(sqrt(2)) + yield return new object[] { -1.12837917f, 0.323557264f, SingleCrossPlatformMachineEpsilon }; // value: -(2 / sqrt(pi)) + yield return new object[] { -1.0f, 0.367879441f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { -0.785398163f, 0.455938128f, SingleCrossPlatformMachineEpsilon }; // value: -(pi / 4) + yield return new object[] { -0.707106781f, 0.493068691f, SingleCrossPlatformMachineEpsilon }; // value: -(1 / sqrt(2)) + yield return new object[] { -0.693147181f, 0.5f, SingleCrossPlatformMachineEpsilon }; // value: -(ln(2)) + yield return new object[] { -0.636619772f, 0.529077808f, SingleCrossPlatformMachineEpsilon }; // value: -(2 / pi) + yield return new object[] { -0.434294482f, 0.647721485f, SingleCrossPlatformMachineEpsilon }; // value: -(log10(e)) + yield return new object[] { -0.318309886f, 0.727377349f, SingleCrossPlatformMachineEpsilon }; // value: -(1 / pi) + yield return new object[] { -0.0f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; + yield return new object[] { float.NaN, float.NaN, 0.0f }; + yield return new object[] { 0.0f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; + yield return new object[] { 0.318309886f, 1.37480223f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi) + yield return new object[] { 0.434294482f, 1.54387344f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e)) + yield return new object[] { 0.636619772f, 1.89008116f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (2 / pi) + yield return new object[] { 0.693147181f, 2.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (ln(2)) + yield return new object[] { 0.707106781f, 2.02811498f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (1 / sqrt(2)) + yield return new object[] { 0.785398163f, 2.19328005f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 4) + yield return new object[] { 1.0f, 2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 1.12837917f, 3.09064302f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (2 / sqrt(pi)) + yield return new object[] { 1.41421356f, 4.11325038f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (sqrt(2)) + yield return new object[] { 1.44269504f, 4.23208611f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (log2(e)) + yield return new object[] { 1.57079633f, 4.81047738f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 2) + yield return new object[] { 2.30258509f, 10.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (ln(10)) + yield return new object[] { 2.71828183f, 15.1542622f, SingleCrossPlatformMachineEpsilon * 100 }; // value: (e) + yield return new object[] { 3.14159265f, 23.1406926f, SingleCrossPlatformMachineEpsilon * 100 }; // value: (pi) + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; + } + } + + public static IEnumerable FusedMultiplyAddDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity, double.NaN }; + yield return new object[] { double.NegativeInfinity, -0.0, double.NegativeInfinity, double.NaN }; + yield return new object[] { double.NegativeInfinity, -0.0, -3.1415926535897932, double.NaN }; + yield return new object[] { double.NegativeInfinity, -0.0, -0.0, double.NaN }; + yield return new object[] { double.NegativeInfinity, -0.0, double.NaN, double.NaN }; + yield return new object[] { double.NegativeInfinity, -0.0, 0.0, double.NaN }; + yield return new object[] { double.NegativeInfinity, -0.0, 3.1415926535897932, double.NaN }; + yield return new object[] { double.NegativeInfinity, -0.0, double.PositiveInfinity, double.NaN }; + yield return new object[] { double.NegativeInfinity, 0.0, double.NegativeInfinity, double.NaN }; + yield return new object[] { double.NegativeInfinity, 0.0, -3.1415926535897932, double.NaN }; + yield return new object[] { double.NegativeInfinity, 0.0, -0.0, double.NaN }; + yield return new object[] { double.NegativeInfinity, 0.0, double.NaN, double.NaN }; + yield return new object[] { double.NegativeInfinity, 0.0, 0.0, double.NaN }; + yield return new object[] { double.NegativeInfinity, 0.0, 3.1415926535897932, double.NaN }; + yield return new object[] { double.NegativeInfinity, 0.0, double.PositiveInfinity, double.NaN }; + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity, double.NaN }; + yield return new object[] { -1e308, 2.0, 1e308, -1e308 }; + yield return new object[] { -1e308, 2.0, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { -5, 4, -3, -23 }; + yield return new object[] { -0.0, double.NegativeInfinity, double.NegativeInfinity, double.NaN }; + yield return new object[] { -0.0, double.NegativeInfinity, -3.1415926535897932, double.NaN }; + yield return new object[] { -0.0, double.NegativeInfinity, -0.0, double.NaN }; + yield return new object[] { -0.0, double.NegativeInfinity, double.NaN, double.NaN }; + yield return new object[] { -0.0, double.NegativeInfinity, 0.0, double.NaN }; + yield return new object[] { -0.0, double.NegativeInfinity, 3.1415926535897932, double.NaN }; + yield return new object[] { -0.0, double.NegativeInfinity, double.PositiveInfinity, double.NaN }; + yield return new object[] { -0.0, double.PositiveInfinity, double.NegativeInfinity, double.NaN }; + yield return new object[] { -0.0, double.PositiveInfinity, -3.1415926535897932, double.NaN }; + yield return new object[] { -0.0, double.PositiveInfinity, -0.0, double.NaN }; + yield return new object[] { -0.0, double.PositiveInfinity, double.NaN, double.NaN }; + yield return new object[] { -0.0, double.PositiveInfinity, 0.0, double.NaN }; + yield return new object[] { -0.0, double.PositiveInfinity, 3.1415926535897932, double.NaN }; + yield return new object[] { -0.0, double.PositiveInfinity, double.PositiveInfinity, double.NaN }; + yield return new object[] { 0.0, double.NegativeInfinity, double.NegativeInfinity, double.NaN }; + yield return new object[] { 0.0, double.NegativeInfinity, -3.1415926535897932, double.NaN }; + yield return new object[] { 0.0, double.NegativeInfinity, -0.0, double.NaN }; + yield return new object[] { 0.0, double.NegativeInfinity, double.NaN, double.NaN }; + yield return new object[] { 0.0, double.NegativeInfinity, 0.0, double.NaN }; + yield return new object[] { 0.0, double.NegativeInfinity, 3.1415926535897932, double.NaN }; + yield return new object[] { 0.0, double.NegativeInfinity, double.PositiveInfinity, double.NaN }; + yield return new object[] { 0.0, double.PositiveInfinity, double.NegativeInfinity, double.NaN }; + yield return new object[] { 0.0, double.PositiveInfinity, -3.1415926535897932, double.NaN }; + yield return new object[] { 0.0, double.PositiveInfinity, -0.0, double.NaN }; + yield return new object[] { 0.0, double.PositiveInfinity, double.NaN, double.NaN }; + yield return new object[] { 0.0, double.PositiveInfinity, 0.0, double.NaN }; + yield return new object[] { 0.0, double.PositiveInfinity, 3.1415926535897932, double.NaN }; + yield return new object[] { 0.0, double.PositiveInfinity, double.PositiveInfinity, double.NaN }; + yield return new object[] { 5, 4, 3, 23 }; + yield return new object[] { 1e308, 2.0, -1e308, 1e308 }; + yield return new object[] { 1e308, 2.0, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity, double.NaN }; + yield return new object[] { double.PositiveInfinity, -0.0, double.NegativeInfinity, double.NaN }; + yield return new object[] { double.PositiveInfinity, -0.0, -3.1415926535897932, double.NaN }; + yield return new object[] { double.PositiveInfinity, -0.0, -0.0, double.NaN }; + yield return new object[] { double.PositiveInfinity, -0.0, double.NaN, double.NaN }; + yield return new object[] { double.PositiveInfinity, -0.0, 0.0, double.NaN }; + yield return new object[] { double.PositiveInfinity, -0.0, 3.1415926535897932, double.NaN }; + yield return new object[] { double.PositiveInfinity, -0.0, double.PositiveInfinity, double.NaN }; + yield return new object[] { double.PositiveInfinity, 0.0, double.NegativeInfinity, double.NaN }; + yield return new object[] { double.PositiveInfinity, 0.0, -3.1415926535897932, double.NaN }; + yield return new object[] { double.PositiveInfinity, 0.0, -0.0, double.NaN }; + yield return new object[] { double.PositiveInfinity, 0.0, double.NaN, double.NaN }; + yield return new object[] { double.PositiveInfinity, 0.0, 0.0, double.NaN }; + yield return new object[] { double.PositiveInfinity, 0.0, 3.1415926535897932, double.NaN }; + yield return new object[] { double.PositiveInfinity, 0.0, double.PositiveInfinity, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, double.NegativeInfinity, double.NaN }; + } + } + + public static IEnumerable FusedMultiplyAddSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity, float.NaN }; + yield return new object[] { float.NegativeInfinity, -0.0f, float.NegativeInfinity, float.NaN }; + yield return new object[] { float.NegativeInfinity, -0.0f, -3.14159265f, float.NaN }; + yield return new object[] { float.NegativeInfinity, -0.0f, -0.0f, float.NaN }; + yield return new object[] { float.NegativeInfinity, -0.0f, float.NaN, float.NaN }; + yield return new object[] { float.NegativeInfinity, -0.0f, 0.0f, float.NaN }; + yield return new object[] { float.NegativeInfinity, -0.0f, 3.14159265f, float.NaN }; + yield return new object[] { float.NegativeInfinity, -0.0f, float.PositiveInfinity, float.NaN }; + yield return new object[] { float.NegativeInfinity, 0.0f, float.NegativeInfinity, float.NaN }; + yield return new object[] { float.NegativeInfinity, 0.0f, -3.14159265f, float.NaN }; + yield return new object[] { float.NegativeInfinity, 0.0f, -0.0f, float.NaN }; + yield return new object[] { float.NegativeInfinity, 0.0f, float.NaN, float.NaN }; + yield return new object[] { float.NegativeInfinity, 0.0f, 0.0f, float.NaN }; + yield return new object[] { float.NegativeInfinity, 0.0f, 3.14159265f, float.NaN }; + yield return new object[] { float.NegativeInfinity, 0.0f, float.PositiveInfinity, float.NaN }; + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity, float.NaN }; + yield return new object[] { -1e38f, 2.0f, 1e38f, -1e38f }; + yield return new object[] { -1e38f, 2.0f, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { -5, 4, -3, -23 }; + yield return new object[] { -0.0f, float.NegativeInfinity, float.NegativeInfinity, float.NaN }; + yield return new object[] { -0.0f, float.NegativeInfinity, -3.14159265f, float.NaN }; + yield return new object[] { -0.0f, float.NegativeInfinity, -0.0f, float.NaN }; + yield return new object[] { -0.0f, float.NegativeInfinity, float.NaN, float.NaN }; + yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f, float.NaN }; + yield return new object[] { -0.0f, float.NegativeInfinity, 3.14159265f, float.NaN }; + yield return new object[] { -0.0f, float.NegativeInfinity, float.PositiveInfinity, float.NaN }; + yield return new object[] { -0.0f, float.PositiveInfinity, float.NegativeInfinity, float.NaN }; + yield return new object[] { -0.0f, float.PositiveInfinity, -3.14159265f, float.NaN }; + yield return new object[] { -0.0f, float.PositiveInfinity, -0.0f, float.NaN }; + yield return new object[] { -0.0f, float.PositiveInfinity, float.NaN, float.NaN }; + yield return new object[] { -0.0f, float.PositiveInfinity, 0.0f, float.NaN }; + yield return new object[] { -0.0f, float.PositiveInfinity, 3.14159265f, float.NaN }; + yield return new object[] { -0.0f, float.PositiveInfinity, float.PositiveInfinity, float.NaN }; + yield return new object[] { 0.0f, float.NegativeInfinity, float.NegativeInfinity, float.NaN }; + yield return new object[] { 0.0f, float.NegativeInfinity, -3.14159265f, float.NaN }; + yield return new object[] { 0.0f, float.NegativeInfinity, -0.0f, float.NaN }; + yield return new object[] { 0.0f, float.NegativeInfinity, float.NaN, float.NaN }; + yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f, float.NaN }; + yield return new object[] { 0.0f, float.NegativeInfinity, 3.14159265f, float.NaN }; + yield return new object[] { 0.0f, float.NegativeInfinity, float.PositiveInfinity, float.NaN }; + yield return new object[] { 0.0f, float.PositiveInfinity, float.NegativeInfinity, float.NaN }; + yield return new object[] { 0.0f, float.PositiveInfinity, -3.14159265f, float.NaN }; + yield return new object[] { 0.0f, float.PositiveInfinity, -0.0f, float.NaN }; + yield return new object[] { 0.0f, float.PositiveInfinity, float.NaN, float.NaN }; + yield return new object[] { 0.0f, float.PositiveInfinity, 0.0f, float.NaN }; + yield return new object[] { 0.0f, float.PositiveInfinity, 3.14159265f, float.NaN }; + yield return new object[] { 0.0f, float.PositiveInfinity, float.PositiveInfinity, float.NaN }; + yield return new object[] { 5, 4, 3, 23 }; + yield return new object[] { 1e38f, 2.0f, -1e38f, 1e38f }; + yield return new object[] { 1e38f, 2.0f, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity, float.NaN }; + yield return new object[] { float.PositiveInfinity, -0.0f, float.NegativeInfinity, float.NaN }; + yield return new object[] { float.PositiveInfinity, -0.0f, -3.14159265f, float.NaN }; + yield return new object[] { float.PositiveInfinity, -0.0f, -0.0f, float.NaN }; + yield return new object[] { float.PositiveInfinity, -0.0f, float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, -0.0f, 0.0f, float.NaN }; + yield return new object[] { float.PositiveInfinity, -0.0f, 3.14159265f, float.NaN }; + yield return new object[] { float.PositiveInfinity, -0.0f, float.PositiveInfinity, float.NaN }; + yield return new object[] { float.PositiveInfinity, 0.0f, float.NegativeInfinity, float.NaN }; + yield return new object[] { float.PositiveInfinity, 0.0f, -3.14159265f, float.NaN }; + yield return new object[] { float.PositiveInfinity, 0.0f, -0.0f, float.NaN }; + yield return new object[] { float.PositiveInfinity, 0.0f, float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, 0.0f, 0.0f, float.NaN }; + yield return new object[] { float.PositiveInfinity, 0.0f, 3.14159265f, float.NaN }; + yield return new object[] { float.PositiveInfinity, 0.0f, float.PositiveInfinity, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NaN }; + } + } + + public static IEnumerable HypotDouble + { + get + { + yield return new object[] { double.NaN, double.NaN, double.NaN, 0.0 }; + yield return new object[] { double.NaN, 0.0f, double.NaN, 0.0 }; + yield return new object[] { double.NaN, 1.0f, double.NaN, 0.0 }; + yield return new object[] { double.NaN, 2.7182818284590452, double.NaN, 0.0 }; + yield return new object[] { double.NaN, 10.0, double.NaN, 0.0 }; + yield return new object[] { 0.0, 0.0, 0.0, 0.0 }; + yield return new object[] { 0.0, 1.0, 1.0, 0.0 }; + yield return new object[] { 0.0, 1.5707963267948966, 1.5707963267948966, 0.0 }; + yield return new object[] { 0.0, 2.0, 2.0, 0.0 }; + yield return new object[] { 0.0, 2.7182818284590452, 2.7182818284590452, 0.0 }; + yield return new object[] { 0.0, 3.0, 3.0, 0.0 }; + yield return new object[] { 0.0, 10.0, 10.0, 0.0 }; + yield return new object[] { 1.0, 1.0, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; + yield return new object[] { 1.0, 1e+10, 1e+10, 0.0 }; // dotnet/runtime#75651 + yield return new object[] { 1.0, 1e+20, 1e+20, 0.0 }; // dotnet/runtime#75651 + yield return new object[] { 2.7182818284590452, 0.31830988618379067, 2.7368553638387594, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (1 / pi) + yield return new object[] { 2.7182818284590452, 0.43429448190325183, 2.7527563996732919, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (log10(e)) + yield return new object[] { 2.7182818284590452, 0.63661977236758134, 2.7918346715914253, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (2 / pi) + yield return new object[] { 2.7182818284590452, 0.69314718055994531, 2.8052645352709344, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (ln(2)) + yield return new object[] { 2.7182818284590452, 0.70710678118654752, 2.8087463571726533, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (1 / sqrt(2)) + yield return new object[] { 2.7182818284590452, 0.78539816339744831, 2.8294710413783590, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (pi / 4) + yield return new object[] { 2.7182818284590452, 1.0, 2.8963867315900082, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) + yield return new object[] { 2.7182818284590452, 1.1283791670955126, 2.9431778138036127, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (2 / sqrt(pi)) + yield return new object[] { 2.7182818284590452, 1.4142135623730950, 3.0641566701020120, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (sqrt(2)) + yield return new object[] { 2.7182818284590452, 1.4426950408889634, 3.0774055761202907, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (log2(e)) + yield return new object[] { 2.7182818284590452, 1.5707963267948966, 3.1394995141268918, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (pi / 2) + yield return new object[] { 2.7182818284590452, 2.3025850929940457, 3.5624365551415857, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (ln(10)) + yield return new object[] { 2.7182818284590452, 2.7182818284590452, 3.8442310281591168, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (e) + yield return new object[] { 2.7182818284590452, 3.1415926535897932, 4.1543544023133136, DoubleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (pi) + yield return new object[] { 10.0, 0.31830988618379067, 10.005064776584025, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (1 / pi) + yield return new object[] { 10.0, 0.43429448190325183, 10.009426142242702, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (log10(e)) + yield return new object[] { 10.0, 0.63661977236758134, 10.020243746265325, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (2 / pi) + yield return new object[] { 10.0, 0.69314718055994531, 10.023993865417028, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (ln(2)) + yield return new object[] { 10.0, 0.70710678118654752, 10.024968827881711, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (1 / sqrt(2)) + yield return new object[] { 10.0, 0.78539816339744831, 10.030795096853892, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (pi / 4) + yield return new object[] { 10.0, 1.0, 10.049875621120890, DoubleCrossPlatformMachineEpsilon * 100 }; // + yield return new object[] { 10.0, 1.1283791670955126, 10.063460614755501, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (2 / sqrt(pi)) + yield return new object[] { 10.0, 1.4142135623730950, 10.099504938362078, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (sqrt(2)) + yield return new object[] { 10.0, 1.4426950408889634, 10.103532500121213, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (log2(e)) + yield return new object[] { 10.0, 1.5707963267948966, 10.122618292728040, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (pi / 2) + yield return new object[] { 10.0, 2.3025850929940457, 10.261671311754163, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (ln(10)) + yield return new object[] { 10.0, 2.7182818284590452, 10.362869105558106, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (e) + yield return new object[] { 10.0, 3.1415926535897932, 10.481870272097884, DoubleCrossPlatformMachineEpsilon * 100 }; // y: (pi) + yield return new object[] { double.PositiveInfinity, double.NaN, double.PositiveInfinity, 0.0 }; + yield return new object[] { double.PositiveInfinity, 0.0, double.PositiveInfinity, 0.0 }; + yield return new object[] { double.PositiveInfinity, 1.0, double.PositiveInfinity, 0.0 }; + yield return new object[] { double.PositiveInfinity, 2.7182818284590452, double.PositiveInfinity, 0.0 }; + yield return new object[] { double.PositiveInfinity, 10.0, double.PositiveInfinity, 0.0 }; + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable HypotSingle + { + get + { + yield return new object[] { float.NaN, float.NaN, float.NaN, 0.0f }; + yield return new object[] { float.NaN, 0.0f, float.NaN, 0.0f }; + yield return new object[] { float.NaN, 1.0f, float.NaN, 0.0f }; + yield return new object[] { float.NaN, 2.71828183f, float.NaN, 0.0f }; + yield return new object[] { float.NaN, 10.0f, float.NaN, 0.0f }; + yield return new object[] { 0.0f, 0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, 1.0f, 1.0f, 0.0f }; + yield return new object[] { 0.0f, 1.57079633f, 1.57079633f, 0.0f }; + yield return new object[] { 0.0f, 2.0f, 2.0f, 0.0f }; + yield return new object[] { 0.0f, 2.71828183f, 2.71828183f, 0.0f }; + yield return new object[] { 0.0f, 3.0f, 3.0f, 0.0f }; + yield return new object[] { 0.0f, 10.0f, 10.0f, 0.0f }; + yield return new object[] { 1.0f, 1.0f, 1.41421356f, SingleCrossPlatformMachineEpsilon * 10 }; + yield return new object[] { 1.0f, 1e+10f, 1e+10f, 0.0 }; // dotnet/runtime#75651 + yield return new object[] { 1.0f, 1e+20f, 1e+20f, 0.0 }; // dotnet/runtime#75651 + yield return new object[] { 2.71828183f, 0.318309886f, 2.73685536f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (1 / pi) + yield return new object[] { 2.71828183f, 0.434294482f, 2.75275640f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (log10(e)) + yield return new object[] { 2.71828183f, 0.636619772f, 2.79183467f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (2 / pi) + yield return new object[] { 2.71828183f, 0.693147181f, 2.80526454f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (ln(2)) + yield return new object[] { 2.71828183f, 0.707106781f, 2.80874636f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (1 / sqrt(2)) + yield return new object[] { 2.71828183f, 0.785398163f, 2.82947104f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (pi / 4) + yield return new object[] { 2.71828183f, 1.0f, 2.89638673f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) + yield return new object[] { 2.71828183f, 1.12837917f, 2.94317781f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (2 / sqrt(pi)) + yield return new object[] { 2.71828183f, 1.41421356f, 3.06415667f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (sqrt(2)) + yield return new object[] { 2.71828183f, 1.44269504f, 3.07740558f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (log2(e)) + yield return new object[] { 2.71828183f, 1.57079633f, 3.13949951f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (pi / 2) + yield return new object[] { 2.71828183f, 2.30258509f, 3.56243656f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (ln(10)) + yield return new object[] { 2.71828183f, 2.71828183f, 3.84423103f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (e) + yield return new object[] { 2.71828183f, 3.14159265f, 4.15435440f, SingleCrossPlatformMachineEpsilon * 10 }; // x: (e) y: (pi) + yield return new object[] { 10.0f, 0.318309886f, 10.0050648f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (1 / pi) + yield return new object[] { 10.0f, 0.434294482f, 10.0094261f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (log10(e)) + yield return new object[] { 10.0f, 0.636619772f, 10.0202437f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (2 / pi) + yield return new object[] { 10.0f, 0.693147181f, 10.0239939f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (ln(2)) + yield return new object[] { 10.0f, 0.707106781f, 10.0249688f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (1 / sqrt(2)) + yield return new object[] { 10.0f, 0.785398163f, 10.0307951f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (pi / 4) + yield return new object[] { 10.0f, 1.0f, 10.0498756f, SingleCrossPlatformMachineEpsilon * 100 }; // + yield return new object[] { 10.0f, 1.12837917f, 10.0634606f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (2 / sqrt(pi)) + yield return new object[] { 10.0f, 1.41421356f, 10.0995049f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (sqrt(2)) + yield return new object[] { 10.0f, 1.44269504f, 10.1035325f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (log2(e)) + yield return new object[] { 10.0f, 1.57079633f, 10.1226183f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (pi / 2) + yield return new object[] { 10.0f, 2.30258509f, 10.2616713f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (ln(10)) + yield return new object[] { 10.0f, 2.71828183f, 10.3628691f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (e) + yield return new object[] { 10.0f, 3.14159265f, 10.4818703f, SingleCrossPlatformMachineEpsilon * 100 }; // y: (pi) + yield return new object[] { float.PositiveInfinity, float.NaN, float.PositiveInfinity, 0.0f }; + yield return new object[] { float.PositiveInfinity, 0.0f, float.PositiveInfinity, 0.0f }; + yield return new object[] { float.PositiveInfinity, 1.0f, float.PositiveInfinity, 0.0f }; + yield return new object[] { float.PositiveInfinity, 2.71828183f, float.PositiveInfinity, 0.0f }; + yield return new object[] { float.PositiveInfinity, 10.0f, float.PositiveInfinity, 0.0f }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, 0.0f }; + } + } + + public static IEnumerable IsNaNDouble + { + get + { + yield return new object[] { double.NegativeInfinity, false }; + yield return new object[] { double.MinValue, false }; + yield return new object[] { -MinNormalDouble, false }; + yield return new object[] { -MaxSubnormalDouble, false }; + yield return new object[] { -double.Epsilon, false }; + yield return new object[] { -0.0, false }; + yield return new object[] { double.NaN, true }; + yield return new object[] { 0.0, false }; + yield return new object[] { double.Epsilon, false }; + yield return new object[] { MaxSubnormalDouble, false }; + yield return new object[] { MinNormalDouble, false }; + yield return new object[] { double.MaxValue, false }; + yield return new object[] { double.PositiveInfinity, false }; + } + } + + public static IEnumerable IsNaNSingle + { + get + { + yield return new object[] { float.NegativeInfinity, false }; + yield return new object[] { float.MinValue, false }; + yield return new object[] { -MinNormalSingle, false }; + yield return new object[] { -MaxSubnormalSingle, false }; + yield return new object[] { -float.Epsilon, false }; + yield return new object[] { -0.0f, false }; + yield return new object[] { float.NaN, true }; + yield return new object[] { 0.0f, false }; + yield return new object[] { float.Epsilon, false }; + yield return new object[] { MaxSubnormalSingle, false }; + yield return new object[] { MinNormalSingle, false }; + yield return new object[] { float.MaxValue, false }; + yield return new object[] { float.PositiveInfinity, false }; + } + } + + public static IEnumerable IsNegativeDouble + { + get + { + yield return new object[] { double.NegativeInfinity, true }; + yield return new object[] { double.MinValue, true }; + yield return new object[] { -MinNormalDouble, true }; + yield return new object[] { -MaxSubnormalDouble, true }; + yield return new object[] { -0.0, true }; + yield return new object[] { double.NaN, true }; + yield return new object[] { 0.0, false }; + yield return new object[] { MaxSubnormalDouble, false }; + yield return new object[] { MinNormalDouble, false }; + yield return new object[] { double.MaxValue, false }; + yield return new object[] { double.PositiveInfinity, false }; + } + } + + public static IEnumerable IsNegativeSingle + { + get + { + yield return new object[] { float.NegativeInfinity, true }; + yield return new object[] { float.MinValue, true }; + yield return new object[] { -MinNormalSingle, true }; + yield return new object[] { -MaxSubnormalSingle, true }; + yield return new object[] { -0.0f, true }; + yield return new object[] { float.NaN, true }; + yield return new object[] { 0.0f, false }; + yield return new object[] { MaxSubnormalSingle, false }; + yield return new object[] { MinNormalSingle, false }; + yield return new object[] { float.MaxValue, false }; + yield return new object[] { float.PositiveInfinity, false }; + } + } + + public static IEnumerable IsPositiveDouble + { + get + { + yield return new object[] { double.NegativeInfinity, false }; + yield return new object[] { double.MinValue, false }; + yield return new object[] { -MinNormalDouble, false }; + yield return new object[] { -MaxSubnormalDouble, false }; + yield return new object[] { -0.0, false }; + yield return new object[] { double.NaN, false }; + yield return new object[] { 0.0, true }; + yield return new object[] { MaxSubnormalDouble, true }; + yield return new object[] { MinNormalDouble, true }; + yield return new object[] { double.MaxValue, true }; + yield return new object[] { double.PositiveInfinity, true }; + } + } + + public static IEnumerable IsPositiveSingle + { + get + { + yield return new object[] { float.NegativeInfinity, false }; + yield return new object[] { float.MinValue, false }; + yield return new object[] { -MinNormalSingle, false }; + yield return new object[] { -MaxSubnormalSingle, false }; + yield return new object[] { -0.0f, false }; + yield return new object[] { float.NaN, false }; + yield return new object[] { 0.0f, true }; + yield return new object[] { MaxSubnormalSingle, true }; + yield return new object[] { MinNormalSingle, true }; + yield return new object[] { float.MaxValue, true }; + yield return new object[] { float.PositiveInfinity, true }; + } + } + + public static IEnumerable IsPositiveInfinityDouble + { + get + { + yield return new object[] { double.NegativeInfinity, false }; + yield return new object[] { double.MinValue, false }; + yield return new object[] { -MinNormalDouble, false }; + yield return new object[] { -MaxSubnormalDouble, false }; + yield return new object[] { -double.Epsilon, false }; + yield return new object[] { -0.0, false }; + yield return new object[] { double.NaN, false }; + yield return new object[] { 0.0, false }; + yield return new object[] { double.Epsilon, false }; + yield return new object[] { MaxSubnormalDouble, false }; + yield return new object[] { MinNormalDouble, false }; + yield return new object[] { double.MaxValue, false }; + yield return new object[] { double.PositiveInfinity, true }; + } + } + + public static IEnumerable IsPositiveInfinitySingle + { + get + { + yield return new object[] { float.NegativeInfinity, false }; + yield return new object[] { float.MinValue, false }; + yield return new object[] { -MinNormalSingle, false }; + yield return new object[] { -MaxSubnormalSingle, false }; + yield return new object[] { -float.Epsilon, false }; + yield return new object[] { -0.0f, false }; + yield return new object[] { float.NaN, false }; + yield return new object[] { 0.0f, false }; + yield return new object[] { float.Epsilon, false }; + yield return new object[] { MaxSubnormalSingle, false }; + yield return new object[] { MinNormalSingle, false }; + yield return new object[] { float.MaxValue, false }; + yield return new object[] { float.PositiveInfinity, true }; + } + } + + public static IEnumerable IsZeroDouble + { + get + { + yield return new object[] { double.NegativeInfinity, false }; + yield return new object[] { double.MinValue, false }; + yield return new object[] { -MinNormalDouble, false }; + yield return new object[] { -MaxSubnormalDouble, false }; + yield return new object[] { -double.Epsilon, false }; + yield return new object[] { -0.0, true }; + yield return new object[] { double.NaN, false }; + yield return new object[] { 0.0, true }; + yield return new object[] { double.Epsilon, false }; + yield return new object[] { MaxSubnormalDouble, false }; + yield return new object[] { MinNormalDouble, false }; + yield return new object[] { double.MaxValue, false }; + yield return new object[] { double.PositiveInfinity, false }; + } + } + + public static IEnumerable IsZeroSingle + { + get + { + yield return new object[] { float.NegativeInfinity, false }; + yield return new object[] { float.MinValue, false }; + yield return new object[] { -MinNormalSingle, false }; + yield return new object[] { -MaxSubnormalSingle, false }; + yield return new object[] { -float.Epsilon, false }; + yield return new object[] { -0.0f, true }; + yield return new object[] { float.NaN, false }; + yield return new object[] { 0.0f, true }; + yield return new object[] { float.Epsilon, false }; + yield return new object[] { MaxSubnormalSingle, false }; + yield return new object[] { MinNormalSingle, false }; + yield return new object[] { float.MaxValue, false }; + yield return new object[] { float.PositiveInfinity, false }; + } + } + + public static IEnumerable LerpDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.NegativeInfinity, 0.5, double.NegativeInfinity }; + yield return new object[] { double.NegativeInfinity, double.NaN, 0.5, double.NaN }; + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, 0.5, double.NaN }; + yield return new object[] { double.NegativeInfinity, 0.0, 0.5, double.NegativeInfinity }; + yield return new object[] { double.NegativeInfinity, 1.0, 0.5, double.NegativeInfinity }; + yield return new object[] { double.NaN, double.NegativeInfinity, 0.5, double.NaN }; + yield return new object[] { double.NaN, double.NaN, 0.5, double.NaN }; + yield return new object[] { double.NaN, double.PositiveInfinity, 0.5, double.NaN }; + yield return new object[] { double.NaN, 0.0, 0.5, double.NaN }; + yield return new object[] { double.NaN, 1.0, 0.5, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, 0.5, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.NaN, 0.5, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.5, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, 0.0, 0.5, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, 1.0, 0.5, double.PositiveInfinity }; + yield return new object[] { 1.0, 3.0, 0.0, 1.0 }; + yield return new object[] { 1.0, 3.0, 0.5, 2.0 }; + yield return new object[] { 1.0, 3.0, 1.0, 3.0 }; + yield return new object[] { 1.0, 3.0, 2.0, 5.0 }; + yield return new object[] { 2.0, 4.0, 0.0, 2.0 }; + yield return new object[] { 2.0, 4.0, 0.5, 3.0 }; + yield return new object[] { 2.0, 4.0, 1.0, 4.0 }; + yield return new object[] { 2.0, 4.0, 2.0, 6.0 }; + yield return new object[] { 3.0, 1.0, 0.0, 3.0 }; + yield return new object[] { 3.0, 1.0, 0.5, 2.0 }; + yield return new object[] { 3.0, 1.0, 1.0, 1.0 }; + yield return new object[] { 3.0, 1.0, 2.0, -1.0 }; + yield return new object[] { 4.0, 2.0, 0.0, 4.0 }; + yield return new object[] { 4.0, 2.0, 0.5, 3.0 }; + yield return new object[] { 4.0, 2.0, 1.0, 2.0 }; + yield return new object[] { 4.0, 2.0, 2.0, 0.0 }; + } + } + + public static IEnumerable LerpSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, 0.5f, float.NegativeInfinity }; + yield return new object[] { float.NegativeInfinity, float.NaN, 0.5f, float.NaN }; + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, 0.5f, float.NaN }; + yield return new object[] { float.NegativeInfinity, 0.0f, 0.5f, float.NegativeInfinity }; + yield return new object[] { float.NegativeInfinity, 1.0f, 0.5f, float.NegativeInfinity }; + yield return new object[] { float.NaN, float.NegativeInfinity, 0.5f, float.NaN }; + yield return new object[] { float.NaN, float.NaN, 0.5f, float.NaN }; + yield return new object[] { float.NaN, float.PositiveInfinity, 0.5f, float.NaN }; + yield return new object[] { float.NaN, 0.0f, 0.5f, float.NaN }; + yield return new object[] { float.NaN, 1.0f, 0.5f, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, 0.5f, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.NaN, 0.5f, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.5f, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, 0.0f, 0.5f, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, 1.0f, 0.5f, float.PositiveInfinity }; + yield return new object[] { 1.0f, 3.0f, 0.0f, 1.0f }; + yield return new object[] { 1.0f, 3.0f, 0.5f, 2.0f }; + yield return new object[] { 1.0f, 3.0f, 1.0f, 3.0f }; + yield return new object[] { 1.0f, 3.0f, 2.0f, 5.0f }; + yield return new object[] { 2.0f, 4.0f, 0.0f, 2.0f }; + yield return new object[] { 2.0f, 4.0f, 0.5f, 3.0f }; + yield return new object[] { 2.0f, 4.0f, 1.0f, 4.0f }; + yield return new object[] { 2.0f, 4.0f, 2.0f, 6.0f }; + yield return new object[] { 3.0f, 1.0f, 0.0f, 3.0f }; + yield return new object[] { 3.0f, 1.0f, 0.5f, 2.0f }; + yield return new object[] { 3.0f, 1.0f, 1.0f, 1.0f }; + yield return new object[] { 3.0f, 1.0f, 2.0f, -1.0f }; + yield return new object[] { 4.0f, 2.0f, 0.0f, 4.0f }; + yield return new object[] { 4.0f, 2.0f, 0.5f, 3.0f }; + yield return new object[] { 4.0f, 2.0f, 1.0f, 2.0f }; + yield return new object[] { 4.0f, 2.0f, 2.0f, 0.0f }; + } + } + + public static IEnumerable LogDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.NaN, 0.0 }; + yield return new object[] { -3.1415926535897932, double.NaN, 0.0 }; // value: -(pi) + yield return new object[] { -2.7182818284590452, double.NaN, 0.0 }; // value: -(e) + yield return new object[] { -1.4142135623730950, double.NaN, 0.0 }; // value: -(sqrt(2)) + yield return new object[] { -1.0, double.NaN, 0.0 }; + yield return new object[] { -0.69314718055994531, double.NaN, 0.0 }; // value: -(ln(2)) + yield return new object[] { -0.43429448190325183, double.NaN, 0.0 }; // value: -(log10(e)) + yield return new object[] { -0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] { double.NaN, double.NaN, 0.0 }; + yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] { 0.043213918263772250, -3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) + yield return new object[] { 0.065988035845312537, -2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) + yield return new object[] { 0.1, -2.3025850929940457, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) + yield return new object[] { 0.20787957635076191, -1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) + yield return new object[] { 0.23629008834452270, -1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) + yield return new object[] { 0.24311673443421421, -1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) + yield return new object[] { 0.32355726390307110, -1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) + yield return new object[] { 0.36787944117144232, -1.0, 0.0f }; + yield return new object[] { 0.45593812776599624, -0.78539816339744831, DoubleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) + yield return new object[] { 0.49306869139523979, -0.70710678118654752, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) + yield return new object[] { 0.5, -0.69314718055994531, DoubleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) + yield return new object[] { 0.52907780826773535, -0.63661977236758134, DoubleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) + yield return new object[] { 0.64772148514180065, -0.43429448190325183, DoubleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) + yield return new object[] { 0.72737734929521647, -0.31830988618379067, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) + yield return new object[] { 1.0, 0.0, 0.0 }; + yield return new object[] { 1.3748022274393586, 0.31830988618379067, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 1.5438734439711811, 0.43429448190325183, DoubleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 1.8900811645722220, 0.63661977236758134, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 2.0, 0.69314718055994531, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 2.0281149816474725, 0.70710678118654752, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 2.1932800507380155, 0.78539816339744831, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 2.7182818284590452, 1.0, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (e) + yield return new object[] { 3.0906430223107976, 1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) + yield return new object[] { 4.1132503787829275, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) + yield return new object[] { 4.2320861065570819, 1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) + yield return new object[] { 4.8104773809653517, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) + yield return new object[] { 10.0, 2.3025850929940457, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) + yield return new object[] { 15.154262241479264, 2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 23.140692632779269, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable LogSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.NaN, 0.0f }; + yield return new object[] { -3.14159265f, float.NaN, 0.0f }; // value: -(pi) + yield return new object[] { -2.71828183f, float.NaN, 0.0f }; // value: -(e) + yield return new object[] { -1.41421356f, float.NaN, 0.0f }; // value: -(sqrt(2)) + yield return new object[] { -1.0f, float.NaN, 0.0f }; + yield return new object[] { -0.693147181f, float.NaN, 0.0f }; // value: -(ln(2)) + yield return new object[] { -0.434294482f, float.NaN, 0.0f }; // value: -(log10(e)) + yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { float.NaN, float.NaN, 0.0f }; + yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { 0.0432139183f, -3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) + yield return new object[] { 0.0659880358f, -2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) + yield return new object[] { 0.1f, -2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) + yield return new object[] { 0.207879576f, -1.57079633f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) + yield return new object[] { 0.236290088f, -1.44269504f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) + yield return new object[] { 0.243116734f, -1.41421356f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) + yield return new object[] { 0.323557264f, -1.12837917f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) + yield return new object[] { 0.367879441f, -1.0f, 0.0f }; + yield return new object[] { 0.455938128f, -0.785398163f, SingleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) + yield return new object[] { 0.493068691f, -0.707106781f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) + yield return new object[] { 0.5f, -0.693147181f, SingleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) + yield return new object[] { 0.529077808f, -0.636619772f, SingleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) + yield return new object[] { 0.647721485f, -0.434294482f, SingleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) + yield return new object[] { 0.727377349f, -0.318309886f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) + yield return new object[] { 1.0f, 0.0f, 0.0f }; + yield return new object[] { 1.37480223f, 0.318309886f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 1.54387344f, 0.434294482f, SingleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 1.89008116f, 0.636619772f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 2.0f, 0.693147181f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 2.02811498f, 0.707106781f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 2.19328005f, 0.785398163f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 2.71828183f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (e) + yield return new object[] { 3.09064302f, 1.12837917f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) + yield return new object[] { 4.11325038f, 1.41421356f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) + yield return new object[] { 4.23208611f, 1.44269504f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) + yield return new object[] { 4.81047738f, 1.57079633f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) + yield return new object[] { 10.0f, 2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) + yield return new object[] { 15.1542622f, 2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 23.1406926f, 3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; + } + } + + public static IEnumerable Log2Double + { + get + { + yield return new object[] { double.NegativeInfinity, double.NaN, 0.0 }; + yield return new object[] {-0.11331473229676087, double.NaN, 0.0 }; + yield return new object[] {-0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] { double.NaN, double.NaN, 0.0 }; + yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] { 0.11331473229676087, -3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) + yield return new object[] { 0.15195522325791297, -2.7182818284590453, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) + yield return new object[] { 0.20269956628651730, -2.3025850929940460, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) + yield return new object[] { 0.33662253682241906, -1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) + yield return new object[] { 0.36787944117144232, -1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) + yield return new object[] { 0.37521422724648177, -1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) + yield return new object[] { 0.45742934732229695, -1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) + yield return new object[] { 0.5, -1.0, 0.0f }; + yield return new object[] { 0.58019181037172444, -0.78539816339744840, DoubleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) + yield return new object[] { 0.61254732653606592, -0.70710678118654750, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) + yield return new object[] { 0.61850313780157598, -0.69314718055994537, DoubleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) + yield return new object[] { 0.64321824193300488, -0.63661977236758126, DoubleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) + yield return new object[] { 0.74005557395545179, -0.43429448190325190, DoubleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) + yield return new object[] { 0.80200887896145195, -0.31830988618379073, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) + yield return new object[] { 1, 0.0, 0.0 }; + yield return new object[] { 1.2468689889006383, 0.31830988618379073, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 1.3512498725672678, 0.43429448190325226, DoubleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 1.5546822754821001, 0.63661977236758126, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 1.6168066722416747, 0.69314718055994537, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 1.6325269194381528, 0.70710678118654750, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 1.7235679341273495, 0.78539816339744830, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 2, 1.0, 0.0 }; // value: (e) + yield return new object[] { 2.1861299583286618, 1.1283791670955128, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) + yield return new object[] { 2.6651441426902252, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) + yield return new object[] { 2.7182818284590452, 1.4426950408889632, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) + yield return new object[] { 2.9706864235520193, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) + yield return new object[] { 4.9334096679145963, 2.3025850929940460, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) + yield return new object[] { 6.5808859910179210, 2.7182818284590455, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 8.8249778270762876, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable Log2Single + { + get + { + yield return new object[] { float.NegativeInfinity, float.NaN, 0.0f }; + yield return new object[] { -0.113314732f, float.NaN, 0.0f }; + yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { float.NaN, float.NaN, 0.0f }; + yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { 0.113314732f, -3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) + yield return new object[] { 0.151955223f, -2.71828200f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) + yield return new object[] { 0.202699566f, -2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) + yield return new object[] { 0.336622537f, -1.57079630f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) + yield return new object[] { 0.367879441f, -1.44269500f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) + yield return new object[] { 0.375214227f, -1.41421360f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) + yield return new object[] { 0.457429347f, -1.12837910f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) + yield return new object[] { 0.5f, -1.0f, 0.0f }; + yield return new object[] { 0.580191810f, -0.785398211f, SingleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) + yield return new object[] { 0.612547327f, -0.707106700f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) + yield return new object[] { 0.618503138f, -0.693147144f, SingleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) + yield return new object[] { 0.643218242f, -0.636619823f, SingleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) + yield return new object[] { 0.740055574f, -0.434294550f, SingleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) + yield return new object[] { 0.802008879f, -0.318309900f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) + yield return new object[] { 1, 0.0f, 0.0f }; + yield return new object[] { 1.24686899f, 0.318309870f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 1.35124987f, 0.434294340f, SingleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 1.55468228f, 0.636619823f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 1.61680667f, 0.693147144f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 1.63252692f, 0.707106700f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 1.72356793f, 0.785398211f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 2, 1.0f, 0.0f }; // value: (e) + yield return new object[] { 2.18612996f, 1.12837920f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) + yield return new object[] { 2.66514414f, 1.41421360f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) + yield return new object[] { 2.71828183f, 1.44269490f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) + yield return new object[] { 2.97068642f, 1.57079630f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) + yield return new object[] { 4.93340967f, 2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) + yield return new object[] { 6.58088599f, 2.71828170f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 8.82497783f, 3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; + } + } + + public static IEnumerable MaxDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity }; + yield return new object[] { double.MinValue, double.MaxValue, double.MaxValue }; + yield return new object[] { double.MaxValue, double.MinValue, double.MaxValue }; + yield return new object[] { double.NaN, double.NaN, double.NaN }; + yield return new object[] { double.NaN, 1.0f, double.NaN }; + yield return new object[] { 1.0f, double.NaN, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.NaN, double.NaN }; + yield return new object[] { double.NegativeInfinity, double.NaN, double.NaN }; + yield return new object[] { double.NaN, double.PositiveInfinity, double.NaN }; + yield return new object[] { double.NaN, double.NegativeInfinity, double.NaN }; + yield return new object[] { -0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, -0.0f, 0.0f }; + yield return new object[] { 2.0f, -3.0f, 2.0f }; + yield return new object[] { -3.0f, 2.0f, 2.0f }; + yield return new object[] { 3.0f, -2.0f, 3.0f }; + yield return new object[] { -2.0f, 3.0f, 3.0f }; + } + } + + public static IEnumerable MaxSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity }; + yield return new object[] { float.MinValue, float.MaxValue, float.MaxValue }; + yield return new object[] { float.MaxValue, float.MinValue, float.MaxValue }; + yield return new object[] { float.NaN, float.NaN, float.NaN }; + yield return new object[] { float.NaN, 1.0f, float.NaN }; + yield return new object[] { 1.0f, float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.NaN, float.NaN }; + yield return new object[] { float.NegativeInfinity, float.NaN, float.NaN }; + yield return new object[] { float.NaN, float.PositiveInfinity, float.NaN }; + yield return new object[] { float.NaN, float.NegativeInfinity, float.NaN }; + yield return new object[] { -0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, -0.0f, 0.0f }; + yield return new object[] { 2.0f, -3.0f, 2.0f }; + yield return new object[] { -3.0f, 2.0f, 2.0f }; + yield return new object[] { 3.0f, -2.0f, 3.0f }; + yield return new object[] { -2.0f, 3.0f, 3.0f }; + } + } + + public static IEnumerable MaxMagnitudeDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity }; + yield return new object[] { double.MinValue, double.MaxValue, double.MaxValue }; + yield return new object[] { double.MaxValue, double.MinValue, double.MaxValue }; + yield return new object[] { double.NaN, double.NaN, double.NaN }; + yield return new object[] { double.NaN, 1.0f, double.NaN }; + yield return new object[] { 1.0f, double.NaN, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.NaN, double.NaN }; + yield return new object[] { double.NegativeInfinity, double.NaN, double.NaN }; + yield return new object[] { double.NaN, double.PositiveInfinity, double.NaN }; + yield return new object[] { double.NaN, double.NegativeInfinity, double.NaN }; + yield return new object[] { -0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, -0.0f, 0.0f }; + yield return new object[] { 2.0f, -3.0f, -3.0f }; + yield return new object[] { -3.0f, 2.0f, -3.0f }; + yield return new object[] { 3.0f, -2.0f, 3.0f }; + yield return new object[] { -2.0f, 3.0f, 3.0f }; + } + } + + public static IEnumerable MaxMagnitudeSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity }; + yield return new object[] { float.MinValue, float.MaxValue, float.MaxValue }; + yield return new object[] { float.MaxValue, float.MinValue, float.MaxValue }; + yield return new object[] { float.NaN, float.NaN, float.NaN }; + yield return new object[] { float.NaN, 1.0f, float.NaN }; + yield return new object[] { 1.0f, float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.NaN, float.NaN }; + yield return new object[] { float.NegativeInfinity, float.NaN, float.NaN }; + yield return new object[] { float.NaN, float.PositiveInfinity, float.NaN }; + yield return new object[] { float.NaN, float.NegativeInfinity, float.NaN }; + yield return new object[] { -0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, -0.0f, 0.0f }; + yield return new object[] { 2.0f, -3.0f, -3.0f }; + yield return new object[] { -3.0f, 2.0f, -3.0f }; + yield return new object[] { 3.0f, -2.0f, 3.0f }; + yield return new object[] { -2.0f, 3.0f, 3.0f }; + } + } + + public static IEnumerable MaxMagnitudeNumberDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity }; + yield return new object[] { double.MinValue, double.MaxValue, double.MaxValue }; + yield return new object[] { double.MaxValue, double.MinValue, double.MaxValue }; + yield return new object[] { double.NaN, double.NaN, double.NaN }; + yield return new object[] { double.NaN, 1.0f, 1.0f }; + yield return new object[] { 1.0f, double.NaN, 1.0f }; + yield return new object[] { double.PositiveInfinity, double.NaN, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, double.NaN, double.NegativeInfinity }; + yield return new object[] { double.NaN, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.NaN, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { -0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, -0.0f, 0.0f }; + yield return new object[] { 2.0f, -3.0f, -3.0f }; + yield return new object[] { -3.0f, 2.0f, -3.0f }; + yield return new object[] { 3.0f, -2.0f, 3.0f }; + yield return new object[] { -2.0f, 3.0f, 3.0f }; + } + } + + public static IEnumerable MaxMagnitudeNumberSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity }; + yield return new object[] { float.MinValue, float.MaxValue, float.MaxValue }; + yield return new object[] { float.MaxValue, float.MinValue, float.MaxValue }; + yield return new object[] { float.NaN, float.NaN, float.NaN }; + yield return new object[] { float.NaN, 1.0f, 1.0f }; + yield return new object[] { 1.0f, float.NaN, 1.0f }; + yield return new object[] { float.PositiveInfinity, float.NaN, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.NaN, float.NegativeInfinity }; + yield return new object[] { float.NaN, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.NaN, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { -0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, -0.0f, 0.0f }; + yield return new object[] { 2.0f, -3.0f, -3.0f }; + yield return new object[] { -3.0f, 2.0f, -3.0f }; + yield return new object[] { 3.0f, -2.0f, 3.0f }; + yield return new object[] { -2.0f, 3.0f, 3.0f }; + } + } + + public static IEnumerable MaxNumberDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity }; + yield return new object[] { double.MinValue, double.MaxValue, double.MaxValue }; + yield return new object[] { double.MaxValue, double.MinValue, double.MaxValue }; + yield return new object[] { double.NaN, double.NaN, double.NaN }; + yield return new object[] { double.NaN, 1.0f, 1.0f }; + yield return new object[] { 1.0f, double.NaN, 1.0f }; + yield return new object[] { double.PositiveInfinity, double.NaN, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, double.NaN, double.NegativeInfinity }; + yield return new object[] { double.NaN, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.NaN, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { -0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, -0.0f, 0.0f }; + yield return new object[] { 2.0f, -3.0f, 2.0f }; + yield return new object[] { -3.0f, 2.0f, 2.0f }; + yield return new object[] { 3.0f, -2.0f, 3.0f }; + yield return new object[] { -2.0f, 3.0f, 3.0f }; + } + } + + public static IEnumerable MaxNumberSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity }; + yield return new object[] { float.MinValue, float.MaxValue, float.MaxValue }; + yield return new object[] { float.MaxValue, float.MinValue, float.MaxValue }; + yield return new object[] { float.NaN, float.NaN, float.NaN }; + yield return new object[] { float.NaN, 1.0f, 1.0f }; + yield return new object[] { 1.0f, float.NaN, 1.0f }; + yield return new object[] { float.PositiveInfinity, float.NaN, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.NaN, float.NegativeInfinity }; + yield return new object[] { float.NaN, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.NaN, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { -0.0f, 0.0f, 0.0f }; + yield return new object[] { 0.0f, -0.0f, 0.0f }; + yield return new object[] { 2.0f, -3.0f, 2.0f }; + yield return new object[] { -3.0f, 2.0f, 2.0f }; + yield return new object[] { 3.0f, -2.0f, 3.0f }; + yield return new object[] { -2.0f, 3.0f, 3.0f }; + } + } + + public static IEnumerable MinDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { double.MinValue, double.MaxValue, double.MinValue }; + yield return new object[] { double.MaxValue, double.MinValue, double.MinValue }; + yield return new object[] { double.NaN, double.NaN, double.NaN }; + yield return new object[] { double.NaN, 1.0f, double.NaN }; + yield return new object[] { 1.0f, double.NaN, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.NaN, double.NaN }; + yield return new object[] { double.NegativeInfinity, double.NaN, double.NaN }; + yield return new object[] { double.NaN, double.PositiveInfinity, double.NaN }; + yield return new object[] { double.NaN, double.NegativeInfinity, double.NaN }; + yield return new object[] { -0.0f, 0.0f, -0.0f }; + yield return new object[] { 0.0f, -0.0f, -0.0f }; + yield return new object[] { 2.0f, -3.0f, -3.0f }; + yield return new object[] { -3.0f, 2.0f, -3.0f }; + yield return new object[] { 3.0f, -2.0f, -2.0f }; + yield return new object[] { -2.0f, 3.0f, -2.0f }; + } + } + + public static IEnumerable MinSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { float.MinValue, float.MaxValue, float.MinValue }; + yield return new object[] { float.MaxValue, float.MinValue, float.MinValue }; + yield return new object[] { float.NaN, float.NaN, float.NaN }; + yield return new object[] { float.NaN, 1.0f, float.NaN }; + yield return new object[] { 1.0f, float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.NaN, float.NaN }; + yield return new object[] { float.NegativeInfinity, float.NaN, float.NaN }; + yield return new object[] { float.NaN, float.PositiveInfinity, float.NaN }; + yield return new object[] { float.NaN, float.NegativeInfinity, float.NaN }; + yield return new object[] { -0.0f, 0.0f, -0.0f }; + yield return new object[] { 0.0f, -0.0f, -0.0f }; + yield return new object[] { 2.0f, -3.0f, -3.0f }; + yield return new object[] { -3.0f, 2.0f, -3.0f }; + yield return new object[] { 3.0f, -2.0f, -2.0f }; + yield return new object[] { -2.0f, 3.0f, -2.0f }; + } + } + + public static IEnumerable MinMagnitudeDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { double.MinValue, double.MaxValue, double.MinValue }; + yield return new object[] { double.MaxValue, double.MinValue, double.MinValue }; + yield return new object[] { double.NaN, double.NaN, double.NaN }; + yield return new object[] { double.NaN, 1.0f, double.NaN }; + yield return new object[] { 1.0f, double.NaN, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.NaN, double.NaN }; + yield return new object[] { double.NegativeInfinity, double.NaN, double.NaN }; + yield return new object[] { double.NaN, double.PositiveInfinity, double.NaN }; + yield return new object[] { double.NaN, double.NegativeInfinity, double.NaN }; + yield return new object[] { -0.0f, 0.0f, -0.0f }; + yield return new object[] { 0.0f, -0.0f, -0.0f }; + yield return new object[] { 2.0f, -3.0f, 2.0f }; + yield return new object[] { -3.0f, 2.0f, 2.0f }; + yield return new object[] { 3.0f, -2.0f, -2.0f }; + yield return new object[] { -2.0f, 3.0f, -2.0f }; + } + } + + public static IEnumerable MinMagnitudeSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { float.MinValue, float.MaxValue, float.MinValue }; + yield return new object[] { float.MaxValue, float.MinValue, float.MinValue }; + yield return new object[] { float.NaN, float.NaN, float.NaN }; + yield return new object[] { float.NaN, 1.0f, float.NaN }; + yield return new object[] { 1.0f, float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.NaN, float.NaN }; + yield return new object[] { float.NegativeInfinity, float.NaN, float.NaN }; + yield return new object[] { float.NaN, float.PositiveInfinity, float.NaN }; + yield return new object[] { float.NaN, float.NegativeInfinity, float.NaN }; + yield return new object[] { -0.0f, 0.0f, -0.0f }; + yield return new object[] { 0.0f, -0.0f, -0.0f }; + yield return new object[] { 2.0f, -3.0f, 2.0f }; + yield return new object[] { -3.0f, 2.0f, 2.0f }; + yield return new object[] { 3.0f, -2.0f, -2.0f }; + yield return new object[] { -2.0f, 3.0f, -2.0f }; + } + } + + public static IEnumerable MinMagnitudeNumberDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { double.MinValue, double.MaxValue, double.MinValue }; + yield return new object[] { double.MaxValue, double.MinValue, double.MinValue }; + yield return new object[] { double.NaN, double.NaN, double.NaN }; + yield return new object[] { double.NaN, 1.0f, 1.0f }; + yield return new object[] { 1.0f, double.NaN, 1.0f }; + yield return new object[] { double.PositiveInfinity, double.NaN, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, double.NaN, double.NegativeInfinity }; + yield return new object[] { double.NaN, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.NaN, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { -0.0f, 0.0f, -0.0f }; + yield return new object[] { 0.0f, -0.0f, -0.0f }; + yield return new object[] { 2.0f, -3.0f, 2.0f }; + yield return new object[] { -3.0f, 2.0f, 2.0f }; + yield return new object[] { 3.0f, -2.0f, -2.0f }; + yield return new object[] { -2.0f, 3.0f, -2.0f }; + } + } + + public static IEnumerable MinMagnitudeNumberSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { float.MinValue, float.MaxValue, float.MinValue }; + yield return new object[] { float.MaxValue, float.MinValue, float.MinValue }; + yield return new object[] { float.NaN, float.NaN, float.NaN }; + yield return new object[] { float.NaN, 1.0f, 1.0f }; + yield return new object[] { 1.0f, float.NaN, 1.0f }; + yield return new object[] { float.PositiveInfinity, float.NaN, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.NaN, float.NegativeInfinity }; + yield return new object[] { float.NaN, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.NaN, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { -0.0f, 0.0f, -0.0f }; + yield return new object[] { 0.0f, -0.0f, -0.0f }; + yield return new object[] { 2.0f, -3.0f, 2.0f }; + yield return new object[] { -3.0f, 2.0f, 2.0f }; + yield return new object[] { 3.0f, -2.0f, -2.0f }; + yield return new object[] { -2.0f, 3.0f, -2.0f }; + } + } + + public static IEnumerable MinNumberDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { double.MinValue, double.MaxValue, double.MinValue }; + yield return new object[] { double.MaxValue, double.MinValue, double.MinValue }; + yield return new object[] { double.NaN, double.NaN, double.NaN }; + yield return new object[] { double.NaN, 1.0f, 1.0f }; + yield return new object[] { 1.0f, double.NaN, 1.0f }; + yield return new object[] { double.PositiveInfinity, double.NaN, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, double.NaN, double.NegativeInfinity }; + yield return new object[] { double.NaN, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.NaN, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { -0.0f, 0.0f, -0.0f }; + yield return new object[] { 0.0f, -0.0f, -0.0f }; + yield return new object[] { 2.0f, -3.0f, -3.0f }; + yield return new object[] { -3.0f, 2.0f, -3.0f }; + yield return new object[] { 3.0f, -2.0f, -2.0f }; + yield return new object[] { -2.0f, 3.0f, -2.0f }; + } + } + + public static IEnumerable MinNumberSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { float.MinValue, float.MaxValue, float.MinValue }; + yield return new object[] { float.MaxValue, float.MinValue, float.MinValue }; + yield return new object[] { float.NaN, float.NaN, float.NaN }; + yield return new object[] { float.NaN, 1.0f, 1.0f }; + yield return new object[] { 1.0f, float.NaN, 1.0f }; + yield return new object[] { float.PositiveInfinity, float.NaN, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.NaN, float.NegativeInfinity }; + yield return new object[] { float.NaN, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.NaN, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { -0.0f, 0.0f, -0.0f }; + yield return new object[] { 0.0f, -0.0f, -0.0f }; + yield return new object[] { 2.0f, -3.0f, -3.0f }; + yield return new object[] { -3.0f, 2.0f, -3.0f }; + yield return new object[] { 3.0f, -2.0f, -2.0f }; + yield return new object[] { -2.0f, 3.0f, -2.0f }; + } + } + + public static IEnumerable RadiansToDegreesDouble + { + get + { + yield return new object[] { double.NaN, double.NaN, 0.0 }; + yield return new object[] { 0.0, 0.0, 0.0 }; + yield return new object[] { 0.0055555555555555567, 0.3183098861837906, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 0.0075798686324546743, 0.4342944819032518, DoubleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 0.008726646259971648, 0.5, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.0111111111111111124, 0.6366197723675813, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 0.0120977005016866801, 0.6931471805599453, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 0.0123413414948843512, 0.7071067811865475, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 0.0137077838904018851, 0.7853981633974483, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 0.017453292519943295, 1.0, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.019693931676727953, 1.1283791670955126, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / sqrt(pi)) + yield return new object[] { 0.024682682989768702, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon }; // expected: (sqrt(2)) + yield return new object[] { 0.025179778565706630, 1.4426950408889634, DoubleCrossPlatformMachineEpsilon }; // expected: (log2(e)) + yield return new object[] { 0.026179938779914940, 1.5, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.027415567780803770, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 2) + yield return new object[] { 0.034906585039886590, 2.0, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.040187691180085916, 2.3025850929940457, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(10)) + yield return new object[] { 0.043633231299858240, 2.5, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.047442967903742035, 2.7182818284590452, DoubleCrossPlatformMachineEpsilon }; // expected: (e) + yield return new object[] { 0.052359877559829880, 3.0, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.054831135561607540, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon }; // expected: (pi) + yield return new object[] { 0.061086523819801536, 3.5, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable RadiansToDegreesSingle + { + get + { + yield return new object[] { float.NaN, float.NaN, 0.0 }; + yield return new object[] { 0.0f, 0.0f, 0.0 }; + yield return new object[] { 0.0055555557f, 0.318309886f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 0.007579869f, 0.434294482f, SingleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 0.008726646f, 0.5f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.011111111f, 0.636619772f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 0.0120977005f, 0.693147181f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 0.012341342f, 0.707106781f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 0.013707785f, 0.785398163f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 0.017453292f, 1.0f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.019693933f, 1.12837917f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / sqrt(pi)) + yield return new object[] { 0.024682684f, 1.41421356f, SingleCrossPlatformMachineEpsilon }; // expected: (sqrt(2)) + yield return new object[] { 0.025179777f, 1.44269504f, SingleCrossPlatformMachineEpsilon }; // expected: (log2(e)) + yield return new object[] { 0.02617994f, 1.5f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.02741557f, 1.57079633f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 2) + yield return new object[] { 0.034906585f, 2.0f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.040187694f, 2.30258509f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(10)) + yield return new object[] { 0.043633234f, 2.5f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.047442965f, 2.71828183f, SingleCrossPlatformMachineEpsilon }; // expected: (e) + yield return new object[] { 0.05235988f, 3.0f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { 0.05483114f, 3.14159265f, SingleCrossPlatformMachineEpsilon }; // expected: (pi) + yield return new object[] { 0.061086528f, 3.5f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable RoundDouble + { + get + { + yield return new object[] { 0.0, 0.0 }; + yield return new object[] { 1.4, 1.0 }; + yield return new object[] { 1.5, 2.0 }; + yield return new object[] { 2e7, 2e7 }; + yield return new object[] { -0.0, -0.0 }; + yield return new object[] { -1.4, -1.0 }; + yield return new object[] { -1.5, -2.0 }; + yield return new object[] { -2e7, -2e7 }; + } + } + + public static IEnumerable RoundSingle + { + get + { + yield return new object[] { 0.0f, 0.0f }; + yield return new object[] { 1.4f, 1.0f }; + yield return new object[] { 1.5f, 2.0f }; + yield return new object[] { 2e7f, 2e7f }; + yield return new object[] { -0.0f, -0.0f }; + yield return new object[] { -1.4f, -1.0f }; + yield return new object[] { -1.5f, -2.0f }; + yield return new object[] { -2e7f, -2e7f }; + } + } + + public static IEnumerable RoundAwayFromZeroDouble + { + get + { + yield return new object[] { 1, 1 }; + yield return new object[] { 0.5, 1 }; + yield return new object[] { 1.5, 2 }; + yield return new object[] { 2.5, 3 }; + yield return new object[] { 3.5, 4 }; + yield return new object[] { 0.49999999999999994, 0 }; + yield return new object[] { 1.5, 2 }; + yield return new object[] { 2.5, 3 }; + yield return new object[] { 3.5, 4 }; + yield return new object[] { 4.5, 5 }; + yield return new object[] { 3.141592653589793, 3 }; + yield return new object[] { 2.718281828459045, 3 }; + yield return new object[] { 1385.4557313670111, 1385 }; + yield return new object[] { 3423423.43432, 3423423 }; + yield return new object[] { 535345.5, 535346 }; + yield return new object[] { 535345.50001, 535346 }; + yield return new object[] { 535345.5, 535346 }; + yield return new object[] { 535345.4, 535345 }; + yield return new object[] { 535345.6, 535346 }; + yield return new object[] { -2.718281828459045, -3 }; + yield return new object[] { 10, 10 }; + yield return new object[] { -10, -10 }; + yield return new object[] { -0, -0 }; + yield return new object[] { 0, 0 }; + yield return new object[] { double.NaN, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { 1.7976931348623157E+308, 1.7976931348623157E+308 }; + yield return new object[] { -1.7976931348623157E+308, -1.7976931348623157E+308 }; + } + } + + public static IEnumerable RoundAwayFromZeroSingle + { + get + { + yield return new object[] { 1f, 1f }; + yield return new object[] { 0.5f, 1f }; + yield return new object[] { 1.5f, 2f }; + yield return new object[] { 2.5f, 3f }; + yield return new object[] { 3.5f, 4f }; + yield return new object[] { 0.49999997f, 0f }; + yield return new object[] { 1.5f, 2f }; + yield return new object[] { 2.5f, 3f }; + yield return new object[] { 3.5f, 4f }; + yield return new object[] { 4.5f, 5f }; + yield return new object[] { 3.1415927f, 3f }; + yield return new object[] { 2.7182817f, 3f }; + yield return new object[] { 1385.4557f, 1385f }; + yield return new object[] { 3423.4343f, 3423f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.4f, 535345f }; + yield return new object[] { 535345.6f, 535346f }; + yield return new object[] { -2.7182817f, -3f }; + yield return new object[] { 10f, 10f }; + yield return new object[] { -10f, -10f }; + yield return new object[] { -0f, -0f }; + yield return new object[] { 0f, 0f }; + yield return new object[] { float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { 3.4028235E+38f, 3.4028235E+38f }; + yield return new object[] { -3.4028235E+38f, -3.4028235E+38f }; + } + } + + public static IEnumerable RoundToEvenDouble + { + get + { + yield return new object[] { 1, 1 }; + yield return new object[] { 0.5, 0 }; + yield return new object[] { 1.5, 2 }; + yield return new object[] { 2.5, 2 }; + yield return new object[] { 3.5, 4 }; + + // Math.Round(var = 0.49999999999999994) returns 1 on ARM32 + if (!PlatformDetection.IsArmProcess) + yield return new object[] { 0.49999999999999994, 0 }; + + yield return new object[] { 1.5, 2 }; + yield return new object[] { 2.5, 2 }; + yield return new object[] { 3.5, 4 }; + yield return new object[] { 4.5, 4 }; + yield return new object[] { 3.141592653589793, 3 }; + yield return new object[] { 2.718281828459045, 3 }; + yield return new object[] { 1385.4557313670111, 1385 }; + yield return new object[] { 3423423.43432, 3423423 }; + yield return new object[] { 535345.5, 535346 }; + yield return new object[] { 535345.50001, 535346 }; + yield return new object[] { 535345.5, 535346 }; + yield return new object[] { 535345.4, 535345 }; + yield return new object[] { 535345.6, 535346 }; + yield return new object[] { -2.718281828459045, -3 }; + yield return new object[] { 10, 10 }; + yield return new object[] { -10, -10 }; + yield return new object[] { -0, -0 }; + yield return new object[] { 0, 0 }; + yield return new object[] { double.NaN, double.NaN }; + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { 1.7976931348623157E+308, 1.7976931348623157E+308 }; + yield return new object[] { -1.7976931348623157E+308, -1.7976931348623157E+308 }; + } + } + + public static IEnumerable RoundToEvenSingle + { + get + { + yield return new object[] { 1f, 1f }; + yield return new object[] { 0.5f, 0f }; + yield return new object[] { 1.5f, 2f }; + yield return new object[] { 2.5f, 2f }; + yield return new object[] { 3.5f, 4f }; + yield return new object[] { 0.49999997f, 0f }; + yield return new object[] { 1.5f, 2f }; + yield return new object[] { 2.5f, 2f }; + yield return new object[] { 3.5f, 4f }; + yield return new object[] { 4.5f, 4f }; + yield return new object[] { 3.1415927f, 3f }; + yield return new object[] { 2.7182817f, 3f }; + yield return new object[] { 1385.4557f, 1385f }; + yield return new object[] { 3423.4343f, 3423f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.4f, 535345f }; + yield return new object[] { 535345.6f, 535346f }; + yield return new object[] { -2.7182817f, -3f }; + yield return new object[] { 10f, 10f }; + yield return new object[] { -10f, -10f }; + yield return new object[] { -0f, -0f }; + yield return new object[] { 0f, 0f }; + yield return new object[] { float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { 3.4028235E+38f, 3.4028235E+38f }; + yield return new object[] { -3.4028235E+38f, -3.4028235E+38f }; + } + } + + public static IEnumerable TruncateDouble + { + get + { + yield return new object[] { 0.12345, 0.0f }; + yield return new object[] { 3.14159, 3.0f }; + yield return new object[] { -3.14159, -3.0f }; + } + } + + public static IEnumerable TruncateSingle + { + get + { + yield return new object[] { 0.12345f, 0.0f }; + yield return new object[] { 3.14159f, 3.0f }; + yield return new object[] { -3.14159f, -3.0f }; + } + } + } +} diff --git a/src/libraries/Common/tests/System/Runtime/Intrinsics/VectorTestMemberData.cs b/src/libraries/Common/tests/System/Runtime/Intrinsics/VectorTestMemberData.cs deleted file mode 100644 index ab2381a97967e..0000000000000 --- a/src/libraries/Common/tests/System/Runtime/Intrinsics/VectorTestMemberData.cs +++ /dev/null @@ -1,442 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; - -namespace System.Runtime.Intrinsics.Tests.Vectors -{ - internal static class VectorTestMemberData - { - // binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this - // is slightly too accurate when writing tests meant to run against libm implementations - // for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. - // - // The tests themselves will take CrossPlatformMachineEpsilon and adjust it according to the expected result - // so that the delta used for comparison will compare the most significant digits and ignore - // any digits that are outside the double precision range (15-17 digits). - // - // For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use - // CrossPlatformMachineEpsilon for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx - // will use CrossPlatformMachineEpsilon / 10 and expected result in the format of x.xxxxxxxxxxxxxxxx will - // use CrossPlatformMachineEpsilon * 10. - internal const double DoubleCrossPlatformMachineEpsilon = 8.8817841970012523e-16; - - // binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this - // is slightly too accurate when writing tests meant to run against libm implementations - // for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. - // - // The tests themselves will take CrossPlatformMachineEpsilon and adjust it according to the expected result - // so that the delta used for comparison will compare the most significant digits and ignore - // any digits that are outside the single precision range (6-9 digits). - // - // For example, a test with an expect result in the format of 0.xxxxxxxxx will use - // CrossPlatformMachineEpsilon for the variance, while an expected result in the format of 0.0xxxxxxxxx - // will use CrossPlatformMachineEpsilon / 10 and expected result in the format of x.xxxxxx will - // use CrossPlatformMachineEpsilon * 10. - private const float SingleCrossPlatformMachineEpsilon = 4.76837158e-07f; - - public static IEnumerable ExpDouble - { - get - { - yield return new object[] { double.NegativeInfinity, 0.0, 0.0 }; - yield return new object[] { -3.1415926535897932, 0.043213918263772250, DoubleCrossPlatformMachineEpsilon / 10 }; // value: -(pi) - yield return new object[] { -2.7182818284590452, 0.065988035845312537, DoubleCrossPlatformMachineEpsilon / 10 }; // value: -(e) - yield return new object[] { -2.3025850929940457, 0.1, DoubleCrossPlatformMachineEpsilon }; // value: -(ln(10)) - yield return new object[] { -1.5707963267948966, 0.20787957635076191, DoubleCrossPlatformMachineEpsilon }; // value: -(pi / 2) - yield return new object[] { -1.4426950408889634, 0.23629008834452270, DoubleCrossPlatformMachineEpsilon }; // value: -(log2(e)) - yield return new object[] { -1.4142135623730950, 0.24311673443421421, DoubleCrossPlatformMachineEpsilon }; // value: -(sqrt(2)) - yield return new object[] { -1.1283791670955126, 0.32355726390307110, DoubleCrossPlatformMachineEpsilon }; // value: -(2 / sqrt(pi)) - yield return new object[] { -1.0, 0.36787944117144232, DoubleCrossPlatformMachineEpsilon }; - yield return new object[] { -0.78539816339744831, 0.45593812776599624, DoubleCrossPlatformMachineEpsilon }; // value: -(pi / 4) - yield return new object[] { -0.70710678118654752, 0.49306869139523979, DoubleCrossPlatformMachineEpsilon }; // value: -(1 / sqrt(2)) - yield return new object[] { -0.69314718055994531, 0.5, 0.0 }; // value: -(ln(2)) - yield return new object[] { -0.63661977236758134, 0.52907780826773535, DoubleCrossPlatformMachineEpsilon }; // value: -(2 / pi) - yield return new object[] { -0.43429448190325183, 0.64772148514180065, DoubleCrossPlatformMachineEpsilon }; // value: -(log10(e)) - yield return new object[] { -0.31830988618379067, 0.72737734929521647, DoubleCrossPlatformMachineEpsilon }; // value: -(1 / pi) - yield return new object[] { -0.0, 1.0, 0.0 }; - yield return new object[] { double.NaN, double.NaN, 0.0 }; - yield return new object[] { 0.0, 1.0, 0.0 }; - yield return new object[] { 0.31830988618379067, 1.3748022274393586, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi) - yield return new object[] { 0.43429448190325183, 1.5438734439711811, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e)) - yield return new object[] { 0.63661977236758134, 1.8900811645722220, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (2 / pi) - yield return new object[] { 0.69314718055994531, 2.0, 0.0 }; // value: (ln(2)) - yield return new object[] { 0.70710678118654752, 2.0281149816474725, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (1 / sqrt(2)) - yield return new object[] { 0.78539816339744831, 2.1932800507380155, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 4) - yield return new object[] { 1.0, 2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 1.1283791670955126, 3.0906430223107976, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (2 / sqrt(pi)) - yield return new object[] { 1.4142135623730950, 4.1132503787829275, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (sqrt(2)) - yield return new object[] { 1.4426950408889634, 4.2320861065570819, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (log2(e)) - yield return new object[] { 1.5707963267948966, 4.8104773809653517, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 2) - yield return new object[] { 2.3025850929940457, 10.0, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (ln(10)) - yield return new object[] { 2.7182818284590452, 15.154262241479264, DoubleCrossPlatformMachineEpsilon * 100 }; // value: (e) - yield return new object[] { 3.1415926535897932, 23.140692632779269, DoubleCrossPlatformMachineEpsilon * 100 }; // value: (pi) - yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; - } - } - - public static IEnumerable ExpSingle - { - get - { - yield return new object[] { float.NegativeInfinity, 0.0f, 0.0f }; - yield return new object[] { -3.14159265f, 0.0432139183f, SingleCrossPlatformMachineEpsilon / 10 }; // value: -(pi) - yield return new object[] { -2.71828183f, 0.0659880358f, SingleCrossPlatformMachineEpsilon / 10 }; // value: -(e) - yield return new object[] { -2.30258509f, 0.1f, SingleCrossPlatformMachineEpsilon }; // value: -(ln(10)) - yield return new object[] { -1.57079633f, 0.207879576f, SingleCrossPlatformMachineEpsilon }; // value: -(pi / 2) - yield return new object[] { -1.44269504f, 0.236290088f, SingleCrossPlatformMachineEpsilon }; // value: -(log2(e)) - yield return new object[] { -1.41421356f, 0.243116734f, SingleCrossPlatformMachineEpsilon }; // value: -(sqrt(2)) - yield return new object[] { -1.12837917f, 0.323557264f, SingleCrossPlatformMachineEpsilon }; // value: -(2 / sqrt(pi)) - yield return new object[] { -1.0f, 0.367879441f, SingleCrossPlatformMachineEpsilon }; - yield return new object[] { -0.785398163f, 0.455938128f, SingleCrossPlatformMachineEpsilon }; // value: -(pi / 4) - yield return new object[] { -0.707106781f, 0.493068691f, SingleCrossPlatformMachineEpsilon }; // value: -(1 / sqrt(2)) - yield return new object[] { -0.693147181f, 0.5f, SingleCrossPlatformMachineEpsilon }; // value: -(ln(2)) - yield return new object[] { -0.636619772f, 0.529077808f, SingleCrossPlatformMachineEpsilon }; // value: -(2 / pi) - yield return new object[] { -0.434294482f, 0.647721485f, SingleCrossPlatformMachineEpsilon }; // value: -(log10(e)) - yield return new object[] { -0.318309886f, 0.727377349f, SingleCrossPlatformMachineEpsilon }; // value: -(1 / pi) - yield return new object[] { -0.0f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; - yield return new object[] { float.NaN, float.NaN, 0.0f }; - yield return new object[] { 0.0f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; - yield return new object[] { 0.318309886f, 1.37480223f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi) - yield return new object[] { 0.434294482f, 1.54387344f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e)) - yield return new object[] { 0.636619772f, 1.89008116f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (2 / pi) - yield return new object[] { 0.693147181f, 2.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (ln(2)) - yield return new object[] { 0.707106781f, 2.02811498f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (1 / sqrt(2)) - yield return new object[] { 0.785398163f, 2.19328005f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 4) - yield return new object[] { 1.0f, 2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 1.12837917f, 3.09064302f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (2 / sqrt(pi)) - yield return new object[] { 1.41421356f, 4.11325038f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (sqrt(2)) - yield return new object[] { 1.44269504f, 4.23208611f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (log2(e)) - yield return new object[] { 1.57079633f, 4.81047738f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 2) - yield return new object[] { 2.30258509f, 10.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (ln(10)) - yield return new object[] { 2.71828183f, 15.1542622f, SingleCrossPlatformMachineEpsilon * 100 }; // value: (e) - yield return new object[] { 3.14159265f, 23.1406926f, SingleCrossPlatformMachineEpsilon * 100 }; // value: (pi) - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; - } - } - - public static IEnumerable LogDouble - { - get - { - yield return new object[] { double.NegativeInfinity, double.NaN, 0.0 }; - yield return new object[] { -3.1415926535897932, double.NaN, 0.0 }; // value: -(pi) - yield return new object[] { -2.7182818284590452, double.NaN, 0.0 }; // value: -(e) - yield return new object[] { -1.4142135623730950, double.NaN, 0.0 }; // value: -(sqrt(2)) - yield return new object[] { -1.0, double.NaN, 0.0 }; - yield return new object[] { -0.69314718055994531, double.NaN, 0.0 }; // value: -(ln(2)) - yield return new object[] { -0.43429448190325183, double.NaN, 0.0 }; // value: -(log10(e)) - yield return new object[] { -0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] { double.NaN, double.NaN, 0.0 }; - yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] { 0.043213918263772250, -3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) - yield return new object[] { 0.065988035845312537, -2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) - yield return new object[] { 0.1, -2.3025850929940457, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) - yield return new object[] { 0.20787957635076191, -1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) - yield return new object[] { 0.23629008834452270, -1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) - yield return new object[] { 0.24311673443421421, -1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) - yield return new object[] { 0.32355726390307110, -1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) - yield return new object[] { 0.36787944117144232, -1.0, 0.0f }; - yield return new object[] { 0.45593812776599624, -0.78539816339744831, DoubleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) - yield return new object[] { 0.49306869139523979, -0.70710678118654752, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) - yield return new object[] { 0.5, -0.69314718055994531, DoubleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) - yield return new object[] { 0.52907780826773535, -0.63661977236758134, DoubleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) - yield return new object[] { 0.64772148514180065, -0.43429448190325183, DoubleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) - yield return new object[] { 0.72737734929521647, -0.31830988618379067, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) - yield return new object[] { 1.0, 0.0, 0.0 }; - yield return new object[] { 1.3748022274393586, 0.31830988618379067, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / pi) - yield return new object[] { 1.5438734439711811, 0.43429448190325183, DoubleCrossPlatformMachineEpsilon }; // expected: (log10(e)) - yield return new object[] { 1.8900811645722220, 0.63661977236758134, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / pi) - yield return new object[] { 2.0, 0.69314718055994531, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(2)) - yield return new object[] { 2.0281149816474725, 0.70710678118654752, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) - yield return new object[] { 2.1932800507380155, 0.78539816339744831, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 4) - yield return new object[] { 2.7182818284590452, 1.0, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (e) - yield return new object[] { 3.0906430223107976, 1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) - yield return new object[] { 4.1132503787829275, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) - yield return new object[] { 4.2320861065570819, 1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) - yield return new object[] { 4.8104773809653517, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) - yield return new object[] { 10.0, 2.3025850929940457, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) - yield return new object[] { 15.154262241479264, 2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 23.140692632779269, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) - yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; - } - } - - public static IEnumerable LogSingle - { - get - { - yield return new object[] { float.NegativeInfinity, float.NaN, 0.0f }; - yield return new object[] { -3.14159265f, float.NaN, 0.0f }; // value: -(pi) - yield return new object[] { -2.71828183f, float.NaN, 0.0f }; // value: -(e) - yield return new object[] { -1.41421356f, float.NaN, 0.0f }; // value: -(sqrt(2)) - yield return new object[] { -1.0f, float.NaN, 0.0f }; - yield return new object[] { -0.693147181f, float.NaN, 0.0f }; // value: -(ln(2)) - yield return new object[] { -0.434294482f, float.NaN, 0.0f }; // value: -(log10(e)) - yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { float.NaN, float.NaN, 0.0f }; - yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { 0.0432139183f, -3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) - yield return new object[] { 0.0659880358f, -2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) - yield return new object[] { 0.1f, -2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) - yield return new object[] { 0.207879576f, -1.57079633f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) - yield return new object[] { 0.236290088f, -1.44269504f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) - yield return new object[] { 0.243116734f, -1.41421356f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) - yield return new object[] { 0.323557264f, -1.12837917f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) - yield return new object[] { 0.367879441f, -1.0f, 0.0f }; - yield return new object[] { 0.455938128f, -0.785398163f, SingleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) - yield return new object[] { 0.493068691f, -0.707106781f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) - yield return new object[] { 0.5f, -0.693147181f, SingleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) - yield return new object[] { 0.529077808f, -0.636619772f, SingleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) - yield return new object[] { 0.647721485f, -0.434294482f, SingleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) - yield return new object[] { 0.727377349f, -0.318309886f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) - yield return new object[] { 1.0f, 0.0f, 0.0f }; - yield return new object[] { 1.37480223f, 0.318309886f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / pi) - yield return new object[] { 1.54387344f, 0.434294482f, SingleCrossPlatformMachineEpsilon }; // expected: (log10(e)) - yield return new object[] { 1.89008116f, 0.636619772f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / pi) - yield return new object[] { 2.0f, 0.693147181f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(2)) - yield return new object[] { 2.02811498f, 0.707106781f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) - yield return new object[] { 2.19328005f, 0.785398163f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 4) - yield return new object[] { 2.71828183f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (e) - yield return new object[] { 3.09064302f, 1.12837917f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) - yield return new object[] { 4.11325038f, 1.41421356f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) - yield return new object[] { 4.23208611f, 1.44269504f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) - yield return new object[] { 4.81047738f, 1.57079633f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) - yield return new object[] { 10.0f, 2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) - yield return new object[] { 15.1542622f, 2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 23.1406926f, 3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; - } - } - - public static IEnumerable Log2Double - { - get - { - yield return new object[] { double.NegativeInfinity, double.NaN, 0.0 }; - yield return new object[] {-0.11331473229676087, double.NaN, 0.0 }; - yield return new object[] {-0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] { double.NaN, double.NaN, 0.0 }; - yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] { 0.11331473229676087, -3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) - yield return new object[] { 0.15195522325791297, -2.7182818284590453, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) - yield return new object[] { 0.20269956628651730, -2.3025850929940460, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) - yield return new object[] { 0.33662253682241906, -1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) - yield return new object[] { 0.36787944117144232, -1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) - yield return new object[] { 0.37521422724648177, -1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) - yield return new object[] { 0.45742934732229695, -1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) - yield return new object[] { 0.5, -1.0, 0.0f }; - yield return new object[] { 0.58019181037172444, -0.78539816339744840, DoubleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) - yield return new object[] { 0.61254732653606592, -0.70710678118654750, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) - yield return new object[] { 0.61850313780157598, -0.69314718055994537, DoubleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) - yield return new object[] { 0.64321824193300488, -0.63661977236758126, DoubleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) - yield return new object[] { 0.74005557395545179, -0.43429448190325190, DoubleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) - yield return new object[] { 0.80200887896145195, -0.31830988618379073, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) - yield return new object[] { 1, 0.0, 0.0 }; - yield return new object[] { 1.2468689889006383, 0.31830988618379073, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / pi) - yield return new object[] { 1.3512498725672678, 0.43429448190325226, DoubleCrossPlatformMachineEpsilon }; // expected: (log10(e)) - yield return new object[] { 1.5546822754821001, 0.63661977236758126, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / pi) - yield return new object[] { 1.6168066722416747, 0.69314718055994537, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(2)) - yield return new object[] { 1.6325269194381528, 0.70710678118654750, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) - yield return new object[] { 1.7235679341273495, 0.78539816339744830, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 4) - yield return new object[] { 2, 1.0, 0.0 }; // value: (e) - yield return new object[] { 2.1861299583286618, 1.1283791670955128, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) - yield return new object[] { 2.6651441426902252, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) - yield return new object[] { 2.7182818284590452, 1.4426950408889632, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) - yield return new object[] { 2.9706864235520193, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) - yield return new object[] { 4.9334096679145963, 2.3025850929940460, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) - yield return new object[] { 6.5808859910179210, 2.7182818284590455, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 8.8249778270762876, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) - yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; - } - } - - public static IEnumerable Log2Single - { - get - { - yield return new object[] { float.NegativeInfinity, float.NaN, 0.0f }; - yield return new object[] { -0.113314732f, float.NaN, 0.0f }; - yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { float.NaN, float.NaN, 0.0f }; - yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { 0.113314732f, -3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) - yield return new object[] { 0.151955223f, -2.71828200f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) - yield return new object[] { 0.202699566f, -2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) - yield return new object[] { 0.336622537f, -1.57079630f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) - yield return new object[] { 0.367879441f, -1.44269500f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) - yield return new object[] { 0.375214227f, -1.41421360f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) - yield return new object[] { 0.457429347f, -1.12837910f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) - yield return new object[] { 0.5f, -1.0f, 0.0f }; - yield return new object[] { 0.580191810f, -0.785398211f, SingleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) - yield return new object[] { 0.612547327f, -0.707106700f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) - yield return new object[] { 0.618503138f, -0.693147144f, SingleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) - yield return new object[] { 0.643218242f, -0.636619823f, SingleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) - yield return new object[] { 0.740055574f, -0.434294550f, SingleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) - yield return new object[] { 0.802008879f, -0.318309900f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) - yield return new object[] { 1, 0.0f, 0.0f }; - yield return new object[] { 1.24686899f, 0.318309870f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / pi) - yield return new object[] { 1.35124987f, 0.434294340f, SingleCrossPlatformMachineEpsilon }; // expected: (log10(e)) - yield return new object[] { 1.55468228f, 0.636619823f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / pi) - yield return new object[] { 1.61680667f, 0.693147144f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(2)) - yield return new object[] { 1.63252692f, 0.707106700f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) - yield return new object[] { 1.72356793f, 0.785398211f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 4) - yield return new object[] { 2, 1.0f, 0.0f }; // value: (e) - yield return new object[] { 2.18612996f, 1.12837920f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) - yield return new object[] { 2.66514414f, 1.41421360f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) - yield return new object[] { 2.71828183f, 1.44269490f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) - yield return new object[] { 2.97068642f, 1.57079630f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) - yield return new object[] { 4.93340967f, 2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) - yield return new object[] { 6.58088599f, 2.71828170f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 8.82497783f, 3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; - } - } - - public static IEnumerable MultiplyAddDouble - { - get - { - yield return new object[] { double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity }; - yield return new object[] { double.NegativeInfinity, -0.0, double.NegativeInfinity }; - yield return new object[] { double.NegativeInfinity, -0.0, -3.1415926535897932 }; - yield return new object[] { double.NegativeInfinity, -0.0, -0.0 }; - yield return new object[] { double.NegativeInfinity, -0.0, double.NaN }; - yield return new object[] { double.NegativeInfinity, -0.0, 0.0 }; - yield return new object[] { double.NegativeInfinity, -0.0, 3.1415926535897932 }; - yield return new object[] { double.NegativeInfinity, -0.0, double.PositiveInfinity }; - yield return new object[] { double.NegativeInfinity, 0.0, double.NegativeInfinity }; - yield return new object[] { double.NegativeInfinity, 0.0, -3.1415926535897932 }; - yield return new object[] { double.NegativeInfinity, 0.0, -0.0 }; - yield return new object[] { double.NegativeInfinity, 0.0, double.NaN }; - yield return new object[] { double.NegativeInfinity, 0.0, 0.0 }; - yield return new object[] { double.NegativeInfinity, 0.0, 3.1415926535897932 }; - yield return new object[] { double.NegativeInfinity, 0.0, double.PositiveInfinity }; - yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity }; - yield return new object[] {-1e308, 2.0, 1e308 }; - yield return new object[] {-1e308, 2.0, double.PositiveInfinity }; - yield return new object[] {-5, 4, -3 }; - yield return new object[] {-0.0, double.NegativeInfinity, double.NegativeInfinity }; - yield return new object[] {-0.0, double.NegativeInfinity, -3.1415926535897932 }; - yield return new object[] {-0.0, double.NegativeInfinity, -0.0 }; - yield return new object[] {-0.0, double.NegativeInfinity, double.NaN }; - yield return new object[] {-0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] {-0.0, double.NegativeInfinity, 3.1415926535897932 }; - yield return new object[] {-0.0, double.NegativeInfinity, double.PositiveInfinity }; - yield return new object[] {-0.0, double.PositiveInfinity, double.NegativeInfinity }; - yield return new object[] {-0.0, double.PositiveInfinity, -3.1415926535897932 }; - yield return new object[] {-0.0, double.PositiveInfinity, -0.0 }; - yield return new object[] {-0.0, double.PositiveInfinity, double.NaN }; - yield return new object[] {-0.0, double.PositiveInfinity, 0.0 }; - yield return new object[] {-0.0, double.PositiveInfinity, 3.1415926535897932 }; - yield return new object[] {-0.0, double.PositiveInfinity, double.PositiveInfinity }; - yield return new object[] { 0.0, double.NegativeInfinity, double.NegativeInfinity }; - yield return new object[] { 0.0, double.NegativeInfinity, -3.1415926535897932 }; - yield return new object[] { 0.0, double.NegativeInfinity, -0.0 }; - yield return new object[] { 0.0, double.NegativeInfinity, double.NaN }; - yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] { 0.0, double.NegativeInfinity, 3.1415926535897932 }; - yield return new object[] { 0.0, double.NegativeInfinity, double.PositiveInfinity }; - yield return new object[] { 0.0, double.PositiveInfinity, double.NegativeInfinity }; - yield return new object[] { 0.0, double.PositiveInfinity, -3.1415926535897932 }; - yield return new object[] { 0.0, double.PositiveInfinity, -0.0 }; - yield return new object[] { 0.0, double.PositiveInfinity, double.NaN }; - yield return new object[] { 0.0, double.PositiveInfinity, 0.0 }; - yield return new object[] { 0.0, double.PositiveInfinity, 3.1415926535897932 }; - yield return new object[] { 0.0, double.PositiveInfinity, double.PositiveInfinity }; - yield return new object[] { 5, 4, 3 }; - yield return new object[] { 1e308, 2.0, -1e308 }; - yield return new object[] { 1e308, 2.0, double.NegativeInfinity }; - yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity }; - yield return new object[] { double.PositiveInfinity, -0.0, double.NegativeInfinity }; - yield return new object[] { double.PositiveInfinity, -0.0, -3.1415926535897932 }; - yield return new object[] { double.PositiveInfinity, -0.0, -0.0 }; - yield return new object[] { double.PositiveInfinity, -0.0, double.NaN }; - yield return new object[] { double.PositiveInfinity, -0.0, 0.0 }; - yield return new object[] { double.PositiveInfinity, -0.0, 3.1415926535897932 }; - yield return new object[] { double.PositiveInfinity, -0.0, double.PositiveInfinity }; - yield return new object[] { double.PositiveInfinity, 0.0, double.NegativeInfinity }; - yield return new object[] { double.PositiveInfinity, 0.0, -3.1415926535897932 }; - yield return new object[] { double.PositiveInfinity, 0.0, -0.0 }; - yield return new object[] { double.PositiveInfinity, 0.0, double.NaN }; - yield return new object[] { double.PositiveInfinity, 0.0, 0.0 }; - yield return new object[] { double.PositiveInfinity, 0.0, 3.1415926535897932 }; - yield return new object[] { double.PositiveInfinity, 0.0, double.PositiveInfinity }; - yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, double.NegativeInfinity }; - } - } - - public static IEnumerable MultiplyAddSingle - { - get - { - yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity }; - yield return new object[] { float.NegativeInfinity, -0.0f, float.NegativeInfinity }; - yield return new object[] { float.NegativeInfinity, -0.0f, -3.14159265f }; - yield return new object[] { float.NegativeInfinity, -0.0f, -0.0f }; - yield return new object[] { float.NegativeInfinity, -0.0f, float.NaN }; - yield return new object[] { float.NegativeInfinity, -0.0f, 0.0f }; - yield return new object[] { float.NegativeInfinity, -0.0f, 3.14159265f }; - yield return new object[] { float.NegativeInfinity, -0.0f, float.PositiveInfinity }; - yield return new object[] { float.NegativeInfinity, 0.0f, float.NegativeInfinity }; - yield return new object[] { float.NegativeInfinity, 0.0f, -3.14159265f }; - yield return new object[] { float.NegativeInfinity, 0.0f, -0.0f }; - yield return new object[] { float.NegativeInfinity, 0.0f, float.NaN }; - yield return new object[] { float.NegativeInfinity, 0.0f, 0.0f }; - yield return new object[] { float.NegativeInfinity, 0.0f, 3.14159265f }; - yield return new object[] { float.NegativeInfinity, 0.0f, float.PositiveInfinity }; - yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity }; - yield return new object[] { -1e38f, 2.0f, 1e38f }; - yield return new object[] { -1e38f, 2.0f, float.PositiveInfinity }; - yield return new object[] { -5, 4, -3 }; - yield return new object[] { -0.0f, float.NegativeInfinity, float.NegativeInfinity }; - yield return new object[] { -0.0f, float.NegativeInfinity, -3.14159265f }; - yield return new object[] { -0.0f, float.NegativeInfinity, -0.0f }; - yield return new object[] { -0.0f, float.NegativeInfinity, float.NaN }; - yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { -0.0f, float.NegativeInfinity, 3.14159265f }; - yield return new object[] { -0.0f, float.NegativeInfinity, float.PositiveInfinity }; - yield return new object[] { -0.0f, float.PositiveInfinity, float.NegativeInfinity }; - yield return new object[] { -0.0f, float.PositiveInfinity, -3.14159265f }; - yield return new object[] { -0.0f, float.PositiveInfinity, -0.0f }; - yield return new object[] { -0.0f, float.PositiveInfinity, float.NaN }; - yield return new object[] { -0.0f, float.PositiveInfinity, 0.0f }; - yield return new object[] { -0.0f, float.PositiveInfinity, 3.14159265f }; - yield return new object[] { -0.0f, float.PositiveInfinity, float.PositiveInfinity }; - yield return new object[] { 0.0f, float.NegativeInfinity, float.NegativeInfinity }; - yield return new object[] { 0.0f, float.NegativeInfinity, -3.14159265f }; - yield return new object[] { 0.0f, float.NegativeInfinity, -0.0f }; - yield return new object[] { 0.0f, float.NegativeInfinity, float.NaN }; - yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { 0.0f, float.NegativeInfinity, 3.14159265f }; - yield return new object[] { 0.0f, float.NegativeInfinity, float.PositiveInfinity }; - yield return new object[] { 0.0f, float.PositiveInfinity, float.NegativeInfinity }; - yield return new object[] { 0.0f, float.PositiveInfinity, -3.14159265f }; - yield return new object[] { 0.0f, float.PositiveInfinity, -0.0f }; - yield return new object[] { 0.0f, float.PositiveInfinity, float.NaN }; - yield return new object[] { 0.0f, float.PositiveInfinity, 0.0f }; - yield return new object[] { 0.0f, float.PositiveInfinity, 3.14159265f }; - yield return new object[] { 0.0f, float.PositiveInfinity, float.PositiveInfinity }; - yield return new object[] { 5, 4, 3 }; - yield return new object[] { 1e38f, 2.0f, -1e38f }; - yield return new object[] { 1e38f, 2.0f, float.NegativeInfinity }; - yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity }; - yield return new object[] { float.PositiveInfinity, -0.0f, float.NegativeInfinity }; - yield return new object[] { float.PositiveInfinity, -0.0f, -3.14159265f }; - yield return new object[] { float.PositiveInfinity, -0.0f, -0.0f }; - yield return new object[] { float.PositiveInfinity, -0.0f, float.NaN }; - yield return new object[] { float.PositiveInfinity, -0.0f, 0.0f }; - yield return new object[] { float.PositiveInfinity, -0.0f, 3.14159265f }; - yield return new object[] { float.PositiveInfinity, -0.0f, float.PositiveInfinity }; - yield return new object[] { float.PositiveInfinity, 0.0f, float.NegativeInfinity }; - yield return new object[] { float.PositiveInfinity, 0.0f, -3.14159265f }; - yield return new object[] { float.PositiveInfinity, 0.0f, -0.0f }; - yield return new object[] { float.PositiveInfinity, 0.0f, float.NaN }; - yield return new object[] { float.PositiveInfinity, 0.0f, 0.0f }; - yield return new object[] { float.PositiveInfinity, 0.0f, 3.14159265f }; - yield return new object[] { float.PositiveInfinity, 0.0f, float.PositiveInfinity }; - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity }; - } - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj index eecc04252e242..b653420933405 100644 --- a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj +++ b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj @@ -99,9 +99,11 @@ + + diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Single.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Single.cs index ae6df0ed43f5c..96150e89108aa 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Single.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Single.cs @@ -440,7 +440,7 @@ public static float Max(ReadOnlySpan x) => /// /// public static void Max(ReadOnlySpan x, ReadOnlySpan y, Span destination) => - InvokeSpanSpanIntoSpan(x, y, destination); + InvokeSpanSpanIntoSpan(x, y, destination); /// Searches for the single-precision floating-point number with the largest magnitude in the specified tensor. /// The tensor, represented as a span. @@ -476,7 +476,7 @@ public static float MaxMagnitude(ReadOnlySpan x) => /// /// public static void MaxMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span destination) => - InvokeSpanSpanIntoSpan(x, y, destination); + InvokeSpanSpanIntoSpan(x, y, destination); /// Searches for the smallest single-precision floating-point number in the specified tensor. /// The tensor, represented as a span. @@ -517,7 +517,7 @@ public static float Min(ReadOnlySpan x) => /// /// public static void Min(ReadOnlySpan x, ReadOnlySpan y, Span destination) => - InvokeSpanSpanIntoSpan(x, y, destination); + InvokeSpanSpanIntoSpan(x, y, destination); /// Searches for the single-precision floating-point number with the smallest magnitude in the specified tensor. /// The tensor, represented as a span. @@ -558,7 +558,7 @@ public static float MinMagnitude(ReadOnlySpan x) => /// /// public static void MinMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span destination) => - InvokeSpanSpanIntoSpan(x, y, destination); + InvokeSpanSpanIntoSpan(x, y, destination); /// Computes the element-wise product of single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.CopySign.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.CopySign.cs index 0277c729a17aa..e914e271bd015 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.CopySign.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.CopySign.cs @@ -47,6 +47,9 @@ public static void CopySign(ReadOnlySpan x, T sign, Span destination) public static Vector128 Invoke(Vector128 x, Vector128 y) { +#if NET9_0_OR_GREATER + return Vector128.CopySign(x, y); +#else if (typeof(T) == typeof(float)) { return Vector128.ConditionalSelect(Vector128.Create(-0.0f).As(), y, x); @@ -71,10 +74,14 @@ public static Vector128 Invoke(Vector128 x, Vector128 y) } return x; +#endif } public static Vector256 Invoke(Vector256 x, Vector256 y) { +#if NET9_0_OR_GREATER + return Vector256.CopySign(x, y); +#else if (typeof(T) == typeof(float)) { return Vector256.ConditionalSelect(Vector256.Create(-0.0f).As(), y, x); @@ -99,10 +106,14 @@ public static Vector256 Invoke(Vector256 x, Vector256 y) } return x; +#endif } public static Vector512 Invoke(Vector512 x, Vector512 y) { +#if NET9_0_OR_GREATER + return Vector512.CopySign(x, y); +#else if (typeof(T) == typeof(float)) { return Vector512.ConditionalSelect(Vector512.Create(-0.0f).As(), y, x); @@ -127,6 +138,7 @@ public static Vector512 Invoke(Vector512 x, Vector512 y) } return x; +#endif } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.DegreesToRadians.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.DegreesToRadians.cs index 27d11cf14ce72..bf21253c4436a 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.DegreesToRadians.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.DegreesToRadians.cs @@ -1,6 +1,7 @@ // 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.Intrinsics; namespace System.Numerics.Tensors @@ -25,10 +26,59 @@ public static void DegreesToRadians(ReadOnlySpan x, Span destination) private readonly struct DegreesToRadiansOperator : IUnaryOperator where T : ITrigonometricFunctions { public static bool Vectorizable => true; + public static T Invoke(T x) => T.DegreesToRadians(x); - public static Vector128 Invoke(Vector128 x) => (x * T.Pi) / T.CreateChecked(180); - public static Vector256 Invoke(Vector256 x) => (x * T.Pi) / T.CreateChecked(180); - public static Vector512 Invoke(Vector512 x) => (x * T.Pi) / T.CreateChecked(180); + + public static Vector128 Invoke(Vector128 x) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector128.DegreesToRadians(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector128.DegreesToRadians(x.AsSingle()).As(); + } +#else + return (x * T.Pi) / T.CreateChecked(180); +#endif + } + + public static Vector256 Invoke(Vector256 x) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector256.DegreesToRadians(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector256.DegreesToRadians(x.AsSingle()).As(); + } +#else + return (x * T.Pi) / T.CreateChecked(180); +#endif + } + + public static Vector512 Invoke(Vector512 x) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector512.DegreesToRadians(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector512.DegreesToRadians(x.AsSingle()).As(); + } +#else + return (x * T.Pi) / T.CreateChecked(180); +#endif + } } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Hypot.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Hypot.cs index f0c46347ac244..c806856672f90 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Hypot.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Hypot.cs @@ -1,6 +1,7 @@ // 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.Intrinsics; namespace System.Numerics.Tensors @@ -29,10 +30,59 @@ public static void Hypot(ReadOnlySpan x, ReadOnlySpan y, Span destin where T : IRootFunctions { public static bool Vectorizable => true; + public static T Invoke(T x, T y) => T.Hypot(x, y); - public static Vector128 Invoke(Vector128 x, Vector128 y) => Vector128.Sqrt((x * x) + (y * y)); - public static Vector256 Invoke(Vector256 x, Vector256 y) => Vector256.Sqrt((x * x) + (y * y)); - public static Vector512 Invoke(Vector512 x, Vector512 y) => Vector512.Sqrt((x * x) + (y * y)); + + public static Vector128 Invoke(Vector128 x, Vector128 y) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector128.Hypot(x.AsDouble(), y.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector128.Hypot(x.AsSingle(), y.AsSingle()).As(); + } +#else + return Vector128.Sqrt((x * x) + (y * y)); +#endif + } + + public static Vector256 Invoke(Vector256 x, Vector256 y) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector256.Hypot(x.AsDouble(), y.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector256.Hypot(x.AsSingle(), y.AsSingle()).As(); + } +#else + return Vector256.Sqrt((x * x) + (y * y)); +#endif + } + + public static Vector512 Invoke(Vector512 x, Vector512 y) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector512.Hypot(x.AsDouble(), y.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector512.Hypot(x.AsSingle(), y.AsSingle()).As(); + } +#else + return Vector512.Sqrt((x * x) + (y * y)); +#endif + } } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Lerp.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Lerp.cs index a605b62430d3f..f4acf4adbe029 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Lerp.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Lerp.cs @@ -1,6 +1,7 @@ // 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.Intrinsics; namespace System.Numerics.Tensors @@ -75,9 +76,57 @@ public static void Lerp(ReadOnlySpan x, T y, ReadOnlySpan amount, Span< private readonly struct LerpOperator : ITernaryOperator where T : IFloatingPointIeee754 { public static T Invoke(T x, T y, T amount) => T.Lerp(x, y, amount); - public static Vector128 Invoke(Vector128 x, Vector128 y, Vector128 amount) => (x * (Vector128.One - amount)) + (y * amount); - public static Vector256 Invoke(Vector256 x, Vector256 y, Vector256 amount) => (x * (Vector256.One - amount)) + (y * amount); - public static Vector512 Invoke(Vector512 x, Vector512 y, Vector512 amount) => (x * (Vector512.One - amount)) + (y * amount); + + public static Vector128 Invoke(Vector128 x, Vector128 y, Vector128 amount) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector128.Lerp(x.AsDouble(), y.AsDouble(), amount.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector128.Lerp(x.AsSingle(), y.AsSingle(), amount.AsSingle()).As(); + } +#else + return MultiplyAddEstimateOperator.Invoke(x, Vector128.One - amount, y * amount); +#endif + } + + public static Vector256 Invoke(Vector256 x, Vector256 y, Vector256 amount) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector256.Lerp(x.AsDouble(), y.AsDouble(), amount.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector256.Lerp(x.AsSingle(), y.AsSingle(), amount.AsSingle()).As(); + } +#else + return MultiplyAddEstimateOperator.Invoke(x, Vector256.One - amount, y * amount); +#endif + } + + public static Vector512 Invoke(Vector512 x, Vector512 y, Vector512 amount) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector512.Lerp(x.AsDouble(), y.AsDouble(), amount.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector512.Lerp(x.AsSingle(), y.AsSingle(), amount.AsSingle()).As(); + } +#else + return MultiplyAddEstimateOperator.Invoke(x, Vector512.One - amount, y * amount); +#endif + } } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs index 2e760e30fb7c6..c939936c69804 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs @@ -1,6 +1,7 @@ // 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.InteropServices; using System.Runtime.Intrinsics; @@ -51,7 +52,7 @@ public static T Max(ReadOnlySpan x) /// public static void Max(ReadOnlySpan x, ReadOnlySpan y, Span destination) where T : INumber => - InvokeSpanSpanIntoSpan>(x, y, destination); + InvokeSpanSpanIntoSpan>(x, y, destination); /// Computes the element-wise maximum of the numbers in the specified tensors. /// The first tensor, represented as a span. @@ -74,45 +75,30 @@ public static void Max(ReadOnlySpan x, ReadOnlySpan y, Span destinat /// public static void Max(ReadOnlySpan x, T y, Span destination) where T : INumber => - InvokeSpanScalarIntoSpan>(x, y, destination); + InvokeSpanScalarIntoSpan>(x, y, destination); - /// T.Max(x, y) (but NaNs may not be propagated) - internal readonly struct MaxOperator : IAggregationOperator where T : INumber + /// Max(x, y) + internal readonly struct MaxOperator : IAggregationOperator + where T : INumber { public static bool Vectorizable => true; - public static T Invoke(T x, T y) - { - if (typeof(T) == typeof(Half) || typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - return x == y ? - (IsNegative(x) ? y : x) : - (y > x ? y : x); - } - - return T.Max(x, y); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Invoke(T x, T y) => T.Max(x, y); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if !NET9_0_OR_GREATER + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - if (AdvSimd.IsSupported && typeof(T) == typeof(float)) - { - return AdvSimd.Max(x.AsSingle(), y.AsSingle()).As(); - } - - if (AdvSimd.Arm64.IsSupported && typeof(T) == typeof(double)) - { - return AdvSimd.Arm64.Max(x.AsDouble(), y.AsDouble()).As(); - } - - return - Vector128.ConditionalSelect(Vector128.Equals(x, y), - Vector128.ConditionalSelect(IsNegative(x), y, x), - Vector128.Max(x, y)); + return Vector128.ConditionalSelect( + Vector128.LessThan(y, x) | IsNaN(x) | (Vector128.Equals(x, y) & IsNegative(y)), + x, + y + ); } +#endif return Vector128.Max(x, y); } @@ -120,13 +106,16 @@ public static Vector128 Invoke(Vector128 x, Vector128 y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Invoke(Vector256 x, Vector256 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if !NET9_0_OR_GREATER + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - return - Vector256.ConditionalSelect(Vector256.Equals(x, y), - Vector256.ConditionalSelect(IsNegative(x), y, x), - Vector256.Max(x, y)); + return Vector256.ConditionalSelect( + Vector256.LessThan(y, x) | IsNaN(x) | (Vector256.Equals(x, y) & IsNegative(y)), + x, + y + ); } +#endif return Vector256.Max(x, y); } @@ -134,13 +123,16 @@ public static Vector256 Invoke(Vector256 x, Vector256 y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Invoke(Vector512 x, Vector512 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if !NET9_0_OR_GREATER + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - return - Vector512.ConditionalSelect(Vector512.Equals(x, y), - Vector512.ConditionalSelect(IsNegative(x), y, x), - Vector512.Max(x, y)); + return Vector512.ConditionalSelect( + Vector512.LessThan(y, x) | IsNaN(x) | (Vector512.Equals(x, y) & IsNegative(y)), + x, + y + ); } +#endif return Vector512.Max(x, y); } @@ -150,84 +142,67 @@ public static Vector512 Invoke(Vector512 x, Vector512 y) public static T Invoke(Vector512 x) => HorizontalAggregate>(x); } - /// Max(x, y) - internal readonly struct MaxPropagateNaNOperator : IBinaryOperator - where T : INumber + /// Gets whether each specified is NaN. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector128 IsNaN(Vector128 vector) { - public static bool Vectorizable => true; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Invoke(T x, T y) => T.Max(x, y); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 Invoke(Vector128 x, Vector128 y) +#if NET9_0_OR_GREATER + return Vector128.IsNaN(vector); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - if (AdvSimd.IsSupported && typeof(T) == typeof(float)) - { - return AdvSimd.Max(x.AsSingle(), y.AsSingle()).As(); - } - - if (AdvSimd.Arm64.IsSupported && typeof(T) == typeof(double)) - { - return AdvSimd.Arm64.Max(x.AsDouble(), y.AsDouble()).As(); - } - - return - Vector128.ConditionalSelect(Vector128.Equals(x, x), - Vector128.ConditionalSelect(Vector128.Equals(y, y), - Vector128.ConditionalSelect(Vector128.Equals(x, y), - Vector128.ConditionalSelect(IsNegative(x), y, x), - Vector128.Max(x, y)), - y), - x); - } - - return Vector128.Max(x, y); + return ~Vector128.Equals(vector, vector); } + return Vector128.Zero; +#endif + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 Invoke(Vector256 x, Vector256 y) + /// Gets whether each specified is NaN. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector256 IsNaN(Vector256 vector) + { +#if NET9_0_OR_GREATER + return Vector256.IsNaN(vector); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - return - Vector256.ConditionalSelect(Vector256.Equals(x, x), - Vector256.ConditionalSelect(Vector256.Equals(y, y), - Vector256.ConditionalSelect(Vector256.Equals(x, y), - Vector256.ConditionalSelect(IsNegative(x), y, x), - Vector256.Max(x, y)), - y), - x); - } - - return Vector256.Max(x, y); + return ~Vector256.Equals(vector, vector); } + return Vector256.Zero; +#endif + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 Invoke(Vector512 x, Vector512 y) + /// Gets whether each specified is NaN. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector512 IsNaN(Vector512 vector) + { +#if NET9_0_OR_GREATER + return Vector512.IsNaN(vector); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - return - Vector512.ConditionalSelect(Vector512.Equals(x, x), - Vector512.ConditionalSelect(Vector512.Equals(y, y), - Vector512.ConditionalSelect(Vector512.Equals(x, y), - Vector512.ConditionalSelect(IsNegative(x), y, x), - Vector512.Max(x, y)), - y), - x); - } - - return Vector512.Max(x, y); + return ~Vector512.Equals(vector, vector); } + return Vector512.Zero; +#endif } /// Gets whether each specified is negative. [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector128 IsNegative(Vector128 vector) { +#if NET9_0_OR_GREATER + return Vector128.IsNegative(vector); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector128.Zero; + } + if (typeof(T) == typeof(float)) { return Vector128.LessThan(vector.AsInt32(), Vector128.Zero).As(); @@ -239,12 +214,25 @@ private static Vector128 IsNegative(Vector128 vector) } return Vector128.LessThan(vector, Vector128.Zero); +#endif } /// Gets whether each specified is negative. [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector256 IsNegative(Vector256 vector) { +#if NET9_0_OR_GREATER + return Vector256.IsNegative(vector); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector256.Zero; + } + if (typeof(T) == typeof(float)) { return Vector256.LessThan(vector.AsInt32(), Vector256.Zero).As(); @@ -256,12 +244,25 @@ private static Vector256 IsNegative(Vector256 vector) } return Vector256.LessThan(vector, Vector256.Zero); +#endif } /// Gets whether each specified is negative. [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector512 IsNegative(Vector512 vector) { +#if NET9_0_OR_GREATER + return Vector512.IsNegative(vector); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector512.Zero; + } + if (typeof(T) == typeof(float)) { return Vector512.LessThan(vector.AsInt32(), Vector512.Zero).As(); @@ -273,13 +274,104 @@ private static Vector512 IsNegative(Vector512 vector) } return Vector512.LessThan(vector, Vector512.Zero); +#endif } - /// - /// This is the same as - /// with an identity transform, except it early exits on NaN. - /// - private static T MinMaxCore(ReadOnlySpan x) + /// Gets whether each specified is positive. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector128 IsPositive(Vector128 vector) + { +#if NET9_0_OR_GREATER + return Vector128.IsPositive(vector); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector128.AllBitsSet; + } + + if (typeof(T) == typeof(float)) + { + return Vector128.GreaterThanOrEqual(vector.AsInt32(), Vector128.Zero).As(); + } + + if (typeof(T) == typeof(double)) + { + return Vector128.GreaterThanOrEqual(vector.AsInt64(), Vector128.Zero).As(); + } + + return Vector128.GreaterThanOrEqual(vector, Vector128.Zero); +#endif + } + + /// Gets whether each specified is positive. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector256 IsPositive(Vector256 vector) + { +#if NET9_0_OR_GREATER + return Vector256.IsPositive(vector); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector256.AllBitsSet; + } + + if (typeof(T) == typeof(float)) + { + return Vector256.GreaterThanOrEqual(vector.AsInt32(), Vector256.Zero).As(); + } + + if (typeof(T) == typeof(double)) + { + return Vector256.GreaterThanOrEqual(vector.AsInt64(), Vector256.Zero).As(); + } + + return Vector256.GreaterThanOrEqual(vector, Vector256.Zero); +#endif + } + + /// Gets whether each specified is positive. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector512 IsPositive(Vector512 vector) + { +#if NET9_0_OR_GREATER + return Vector512.IsPositive(vector); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector512.AllBitsSet; + } + + if (typeof(T) == typeof(float)) + { + return Vector512.GreaterThanOrEqual(vector.AsInt32(), Vector512.Zero).As(); + } + + if (typeof(T) == typeof(double)) + { + return Vector512.GreaterThanOrEqual(vector.AsInt64(), Vector512.Zero).As(); + } + + return Vector512.GreaterThanOrEqual(vector, Vector512.Zero); +#endif + } + + /// + /// This is the same as + /// with an identity transform, except it early exits on NaN. + /// + private static T MinMaxCore(ReadOnlySpan x) where T : INumberBase where TMinMaxOperator : struct, IAggregationOperator { @@ -306,7 +398,7 @@ private static T MinMaxCore(ReadOnlySpan x) if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { // Check for NaNs - nanMask = ~Vector512.Equals(result, result); + nanMask = IsNaN(result); if (nanMask != Vector512.Zero) { return result.GetElement(IndexOfFirstMatch(nanMask)); @@ -437,7 +529,7 @@ private static T MinMaxCore(ReadOnlySpan x) if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { // Check for NaNs - nanMask = ~Vector128.Equals(result, result); + nanMask = IsNaN(result); if (nanMask != Vector128.Zero) { return result.GetElement(IndexOfFirstMatch(nanMask)); @@ -456,7 +548,7 @@ private static T MinMaxCore(ReadOnlySpan x) if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { // Check for NaNs - nanMask = ~Vector128.Equals(current, current); + nanMask = IsNaN(current); if (nanMask != Vector128.Zero) { return current.GetElement(IndexOfFirstMatch(nanMask)); @@ -475,7 +567,7 @@ private static T MinMaxCore(ReadOnlySpan x) if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { // Check for NaNs - nanMask = ~Vector128.Equals(current, current); + nanMask = IsNaN(current); if (nanMask != Vector128.Zero) { return current.GetElement(IndexOfFirstMatch(nanMask)); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitude.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitude.cs index eb28249ed1ea4..29a50e32f2ca9 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitude.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitude.cs @@ -44,7 +44,7 @@ public static T MaxMagnitude(ReadOnlySpan x) /// public static void MaxMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span destination) where T : INumberBase => - InvokeSpanSpanIntoSpan>(x, y, destination); + InvokeSpanSpanIntoSpan>(x, y, destination); /// Computes the element-wise number with the largest magnitude in the specified tensors. /// The first tensor, represented as a span. @@ -61,27 +61,9 @@ public static void MaxMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span /// public static void MaxMagnitude(ReadOnlySpan x, T y, Span destination) where T : INumberBase => - InvokeSpanScalarIntoSpan>(x, y, destination); + InvokeSpanScalarIntoSpan>(x, y, destination); - /// Searches for the smallest number in the specified tensor. - /// The tensor, represented as a span. - /// The minimum element in . - /// Length of must be greater than zero. - /// - /// - /// The determination of the minimum element matches the IEEE 754:2019 `minimum` function. If any value is equal to - /// is present, the first is returned. Negative 0 is considered smaller than positive 0. - /// - /// - /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different - /// operating systems or architectures. - /// - /// - public static T Min(ReadOnlySpan x) - where T : INumber => - MinMaxCore>(x); - - /// Operator to get x or y based on which has the larger MathF.Abs (but NaNs may not be propagated) + /// Operator to get x or y based on which has the larger MathF.Abs internal readonly struct MaxMagnitudeOperator : IAggregationOperator where T : INumberBase { @@ -93,151 +75,69 @@ public static T Min(ReadOnlySpan x) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - Vector128 xMag = Vector128.Abs(x), yMag = Vector128.Abs(y); - - Vector128 result = - Vector128.ConditionalSelect(Vector128.Equals(xMag, yMag), - Vector128.ConditionalSelect(IsNegative(x), y, x), - Vector128.ConditionalSelect(Vector128.GreaterThan(xMag, yMag), x, y)); - - // Handle minimum signed value that should have the largest magnitude - if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(short) || typeof(T) == typeof(int) || typeof(T) == typeof(long) || typeof(T) == typeof(nint)) +#if NET9_0_OR_GREATER + return Vector128.MaxMagnitude(x, y); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector128 negativeMagnitudeX = Vector128.LessThan(xMag, Vector128.Zero); - Vector128 negativeMagnitudeY = Vector128.LessThan(yMag, Vector128.Zero); - result = Vector128.ConditionalSelect(negativeMagnitudeX, + Vector128 xMag = Vector128.Abs(x); + Vector128 yMag = Vector128.Abs(y); + return Vector128.ConditionalSelect( + Vector128.GreaterThan(xMag, yMag) | IsNaN(xMag) | (Vector128.Equals(xMag, yMag) & IsPositive(x)), x, - Vector128.ConditionalSelect(negativeMagnitudeY, - y, - result)); + y + ); } - return result; + return MaxMagnitudeNumberOperator.Invoke(x, y); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Invoke(Vector256 x, Vector256 y) { - Vector256 xMag = Vector256.Abs(x), yMag = Vector256.Abs(y); - - Vector256 result = - Vector256.ConditionalSelect(Vector256.Equals(xMag, yMag), - Vector256.ConditionalSelect(IsNegative(x), y, x), - Vector256.ConditionalSelect(Vector256.GreaterThan(xMag, yMag), x, y)); - - // Handle minimum signed value that should have the largest magnitude - if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(short) || typeof(T) == typeof(int) || typeof(T) == typeof(long) || typeof(T) == typeof(nint)) +#if NET9_0_OR_GREATER + return Vector256.MaxMagnitude(x, y); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector256 negativeMagnitudeX = Vector256.LessThan(xMag, Vector256.Zero); - Vector256 negativeMagnitudeY = Vector256.LessThan(yMag, Vector256.Zero); - result = Vector256.ConditionalSelect(negativeMagnitudeX, + Vector256 xMag = Vector256.Abs(x); + Vector256 yMag = Vector256.Abs(y); + return Vector256.ConditionalSelect( + Vector256.GreaterThan(xMag, yMag) | IsNaN(xMag) | (Vector256.Equals(xMag, yMag) & IsPositive(x)), x, - Vector256.ConditionalSelect(negativeMagnitudeY, - y, - result)); + y + ); } - return result; + return MaxMagnitudeNumberOperator.Invoke(x, y); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Invoke(Vector512 x, Vector512 y) { - Vector512 xMag = Vector512.Abs(x), yMag = Vector512.Abs(y); - - Vector512 result = - Vector512.ConditionalSelect(Vector512.Equals(xMag, yMag), - Vector512.ConditionalSelect(IsNegative(x), y, x), - Vector512.ConditionalSelect(Vector512.GreaterThan(xMag, yMag), x, y)); - - // Handle minimum signed value that should have the largest magnitude - if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(short) || typeof(T) == typeof(int) || typeof(T) == typeof(long) || typeof(T) == typeof(nint)) +#if NET9_0_OR_GREATER + return Vector512.MaxMagnitude(x, y); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector512 negativeMagnitudeX = Vector512.LessThan(xMag, Vector512.Zero); - Vector512 negativeMagnitudeY = Vector512.LessThan(yMag, Vector512.Zero); - result = Vector512.ConditionalSelect(negativeMagnitudeX, + Vector512 xMag = Vector512.Abs(x); + Vector512 yMag = Vector512.Abs(y); + return Vector512.ConditionalSelect( + Vector512.GreaterThan(xMag, yMag) | IsNaN(xMag) | (Vector512.Equals(xMag, yMag) & IsPositive(x)), x, - Vector512.ConditionalSelect(negativeMagnitudeY, - y, - result)); + y + ); } - return result; + return MaxMagnitudeNumberOperator.Invoke(x, y); +#endif } public static T Invoke(Vector128 x) => HorizontalAggregate>(x); public static T Invoke(Vector256 x) => HorizontalAggregate>(x); public static T Invoke(Vector512 x) => HorizontalAggregate>(x); } - - /// Operator to get x or y based on which has the larger MathF.Abs - internal readonly struct MaxMagnitudePropagateNaNOperator : IBinaryOperator - where T : INumberBase - { - public static bool Vectorizable => true; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Invoke(T x, T y) => T.MaxMagnitude(x, y); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 Invoke(Vector128 x, Vector128 y) - { - // Handle NaNs - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - Vector128 xMag = Vector128.Abs(x), yMag = Vector128.Abs(y); - return - Vector128.ConditionalSelect(Vector128.Equals(x, x), - Vector128.ConditionalSelect(Vector128.Equals(y, y), - Vector128.ConditionalSelect(Vector128.Equals(yMag, xMag), - Vector128.ConditionalSelect(IsNegative(x), y, x), - Vector128.ConditionalSelect(Vector128.GreaterThan(yMag, xMag), y, x)), - y), - x); - } - - return MaxMagnitudeOperator.Invoke(x, y); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 Invoke(Vector256 x, Vector256 y) - { - // Handle NaNs - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - Vector256 xMag = Vector256.Abs(x), yMag = Vector256.Abs(y); - return - Vector256.ConditionalSelect(Vector256.Equals(x, x), - Vector256.ConditionalSelect(Vector256.Equals(y, y), - Vector256.ConditionalSelect(Vector256.Equals(xMag, yMag), - Vector256.ConditionalSelect(IsNegative(x), y, x), - Vector256.ConditionalSelect(Vector256.GreaterThan(xMag, yMag), x, y)), - y), - x); - } - - return MaxMagnitudeOperator.Invoke(x, y); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 Invoke(Vector512 x, Vector512 y) - { - // Handle NaNs - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - Vector512 xMag = Vector512.Abs(x), yMag = Vector512.Abs(y); - return - Vector512.ConditionalSelect(Vector512.Equals(x, x), - Vector512.ConditionalSelect(Vector512.Equals(y, y), - Vector512.ConditionalSelect(Vector512.Equals(xMag, yMag), - Vector512.ConditionalSelect(IsNegative(x), y, x), - Vector512.ConditionalSelect(Vector512.GreaterThan(xMag, yMag), x, y)), - y), - x); - } - - return MaxMagnitudeOperator.Invoke(x, y); - } - } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitudeNumber.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitudeNumber.cs new file mode 100644 index 0000000000000..53eb31e5dc2a2 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitudeNumber.cs @@ -0,0 +1,152 @@ +// 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.Tensors +{ + public static partial class TensorPrimitives + { + /// Operator to get x or y based on which has the larger MathF.Abs + internal readonly struct MaxMagnitudeNumberOperator : IAggregationOperator + where T : INumberBase + { + public static bool Vectorizable => true; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Invoke(T x, T y) => T.MaxMagnitudeNumber(x, y); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 Invoke(Vector128 x, Vector128 y) + { +#if NET9_0_OR_GREATER + return Vector128.MaxMagnitudeNumber(x, y); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector128.Max(x, y); + } + + Vector128 xMag = Vector128.Abs(x); + Vector128 yMag = Vector128.Abs(y); + + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double)) + ) + { + return Vector128.ConditionalSelect( + Vector128.GreaterThan(xMag, yMag) | IsNaN(yMag) | (Vector128.Equals(xMag, yMag) & IsPositive(x)), + x, + y + ); + } + + Debug.Assert((typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint))); + + return Vector128.ConditionalSelect( + (Vector128.GreaterThan(xMag, yMag) & IsPositive(yMag)) | (Vector128.Equals(xMag, yMag) & IsNegative(y)) | IsNegative(xMag), + x, + y + ); +#endif + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Invoke(Vector256 x, Vector256 y) + { +#if NET9_0_OR_GREATER + return Vector256.MaxMagnitudeNumber(x, y); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector256.Max(x, y); + } + + Vector256 xMag = Vector256.Abs(x); + Vector256 yMag = Vector256.Abs(y); + + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double)) + ) + { + return Vector256.ConditionalSelect( + Vector256.GreaterThan(xMag, yMag) | IsNaN(yMag) | (Vector256.Equals(xMag, yMag) & IsPositive(x)), + x, + y + ); + } + + Debug.Assert((typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint))); + + return Vector256.ConditionalSelect( + (Vector256.GreaterThan(xMag, yMag) & IsPositive(yMag)) | (Vector256.Equals(xMag, yMag) & IsNegative(y)) | IsNegative(xMag), + x, + y + ); +#endif + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Invoke(Vector512 x, Vector512 y) + { +#if NET9_0_OR_GREATER + return Vector512.MaxMagnitudeNumber(x, y); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector512.Max(x, y); + } + + Vector512 xMag = Vector512.Abs(x); + Vector512 yMag = Vector512.Abs(y); + + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double)) + ) + { + return Vector512.ConditionalSelect( + Vector512.GreaterThan(xMag, yMag) | IsNaN(yMag) | (Vector512.Equals(xMag, yMag) & IsPositive(x)), + x, + y + ); + } + + Debug.Assert((typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint))); + + return Vector512.ConditionalSelect( + (Vector512.GreaterThan(xMag, yMag) & IsPositive(yMag)) | (Vector512.Equals(xMag, yMag) & IsNegative(y)) | IsNegative(xMag), + x, + y + ); +#endif + } + + public static T Invoke(Vector128 x) => HorizontalAggregate>(x); + public static T Invoke(Vector256 x) => HorizontalAggregate>(x); + public static T Invoke(Vector512 x) => HorizontalAggregate>(x); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxNumber.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxNumber.cs index dc0019ce66016..92da165265601 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxNumber.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxNumber.cs @@ -86,93 +86,58 @@ public static void MaxNumber(ReadOnlySpan x, T y, Span destination) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if NET9_0_OR_GREATER + return Vector128.MaxNumber(x, y); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - // We can't use AdvSimd.MaxNumber here because it doesn't correctly - // handle sNaN (it converts it to qNaN as per the now deprecated - // maxNum function defined by IEEE 754:2008, but which is not inline - // with the maximumNumber function that replaces it in IEEE 754:2019) - - Vector128 max; - - if (Sse.IsSupported && typeof(T) == typeof(float)) - { - max = Sse.Max(x.AsSingle(), y.AsSingle()).As(); - } - else if (Sse2.IsSupported && typeof(T) == typeof(double)) - { - max = Sse2.Max(x.AsDouble(), y.AsDouble()).As(); - } - else - { - max = Vector128.ConditionalSelect(Vector128.LessThan(y, x), x, y); - } - - return - Vector128.ConditionalSelect(Vector128.Equals(x, y), - Vector128.ConditionalSelect(IsNegative(y), x, y), - Vector128.ConditionalSelect(Vector128.Equals(y, y), max, x)); + return Vector128.ConditionalSelect( + Vector128.LessThan(y, x) | IsNaN(y) | (Vector128.Equals(x, y) & IsNegative(y)), + x, + y + ); } return Vector128.Max(x, y); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Invoke(Vector256 x, Vector256 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if NET9_0_OR_GREATER + return Vector256.MaxNumber(x, y); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector256 max; - - if (Avx.IsSupported && typeof(T) == typeof(float)) - { - max = Avx.Max(x.AsSingle(), y.AsSingle()).As(); - } - else if (Avx.IsSupported && typeof(T) == typeof(double)) - { - max = Avx.Max(x.AsDouble(), y.AsDouble()).As(); - } - else - { - max = Vector256.ConditionalSelect(Vector256.LessThan(y, x), x, y); - } - - return - Vector256.ConditionalSelect(Vector256.Equals(x, y), - Vector256.ConditionalSelect(IsNegative(y), x, y), - Vector256.ConditionalSelect(Vector256.Equals(y, y), max, x)); + return Vector256.ConditionalSelect( + Vector256.LessThan(y, x) | IsNaN(y) | (Vector256.Equals(x, y) & IsNegative(y)), + x, + y + ); } return Vector256.Max(x, y); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Invoke(Vector512 x, Vector512 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if NET9_0_OR_GREATER + return Vector512.MaxNumber(x, y); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector512 max; - - if (Avx512F.IsSupported && typeof(T) == typeof(float)) - { - max = Avx512F.Max(x.AsSingle(), y.AsSingle()).As(); - } - else if (Avx512F.IsSupported && typeof(T) == typeof(double)) - { - max = Avx512F.Max(x.AsDouble(), y.AsDouble()).As(); - } - else - { - max = Vector512.ConditionalSelect(Vector512.LessThan(y, x), x, y); - } - - return - Vector512.ConditionalSelect(Vector512.Equals(x, y), - Vector512.ConditionalSelect(IsNegative(y), x, y), - Vector512.ConditionalSelect(Vector512.Equals(y, y), max, x)); + return Vector512.ConditionalSelect( + Vector512.LessThan(y, x) | IsNaN(y) | (Vector512.Equals(x, y) & IsNegative(y)), + x, + y + ); } return Vector512.Max(x, y); +#endif } public static T Invoke(Vector128 x) => HorizontalAggregate>(x); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs index fd3931fa3d194..f51e9797aebf3 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs @@ -9,6 +9,24 @@ namespace System.Numerics.Tensors { public static partial class TensorPrimitives { + /// Searches for the smallest number in the specified tensor. + /// The tensor, represented as a span. + /// The minimum element in . + /// Length of must be greater than zero. + /// + /// + /// The determination of the minimum element matches the IEEE 754:2019 `minimum` function. If any value is equal to + /// is present, the first is returned. Negative 0 is considered smaller than positive 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static T Min(ReadOnlySpan x) + where T : INumber => + MinMaxCore>(x); + /// Computes the element-wise minimum of the numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. @@ -32,7 +50,7 @@ public static partial class TensorPrimitives /// public static void Min(ReadOnlySpan x, ReadOnlySpan y, Span destination) where T : INumber => - InvokeSpanSpanIntoSpan>(x, y, destination); + InvokeSpanSpanIntoSpan>(x, y, destination); /// Computes the element-wise minimum of the numbers in the specified tensors. /// The first tensor, represented as a span. @@ -55,47 +73,30 @@ public static void Min(ReadOnlySpan x, ReadOnlySpan y, Span destinat /// public static void Min(ReadOnlySpan x, T y, Span destination) where T : INumber => - InvokeSpanScalarIntoSpan>(x, y, destination); + InvokeSpanScalarIntoSpan>(x, y, destination); - /// T.Min(x, y) (but NaNs may not be propagated) + /// T.Min(x, y) internal readonly struct MinOperator : IAggregationOperator where T : INumber { public static bool Vectorizable => true; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Invoke(T x, T y) - { - if (typeof(T) == typeof(Half) || typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - return x == y ? - (IsNegative(y) ? y : x) : - (y < x ? y : x); - } - - return T.Min(x, y); - } + public static T Invoke(T x, T y) => T.Min(x, y); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if !NET9_0_OR_GREATER + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - if (AdvSimd.IsSupported && typeof(T) == typeof(float)) - { - return AdvSimd.Min(x.AsSingle(), y.AsSingle()).As(); - } - - if (AdvSimd.Arm64.IsSupported && typeof(T) == typeof(double)) - { - return AdvSimd.Arm64.Min(x.AsDouble(), y.AsDouble()).As(); - } - - return - Vector128.ConditionalSelect(Vector128.Equals(x, y), - Vector128.ConditionalSelect(IsNegative(y), y, x), - Vector128.Min(x, y)); + return Vector128.ConditionalSelect( + Vector128.LessThan(x, y) | IsNaN(x) | (Vector128.Equals(x, y) & IsNegative(x)), + x, + y + ); } +#endif return Vector128.Min(x, y); } @@ -103,12 +104,16 @@ public static Vector128 Invoke(Vector128 x, Vector128 y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Invoke(Vector256 x, Vector256 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if !NET9_0_OR_GREATER + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - return Vector256.ConditionalSelect(Vector256.Equals(x, y), - Vector256.ConditionalSelect(IsNegative(y), y, x), - Vector256.Min(x, y)); + return Vector256.ConditionalSelect( + Vector256.LessThan(x, y) | IsNaN(x) | (Vector256.Equals(x, y) & IsNegative(x)), + x, + y + ); } +#endif return Vector256.Min(x, y); } @@ -116,12 +121,16 @@ public static Vector256 Invoke(Vector256 x, Vector256 y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Invoke(Vector512 x, Vector512 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if !NET9_0_OR_GREATER + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - return Vector512.ConditionalSelect(Vector512.Equals(x, y), - Vector512.ConditionalSelect(IsNegative(y), y, x), - Vector512.Min(x, y)); + return Vector512.ConditionalSelect( + Vector512.LessThan(x, y) | IsNaN(x) | (Vector512.Equals(x, y) & IsNegative(x)), + x, + y + ); } +#endif return Vector512.Min(x, y); } @@ -130,79 +139,5 @@ public static Vector512 Invoke(Vector512 x, Vector512 y) public static T Invoke(Vector256 x) => HorizontalAggregate>(x); public static T Invoke(Vector512 x) => HorizontalAggregate>(x); } - - /// T.Min(x, y) - internal readonly struct MinPropagateNaNOperator : IBinaryOperator - where T : INumber - { - public static bool Vectorizable => true; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Invoke(T x, T y) => T.Min(x, y); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 Invoke(Vector128 x, Vector128 y) - { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - if (AdvSimd.IsSupported && typeof(T) == typeof(float)) - { - return AdvSimd.Min(x.AsSingle(), y.AsSingle()).As(); - } - - if (AdvSimd.Arm64.IsSupported && typeof(T) == typeof(double)) - { - return AdvSimd.Arm64.Min(x.AsDouble(), y.AsDouble()).As(); - } - - return - Vector128.ConditionalSelect(Vector128.Equals(x, x), - Vector128.ConditionalSelect(Vector128.Equals(y, y), - Vector128.ConditionalSelect(Vector128.Equals(x, y), - Vector128.ConditionalSelect(IsNegative(x), x, y), - Vector128.Min(x, y)), - y), - x); - } - - return Vector128.Min(x, y); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 Invoke(Vector256 x, Vector256 y) - { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - return - Vector256.ConditionalSelect(Vector256.Equals(x, x), - Vector256.ConditionalSelect(Vector256.Equals(y, y), - Vector256.ConditionalSelect(Vector256.Equals(x, y), - Vector256.ConditionalSelect(IsNegative(x), x, y), - Vector256.Min(x, y)), - y), - x); - } - - return Vector256.Min(x, y); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 Invoke(Vector512 x, Vector512 y) - { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - return - Vector512.ConditionalSelect(Vector512.Equals(x, x), - Vector512.ConditionalSelect(Vector512.Equals(y, y), - Vector512.ConditionalSelect(Vector512.Equals(x, y), - Vector512.ConditionalSelect(IsNegative(x), x, y), - Vector512.Min(x, y)), - y), - x); - } - - return Vector512.Min(x, y); - } - } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitude.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitude.cs index 47b492eaffb8a..d3158f6e12bb4 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitude.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitude.cs @@ -49,7 +49,7 @@ public static T MinMagnitude(ReadOnlySpan x) /// public static void MinMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span destination) where T : INumberBase => - InvokeSpanSpanIntoSpan>(x, y, destination); + InvokeSpanSpanIntoSpan>(x, y, destination); /// Computes the element-wise number with the smallest magnitude in the specified tensors. /// The first tensor, represented as a span. @@ -71,9 +71,9 @@ public static void MinMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span /// public static void MinMagnitude(ReadOnlySpan x, T y, Span destination) where T : INumberBase => - InvokeSpanScalarIntoSpan>(x, y, destination); + InvokeSpanScalarIntoSpan>(x, y, destination); - /// Operator to get x or y based on which has the smaller MathF.Abs (but NaNs may not be propagated) + /// Operator to get x or y based on which has the smaller MathF.Abs internal readonly struct MinMagnitudeOperator : IAggregationOperator where T : INumberBase { @@ -85,148 +85,72 @@ public static void MinMagnitude(ReadOnlySpan x, T y, Span destination) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - Vector128 xMag = Vector128.Abs(x), yMag = Vector128.Abs(y); - - Vector128 result = - Vector128.ConditionalSelect(Vector128.Equals(yMag, xMag), - Vector128.ConditionalSelect(IsNegative(y), y, x), - Vector128.ConditionalSelect(Vector128.LessThan(yMag, xMag), y, x)); +#if NET9_0_OR_GREATER + return Vector128.MinMagnitude(x, y); +#else - if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(short) || typeof(T) == typeof(int) || typeof(T) == typeof(long) || typeof(T) == typeof(nint)) + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector128 negativeMagnitudeX = Vector128.LessThan(xMag, Vector128.Zero); - Vector128 negativeMagnitudeY = Vector128.LessThan(yMag, Vector128.Zero); - result = Vector128.ConditionalSelect(negativeMagnitudeX, - y, - Vector128.ConditionalSelect(negativeMagnitudeY, - x, - result)); + Vector128 xMag = Vector128.Abs(x); + Vector128 yMag = Vector128.Abs(y); + + return Vector128.ConditionalSelect( + Vector128.LessThan(xMag, yMag) | IsNaN(xMag) | (Vector128.Equals(xMag, yMag) & IsNegative(x)), + x, + y + ); } - - return result; + return MinMagnitudeNumberOperator.Invoke(x, y); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Invoke(Vector256 x, Vector256 y) { - Vector256 xMag = Vector256.Abs(x), yMag = Vector256.Abs(y); +#if NET9_0_OR_GREATER + return Vector256.MinMagnitude(x, y); +#else - Vector256 result = - Vector256.ConditionalSelect(Vector256.Equals(yMag, xMag), - Vector256.ConditionalSelect(IsNegative(y), y, x), - Vector256.ConditionalSelect(Vector256.LessThan(yMag, xMag), y, x)); - - if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(short) || typeof(T) == typeof(int) || typeof(T) == typeof(long) || typeof(T) == typeof(nint)) + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector256 negativeMagnitudeX = Vector256.LessThan(xMag, Vector256.Zero); - Vector256 negativeMagnitudeY = Vector256.LessThan(yMag, Vector256.Zero); - result = Vector256.ConditionalSelect(negativeMagnitudeX, - y, - Vector256.ConditionalSelect(negativeMagnitudeY, - x, - result)); + Vector256 xMag = Vector256.Abs(x); + Vector256 yMag = Vector256.Abs(y); + + return Vector256.ConditionalSelect( + Vector256.LessThan(xMag, yMag) | IsNaN(xMag) | (Vector256.Equals(xMag, yMag) & IsNegative(x)), + x, + y + ); } - - return result; + return MinMagnitudeNumberOperator.Invoke(x, y); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Invoke(Vector512 x, Vector512 y) { - Vector512 xMag = Vector512.Abs(x), yMag = Vector512.Abs(y); +#if NET9_0_OR_GREATER + return Vector512.MinMagnitude(x, y); +#else - Vector512 result = - Vector512.ConditionalSelect(Vector512.Equals(yMag, xMag), - Vector512.ConditionalSelect(IsNegative(y), y, x), - Vector512.ConditionalSelect(Vector512.LessThan(yMag, xMag), y, x)); - - if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(short) || typeof(T) == typeof(int) || typeof(T) == typeof(long) || typeof(T) == typeof(nint)) + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector512 negativeMagnitudeX = Vector512.LessThan(xMag, Vector512.Zero); - Vector512 negativeMagnitudeY = Vector512.LessThan(yMag, Vector512.Zero); - result = Vector512.ConditionalSelect(negativeMagnitudeX, - y, - Vector512.ConditionalSelect(negativeMagnitudeY, - x, - result)); + Vector512 xMag = Vector512.Abs(x); + Vector512 yMag = Vector512.Abs(y); + + return Vector512.ConditionalSelect( + Vector512.LessThan(xMag, yMag) | IsNaN(xMag) | (Vector512.Equals(xMag, yMag) & IsNegative(x)), + x, + y + ); } - - return result; + return MinMagnitudeNumberOperator.Invoke(x, y); +#endif } public static T Invoke(Vector128 x) => HorizontalAggregate>(x); public static T Invoke(Vector256 x) => HorizontalAggregate>(x); public static T Invoke(Vector512 x) => HorizontalAggregate>(x); } - - /// Operator to get x or y based on which has the smaller MathF.Abs - internal readonly struct MinMagnitudePropagateNaNOperator : IBinaryOperator - where T : INumberBase - { - public static bool Vectorizable => true; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Invoke(T x, T y) => T.MinMagnitude(x, y); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 Invoke(Vector128 x, Vector128 y) - { - // Handle NaNs - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - Vector128 xMag = Vector128.Abs(x), yMag = Vector128.Abs(y); - return - Vector128.ConditionalSelect(Vector128.Equals(x, x), - Vector128.ConditionalSelect(Vector128.Equals(y, y), - Vector128.ConditionalSelect(Vector128.Equals(yMag, xMag), - Vector128.ConditionalSelect(IsNegative(x), x, y), - Vector128.ConditionalSelect(Vector128.LessThan(xMag, yMag), x, y)), - y), - x); - } - - return MinMagnitudeOperator.Invoke(x, y); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 Invoke(Vector256 x, Vector256 y) - { - // Handle NaNs - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - Vector256 xMag = Vector256.Abs(x), yMag = Vector256.Abs(y); - return - Vector256.ConditionalSelect(Vector256.Equals(x, x), - Vector256.ConditionalSelect(Vector256.Equals(y, y), - Vector256.ConditionalSelect(Vector256.Equals(yMag, xMag), - Vector256.ConditionalSelect(IsNegative(x), x, y), - Vector256.ConditionalSelect(Vector256.LessThan(xMag, yMag), x, y)), - y), - x); - } - - return MinMagnitudeOperator.Invoke(x, y); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 Invoke(Vector512 x, Vector512 y) - { - // Handle NaNs - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { - Vector512 xMag = Vector512.Abs(x), yMag = Vector512.Abs(y); - return - Vector512.ConditionalSelect(Vector512.Equals(x, x), - Vector512.ConditionalSelect(Vector512.Equals(y, y), - Vector512.ConditionalSelect(Vector512.Equals(yMag, xMag), - Vector512.ConditionalSelect(IsNegative(x), x, y), - Vector512.ConditionalSelect(Vector512.LessThan(xMag, yMag), x, y)), - y), - x); - } - - return MinMagnitudeOperator.Invoke(x, y); - } - } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitudeNumber.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitudeNumber.cs new file mode 100644 index 0000000000000..b714b8e7d0a64 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitudeNumber.cs @@ -0,0 +1,149 @@ +// 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.Tensors +{ + public static partial class TensorPrimitives + { + /// Operator to get x or y based on which has the smaller MathF.Abs + internal readonly struct MinMagnitudeNumberOperator : IAggregationOperator + where T : INumberBase + { + public static bool Vectorizable => true; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Invoke(T x, T y) => T.MinMagnitudeNumber(x, y); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 Invoke(Vector128 x, Vector128 y) + { +#if NET9_0_OR_GREATER + return Vector128.MinMagnitudeNumber(x, y); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector128.Min(x, y); + } + + Vector128 xMag = Vector128.Abs(x); + Vector128 yMag = Vector128.Abs(y); + + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return Vector128.ConditionalSelect( + Vector128.LessThan(xMag, yMag) | IsNaN(yMag) | (Vector128.Equals(xMag, yMag) & IsNegative(x)), + x, + y + ); + } + + Debug.Assert((typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint))); + + return Vector128.ConditionalSelect( + (Vector128.LessThan(xMag, yMag) & IsPositive(xMag)) | (Vector128.Equals(xMag, yMag) & IsNegative(x)) | IsNegative(yMag), + x, + y + ); +#endif + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Invoke(Vector256 x, Vector256 y) + { +#if NET9_0_OR_GREATER + return Vector256.MinMagnitudeNumber(x, y); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector256.Min(x, y); + } + + Vector256 xMag = Vector256.Abs(x); + Vector256 yMag = Vector256.Abs(y); + + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return Vector256.ConditionalSelect( + Vector256.LessThan(xMag, yMag) | IsNaN(yMag) | (Vector256.Equals(xMag, yMag) & IsNegative(x)), + x, + y + ); + } + + Debug.Assert((typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint))); + + return Vector256.ConditionalSelect( + (Vector256.LessThan(xMag, yMag) & IsPositive(xMag)) | (Vector256.Equals(xMag, yMag) & IsNegative(x)) | IsNegative(yMag), + x, + y + ); +#endif + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Invoke(Vector512 x, Vector512 y) + { +#if NET9_0_OR_GREATER + return Vector512.MinMagnitudeNumber(x, y); +#else + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector512.Min(x, y); + } + + Vector512 xMag = Vector512.Abs(x); + Vector512 yMag = Vector512.Abs(y); + + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return Vector512.ConditionalSelect( + Vector512.LessThan(xMag, yMag) | IsNaN(yMag) | (Vector512.Equals(xMag, yMag) & IsNegative(x)), + x, + y + ); + } + + Debug.Assert((typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint))); + + return Vector512.ConditionalSelect( + (Vector512.LessThan(xMag, yMag) & IsPositive(xMag)) | (Vector512.Equals(xMag, yMag) & IsNegative(x)) | IsNegative(yMag), + x, + y + ); +#endif + } + + public static T Invoke(Vector128 x) => HorizontalAggregate>(x); + public static T Invoke(Vector256 x) => HorizontalAggregate>(x); + public static T Invoke(Vector512 x) => HorizontalAggregate>(x); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinNumber.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinNumber.cs index 79e04bf6d747d..653e8c7383eae 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinNumber.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinNumber.cs @@ -86,93 +86,58 @@ public static void MinNumber(ReadOnlySpan x, T y, Span destination) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if NET9_0_OR_GREATER + return Vector128.MinNumber(x, y); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - // We can't use AdvSimd.MinNumber here because it doesn't correctly - // handle sNaN (it converts it to qNaN as per the now deprecated - // minNum function defined by IEEE 754:2008, but which is not inline - // with the minimumNumber function that replaces it in IEEE 754:2019) - - Vector128 min; - - if (Sse.IsSupported && typeof(T) == typeof(float)) - { - min = Sse.Min(x.AsSingle(), y.AsSingle()).As(); - } - else if (Sse2.IsSupported && typeof(T) == typeof(double)) - { - min = Sse2.Min(x.AsDouble(), y.AsDouble()).As(); - } - else - { - min = Vector128.ConditionalSelect(Vector128.LessThan(x, y), x, y); - } - - return - Vector128.ConditionalSelect(Vector128.Equals(x, y), - Vector128.ConditionalSelect(IsNegative(x), x, y), - Vector128.ConditionalSelect(Vector128.Equals(y, y), min, x)); + return Vector128.ConditionalSelect( + (Vector128.Equals(x, y) & IsNegative(x)) | IsNaN(y) | Vector128.LessThan(x, y), + x, + y + ); } return Vector128.Min(x, y); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Invoke(Vector256 x, Vector256 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if NET9_0_OR_GREATER + return Vector256.MinNumber(x, y); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector256 min; - - if (Avx.IsSupported && typeof(T) == typeof(float)) - { - min = Avx.Min(x.AsSingle(), y.AsSingle()).As(); - } - else if (Avx.IsSupported && typeof(T) == typeof(double)) - { - min = Avx.Min(x.AsDouble(), y.AsDouble()).As(); - } - else - { - min = Vector256.ConditionalSelect(Vector256.LessThan(x, y), x, y); - } - - return - Vector256.ConditionalSelect(Vector256.Equals(x, y), - Vector256.ConditionalSelect(IsNegative(x), x, y), - Vector256.ConditionalSelect(Vector256.Equals(y, y), min, x)); + return Vector256.ConditionalSelect( + (Vector256.Equals(x, y) & IsNegative(x)) | IsNaN(y) | Vector256.LessThan(x, y), + x, + y + ); } return Vector256.Min(x, y); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Invoke(Vector512 x, Vector512 y) { - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) +#if NET9_0_OR_GREATER + return Vector512.MinNumber(x, y); +#else + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) { - Vector512 min; - - if (Avx512F.IsSupported && typeof(T) == typeof(float)) - { - min = Avx512F.Min(x.AsSingle(), y.AsSingle()).As(); - } - else if (Avx512F.IsSupported && typeof(T) == typeof(double)) - { - min = Avx512F.Min(x.AsDouble(), y.AsDouble()).As(); - } - else - { - min = Vector512.ConditionalSelect(Vector512.LessThan(x, y), x, y); - } - - return - Vector512.ConditionalSelect(Vector512.Equals(x, y), - Vector512.ConditionalSelect(IsNegative(x), x, y), - Vector512.ConditionalSelect(Vector512.Equals(y, y), min, x)); + return Vector512.ConditionalSelect( + (Vector512.Equals(x, y) & IsNegative(x)) | IsNaN(y) | Vector512.LessThan(x, y), + x, + y + ); } return Vector512.Min(x, y); +#endif } public static T Invoke(Vector128 x) => HorizontalAggregate>(x); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RadiansToDegrees.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RadiansToDegrees.cs index 53298f5cf3c0e..077934dd1099b 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RadiansToDegrees.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RadiansToDegrees.cs @@ -1,6 +1,7 @@ // 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.Intrinsics; namespace System.Numerics.Tensors @@ -25,10 +26,59 @@ public static void RadiansToDegrees(ReadOnlySpan x, Span destination) private readonly struct RadiansToDegreesOperator : IUnaryOperator where T : ITrigonometricFunctions { public static bool Vectorizable => true; + public static T Invoke(T x) => T.RadiansToDegrees(x); - public static Vector128 Invoke(Vector128 x) => (x * T.CreateChecked(180)) / T.Pi; - public static Vector256 Invoke(Vector256 x) => (x * T.CreateChecked(180)) / T.Pi; - public static Vector512 Invoke(Vector512 x) => (x * T.CreateChecked(180)) / T.Pi; + + public static Vector128 Invoke(Vector128 x) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector128.RadiansToDegrees(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector128.RadiansToDegrees(x.AsSingle()).As(); + } +#else + return (x * T.CreateChecked(180)) / T.Pi; +#endif + } + + public static Vector256 Invoke(Vector256 x) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector256.RadiansToDegrees(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector256.RadiansToDegrees(x.AsSingle()).As(); + } +#else + return (x * T.CreateChecked(180)) / T.Pi; +#endif + } + + public static Vector512 Invoke(Vector512 x) + { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector512.RadiansToDegrees(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector512.RadiansToDegrees(x.AsSingle()).As(); + } +#else + return (x * T.CreateChecked(180)) / T.Pi; +#endif + } } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Round.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Round.cs index 83cd73d184435..bd39bd0cdf9f2 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Round.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Round.cs @@ -171,28 +171,66 @@ public static void Round(ReadOnlySpan x, int digits, MidpointRounding mode public static T Invoke(T x) => T.Round(x); +#if !NET9_0_OR_GREATER private const float SingleBoundary = 8388608.0f; // 2^23 private const double DoubleBoundary = 4503599627370496.0; // 2^52 +#endif public static Vector128 Invoke(Vector128 x) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector128.Round(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector128.Round(x.AsSingle()).As(); + } +#else Vector128 boundary = Vector128.Create(typeof(T) == typeof(float) ? T.CreateTruncating(SingleBoundary) : T.CreateTruncating(DoubleBoundary)); Vector128 temp = CopySignOperator.Invoke(boundary, x); return Vector128.ConditionalSelect(Vector128.GreaterThan(Vector128.Abs(x), boundary), x, CopySignOperator.Invoke((x + temp) - temp, x)); +#endif } public static Vector256 Invoke(Vector256 x) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector256.Round(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector256.Round(x.AsSingle()).As(); + } +#else Vector256 boundary = Vector256.Create(typeof(T) == typeof(float) ? T.CreateTruncating(SingleBoundary) : T.CreateTruncating(DoubleBoundary)); Vector256 temp = CopySignOperator.Invoke(boundary, x); return Vector256.ConditionalSelect(Vector256.GreaterThan(Vector256.Abs(x), boundary), x, CopySignOperator.Invoke((x + temp) - temp, x)); +#endif } public static Vector512 Invoke(Vector512 x) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector512.Round(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector512.Round(x.AsSingle()).As(); + } +#else Vector512 boundary = Vector512.Create(typeof(T) == typeof(float) ? T.CreateTruncating(SingleBoundary) : T.CreateTruncating(DoubleBoundary)); Vector512 temp = CopySignOperator.Invoke(boundary, x); return Vector512.ConditionalSelect(Vector512.GreaterThan(Vector512.Abs(x), boundary), x, CopySignOperator.Invoke((x + temp) - temp, x)); +#endif } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Single.netcore.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Single.netcore.cs index b1f6309e6dbca..a15a43d2178a0 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Single.netcore.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Single.netcore.cs @@ -21,13 +21,9 @@ global using LogOperator_Single = System.Numerics.Tensors.TensorPrimitives.LogOperator; global using Log2Operator_Single = System.Numerics.Tensors.TensorPrimitives.Log2Operator; global using MaxOperator_Single = System.Numerics.Tensors.TensorPrimitives.MaxOperator; -global using MaxPropagateNaNOperator_Single = System.Numerics.Tensors.TensorPrimitives.MaxPropagateNaNOperator; global using MaxMagnitudeOperator_Single = System.Numerics.Tensors.TensorPrimitives.MaxMagnitudeOperator; -global using MaxMagnitudePropagateNaNOperator_Single = System.Numerics.Tensors.TensorPrimitives.MaxMagnitudePropagateNaNOperator; global using MinOperator_Single = System.Numerics.Tensors.TensorPrimitives.MinOperator; -global using MinPropagateNaNOperator_Single = System.Numerics.Tensors.TensorPrimitives.MinPropagateNaNOperator; global using MinMagnitudeOperator_Single = System.Numerics.Tensors.TensorPrimitives.MinMagnitudeOperator; -global using MinMagnitudePropagateNaNOperator_Single = System.Numerics.Tensors.TensorPrimitives.MinMagnitudePropagateNaNOperator; global using MultiplyAddOperator_Single = System.Numerics.Tensors.TensorPrimitives.MultiplyAddOperator; global using NegateOperator_Single = System.Numerics.Tensors.TensorPrimitives.NegateOperator; global using IdentityOperator_Single = System.Numerics.Tensors.TensorPrimitives.IdentityOperator; diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Truncate.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Truncate.cs index 3a2e3cea290af..f50c9b6e20d85 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Truncate.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Truncate.cs @@ -32,6 +32,17 @@ public static void Truncate(ReadOnlySpan x, Span destination) public static Vector128 Invoke(Vector128 x) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector128.Truncate(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector128.Truncate(x.AsSingle()).As(); + } +#else if (typeof(T) == typeof(float)) { if (Sse41.IsSupported) return Sse41.RoundToZero(x.AsSingle()).As(); @@ -52,10 +63,22 @@ public static Vector128 Invoke(Vector128 x) Vector128.Floor(x.AsDouble()).As(), Vector128.Ceiling(x.AsDouble()).As()); } +#endif } public static Vector256 Invoke(Vector256 x) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector256.Truncate(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector256.Truncate(x.AsSingle()).As(); + } +#else if (typeof(T) == typeof(float)) { if (Avx.IsSupported) return Avx.RoundToZero(x.AsSingle()).As(); @@ -74,10 +97,22 @@ public static Vector256 Invoke(Vector256 x) Vector256.Floor(x.AsDouble()).As(), Vector256.Ceiling(x.AsDouble()).As()); } +#endif } public static Vector512 Invoke(Vector512 x) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector512.Truncate(x.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector512.Truncate(x.AsSingle()).As(); + } +#else if (typeof(T) == typeof(float)) { if (Avx512F.IsSupported) return Avx512F.RoundScale(x.AsSingle(), 0b11).As(); @@ -96,6 +131,7 @@ public static Vector512 Invoke(Vector512 x) Vector512.Floor(x.AsDouble()).As(), Vector512.Ceiling(x.AsDouble()).As()); } +#endif } } } 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 13b94b02fd2cf..fba0c8dbcd4be 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -238,6 +238,8 @@ public static partial class Vector public static System.Numerics.Vector BitwiseOr(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Ceiling(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector Ceiling(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Clamp(System.Numerics.Vector value, System.Numerics.Vector min, System.Numerics.Vector max) { throw null; } + public static System.Numerics.Vector ClampNative(System.Numerics.Vector value, System.Numerics.Vector min, System.Numerics.Vector max) { throw null; } public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector condition, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector condition, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector condition, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -259,9 +261,12 @@ 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 CopySign(System.Numerics.Vector value, System.Numerics.Vector sign) { 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 DegreesToRadians(System.Numerics.Vector degrees) { throw null; } + public static System.Numerics.Vector DegreesToRadians(System.Numerics.Vector degrees) { 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; } public static T Dot(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -272,6 +277,8 @@ public static partial class Vector public static bool EqualsAll(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static bool EqualsAny(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Equals(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Exp(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector Exp(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector Floor(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector Floor(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector FusedMultiplyAdd(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector addend) { throw null; } @@ -291,6 +298,15 @@ public static partial class Vector public static bool GreaterThanOrEqualAny(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector GreaterThanOrEqual(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector GreaterThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Hypot(System.Numerics.Vector x, System.Numerics.Vector y) { throw null; } + public static System.Numerics.Vector Hypot(System.Numerics.Vector x, System.Numerics.Vector y) { throw null; } + public static System.Numerics.Vector IsNaN(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsNegative(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsPositive(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsPositiveInfinity(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsZero(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector Lerp(System.Numerics.Vector x, System.Numerics.Vector y, System.Numerics.Vector amount) { throw null; } + public static System.Numerics.Vector Lerp(System.Numerics.Vector x, System.Numerics.Vector y, System.Numerics.Vector amount) { throw null; } public static System.Numerics.Vector LessThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector LessThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector LessThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -316,8 +332,20 @@ public static partial class Vector public static System.Numerics.Vector LoadUnsafe(ref readonly T source) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector LoadUnsafe(ref readonly T source, nuint elementOffset) { throw null; } + public static System.Numerics.Vector Log(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector Log(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector Log2(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector Log2(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxMagnitude(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxMagnitudeNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxNative(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinMagnitude(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinMagnitudeNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinNative(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Multiply(System.Numerics.Vector left, T right) { throw null; } public static System.Numerics.Vector Multiply(T left, System.Numerics.Vector right) { throw null; } @@ -336,6 +364,12 @@ public static partial class Vector public static System.Numerics.Vector Narrow(System.Numerics.Vector low, System.Numerics.Vector high) { throw null; } public static System.Numerics.Vector Negate(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector OnesComplement(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector RadiansToDegrees(System.Numerics.Vector radians) { throw null; } + public static System.Numerics.Vector RadiansToDegrees(System.Numerics.Vector radians) { throw null; } + public static System.Numerics.Vector Round(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector Round(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector Round(System.Numerics.Vector vector, System.MidpointRounding mode) { throw null; } + public static System.Numerics.Vector Round(System.Numerics.Vector vector, System.MidpointRounding mode) { throw null; } public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) { throw null; } public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) { throw null; } public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) { throw null; } @@ -387,6 +421,8 @@ public static partial class Vector public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static T Sum(System.Numerics.Vector value) { throw null; } public static T ToScalar(this System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector Truncate(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector Truncate(System.Numerics.Vector vector) { throw null; } [System.CLSCompliantAttribute(false)] public static void Widen(System.Numerics.Vector source, out System.Numerics.Vector low, out System.Numerics.Vector high) { throw null; } public static void Widen(System.Numerics.Vector source, out System.Numerics.Vector low, out System.Numerics.Vector high) { throw null; } @@ -430,7 +466,15 @@ public partial struct Vector2 : System.IEquatable, Syst public Vector2(float value) { throw null; } public Vector2(float x, float y) { throw null; } public Vector2(System.ReadOnlySpan values) { throw null; } + public static System.Numerics.Vector2 E { get { throw null; } } + public static System.Numerics.Vector2 Epsilon { get { throw null; } } + public static System.Numerics.Vector2 NaN { get { throw null; } } + public static System.Numerics.Vector2 NegativeInfinity { get { throw null; } } + public static System.Numerics.Vector2 NegativeZero { get { throw null; } } public static System.Numerics.Vector2 One { get { throw null; } } + public static System.Numerics.Vector2 Pi { get { throw null; } } + public static System.Numerics.Vector2 PositiveInfinity { get { throw null; } } + public static System.Numerics.Vector2 Tau { get { throw null; } } public static System.Numerics.Vector2 UnitX { get { throw null; } } public static System.Numerics.Vector2 UnitY { get { throw null; } } public float this[int index] { readonly get { throw null; } set { throw null; } } @@ -438,6 +482,8 @@ 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 ClampNative(System.Numerics.Vector2 value1, System.Numerics.Vector2 min, System.Numerics.Vector2 max) { throw null; } + public static System.Numerics.Vector2 CopySign(System.Numerics.Vector2 value, System.Numerics.Vector2 sign) { 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; } @@ -445,6 +491,7 @@ public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } public readonly void CopyTo(System.Span destination) { } public readonly bool TryCopyTo(System.Span destination) { throw null; } + public static System.Numerics.Vector2 DegreesToRadians(System.Numerics.Vector2 degrees) { throw null; } public static float Distance(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } public static float DistanceSquared(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } public static System.Numerics.Vector2 Divide(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } @@ -452,13 +499,26 @@ public readonly void CopyTo(System.Span destination) { } public static float Dot(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } public readonly bool Equals(System.Numerics.Vector2 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public static System.Numerics.Vector2 Exp(System.Numerics.Vector2 vector) { throw null; } public static System.Numerics.Vector2 FusedMultiplyAdd(System.Numerics.Vector2 left, System.Numerics.Vector2 right, System.Numerics.Vector2 addend) { throw null; } public override readonly int GetHashCode() { throw null; } + public static System.Numerics.Vector2 Hypot(System.Numerics.Vector2 x, System.Numerics.Vector2 y) { throw null; } public readonly float Length() { throw null; } public readonly float LengthSquared() { throw null; } public static System.Numerics.Vector2 Lerp(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2, float amount) { throw null; } + public static System.Numerics.Vector2 Lerp(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2, System.Numerics.Vector2 amount) { throw null; } + public static System.Numerics.Vector2 Log(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 Log2(System.Numerics.Vector2 vector) { throw null; } public static System.Numerics.Vector2 Max(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } + public static System.Numerics.Vector2 MaxMagnitude(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } + public static System.Numerics.Vector2 MaxMagnitudeNumber(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } + public static System.Numerics.Vector2 MaxNative(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } + public static System.Numerics.Vector2 MaxNumber(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } public static System.Numerics.Vector2 Min(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } + public static System.Numerics.Vector2 MinMagnitude(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } + public static System.Numerics.Vector2 MinMagnitudeNumber(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } + public static System.Numerics.Vector2 MinNative(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } + public static System.Numerics.Vector2 MinNumber(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } public static System.Numerics.Vector2 Multiply(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 Multiply(System.Numerics.Vector2 left, float right) { throw null; } public static System.Numerics.Vector2 Multiply(float left, System.Numerics.Vector2 right) { throw null; } @@ -475,6 +535,9 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector2 operator *(float left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 operator -(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 operator -(System.Numerics.Vector2 value) { throw null; } + public static System.Numerics.Vector2 RadiansToDegrees(System.Numerics.Vector2 radians) { throw null; } + public static System.Numerics.Vector2 Round(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 Round(System.Numerics.Vector2 vector, System.MidpointRounding mode) { throw null; } public static System.Numerics.Vector2 Reflect(System.Numerics.Vector2 vector, System.Numerics.Vector2 normal) { throw null; } public static System.Numerics.Vector2 SquareRoot(System.Numerics.Vector2 value) { throw null; } public static System.Numerics.Vector2 Subtract(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } @@ -486,6 +549,7 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector2 Transform(System.Numerics.Vector2 value, System.Numerics.Quaternion rotation) { throw null; } public static System.Numerics.Vector2 TransformNormal(System.Numerics.Vector2 normal, System.Numerics.Matrix3x2 matrix) { throw null; } public static System.Numerics.Vector2 TransformNormal(System.Numerics.Vector2 normal, System.Numerics.Matrix4x4 matrix) { throw null; } + public static System.Numerics.Vector2 Truncate(System.Numerics.Vector2 vector) { throw null; } } public partial struct Vector3 : System.IEquatable, System.IFormattable { @@ -496,7 +560,15 @@ public partial struct Vector3 : System.IEquatable, Syst public Vector3(float value) { throw null; } public Vector3(float x, float y, float z) { throw null; } public Vector3(System.ReadOnlySpan values) { throw null; } + public static System.Numerics.Vector3 E { get { throw null; } } + public static System.Numerics.Vector3 Epsilon { get { throw null; } } + public static System.Numerics.Vector3 NaN { get { throw null; } } + public static System.Numerics.Vector3 NegativeInfinity { get { throw null; } } + public static System.Numerics.Vector3 NegativeZero { get { throw null; } } public static System.Numerics.Vector3 One { get { throw null; } } + public static System.Numerics.Vector3 Pi { get { throw null; } } + public static System.Numerics.Vector3 PositiveInfinity { get { throw null; } } + public static System.Numerics.Vector3 Tau { get { throw null; } } public static System.Numerics.Vector3 UnitX { get { throw null; } } public static System.Numerics.Vector3 UnitY { get { throw null; } } public static System.Numerics.Vector3 UnitZ { get { throw null; } } @@ -505,6 +577,8 @@ 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 ClampNative(System.Numerics.Vector3 value1, System.Numerics.Vector3 min, System.Numerics.Vector3 max) { throw null; } + public static System.Numerics.Vector3 CopySign(System.Numerics.Vector3 value, System.Numerics.Vector3 sign) { 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; } @@ -514,6 +588,7 @@ public readonly void CopyTo(float[] array, int index) { } public readonly void CopyTo(System.Span destination) { } public readonly bool TryCopyTo(System.Span destination) { throw null; } public static System.Numerics.Vector3 Cross(System.Numerics.Vector3 vector1, System.Numerics.Vector3 vector2) { throw null; } + public static System.Numerics.Vector3 DegreesToRadians(System.Numerics.Vector3 degrees) { throw null; } public static float Distance(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } public static float DistanceSquared(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } public static System.Numerics.Vector3 Divide(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } @@ -521,13 +596,26 @@ public readonly void CopyTo(System.Span destination) { } public static float Dot(System.Numerics.Vector3 vector1, System.Numerics.Vector3 vector2) { throw null; } public readonly bool Equals(System.Numerics.Vector3 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public static System.Numerics.Vector3 Exp(System.Numerics.Vector3 vector) { throw null; } public static System.Numerics.Vector3 FusedMultiplyAdd(System.Numerics.Vector3 left, System.Numerics.Vector3 right, System.Numerics.Vector3 addend) { throw null; } public override readonly int GetHashCode() { throw null; } public readonly float Length() { throw null; } public readonly float LengthSquared() { throw null; } + public static System.Numerics.Vector3 Hypot(System.Numerics.Vector3 x, System.Numerics.Vector3 y) { throw null; } public static System.Numerics.Vector3 Lerp(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2, float amount) { throw null; } + public static System.Numerics.Vector3 Lerp(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2, System.Numerics.Vector3 amount) { throw null; } + public static System.Numerics.Vector3 Log(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 Log2(System.Numerics.Vector3 vector) { throw null; } public static System.Numerics.Vector3 Max(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } + public static System.Numerics.Vector3 MaxMagnitude(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } + public static System.Numerics.Vector3 MaxMagnitudeNumber(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } + public static System.Numerics.Vector3 MaxNative(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } + public static System.Numerics.Vector3 MaxNumber(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } public static System.Numerics.Vector3 Min(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } + public static System.Numerics.Vector3 MinMagnitude(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } + public static System.Numerics.Vector3 MinMagnitudeNumber(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } + public static System.Numerics.Vector3 MinNative(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } + public static System.Numerics.Vector3 MinNumber(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } public static System.Numerics.Vector3 Multiply(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 Multiply(System.Numerics.Vector3 left, float right) { throw null; } public static System.Numerics.Vector3 Multiply(float left, System.Numerics.Vector3 right) { throw null; } @@ -544,7 +632,10 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector3 operator *(float left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 operator -(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 operator -(System.Numerics.Vector3 value) { throw null; } + public static System.Numerics.Vector3 RadiansToDegrees(System.Numerics.Vector3 radians) { throw null; } public static System.Numerics.Vector3 Reflect(System.Numerics.Vector3 vector, System.Numerics.Vector3 normal) { throw null; } + public static System.Numerics.Vector3 Round(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 Round(System.Numerics.Vector3 vector, System.MidpointRounding mode) { throw null; } public static System.Numerics.Vector3 SquareRoot(System.Numerics.Vector3 value) { throw null; } public static System.Numerics.Vector3 Subtract(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public override readonly string ToString() { throw null; } @@ -553,6 +644,7 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector3 Transform(System.Numerics.Vector3 position, System.Numerics.Matrix4x4 matrix) { throw null; } public static System.Numerics.Vector3 Transform(System.Numerics.Vector3 value, System.Numerics.Quaternion rotation) { throw null; } public static System.Numerics.Vector3 TransformNormal(System.Numerics.Vector3 normal, System.Numerics.Matrix4x4 matrix) { throw null; } + public static System.Numerics.Vector3 Truncate(System.Numerics.Vector3 vector) { throw null; } } public partial struct Vector4 : System.IEquatable, System.IFormattable { @@ -565,7 +657,15 @@ public partial struct Vector4 : System.IEquatable, Syst public Vector4(float value) { throw null; } public Vector4(float x, float y, float z, float w) { throw null; } public Vector4(System.ReadOnlySpan values) { throw null; } + public static System.Numerics.Vector4 E { get { throw null; } } + public static System.Numerics.Vector4 Epsilon { get { throw null; } } + public static System.Numerics.Vector4 NaN { get { throw null; } } + public static System.Numerics.Vector4 NegativeInfinity { get { throw null; } } + public static System.Numerics.Vector4 NegativeZero { get { throw null; } } public static System.Numerics.Vector4 One { get { throw null; } } + public static System.Numerics.Vector4 Pi { get { throw null; } } + public static System.Numerics.Vector4 PositiveInfinity { get { throw null; } } + public static System.Numerics.Vector4 Tau { get { throw null; } } public static System.Numerics.Vector4 UnitW { get { throw null; } } public static System.Numerics.Vector4 UnitX { get { throw null; } } public static System.Numerics.Vector4 UnitY { get { throw null; } } @@ -575,6 +675,8 @@ 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 ClampNative(System.Numerics.Vector4 value1, System.Numerics.Vector4 min, System.Numerics.Vector4 max) { throw null; } + public static System.Numerics.Vector4 CopySign(System.Numerics.Vector4 value, System.Numerics.Vector4 sign) { 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; } @@ -584,6 +686,7 @@ public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } public readonly void CopyTo(System.Span destination) { } public readonly bool TryCopyTo(System.Span destination) { throw null; } + public static System.Numerics.Vector4 DegreesToRadians(System.Numerics.Vector4 degrees) { throw null; } public static float Distance(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } public static float DistanceSquared(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } public static System.Numerics.Vector4 Divide(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } @@ -591,13 +694,26 @@ public readonly void CopyTo(System.Span destination) { } public static float Dot(System.Numerics.Vector4 vector1, System.Numerics.Vector4 vector2) { throw null; } public readonly bool Equals(System.Numerics.Vector4 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public static System.Numerics.Vector4 Exp(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 FusedMultiplyAdd(System.Numerics.Vector4 left, System.Numerics.Vector4 right, System.Numerics.Vector4 addend) { throw null; } public override readonly int GetHashCode() { throw null; } public readonly float Length() { throw null; } public readonly float LengthSquared() { throw null; } + public static System.Numerics.Vector4 Hypot(System.Numerics.Vector4 x, System.Numerics.Vector4 y) { throw null; } public static System.Numerics.Vector4 Lerp(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2, float amount) { throw null; } + public static System.Numerics.Vector4 Lerp(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2, System.Numerics.Vector4 amount) { throw null; } + public static System.Numerics.Vector4 Log(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 Log2(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 Max(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } + public static System.Numerics.Vector4 MaxMagnitude(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } + public static System.Numerics.Vector4 MaxMagnitudeNumber(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } + public static System.Numerics.Vector4 MaxNative(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } + public static System.Numerics.Vector4 MaxNumber(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } public static System.Numerics.Vector4 Min(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } + public static System.Numerics.Vector4 MinMagnitude(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } + public static System.Numerics.Vector4 MinMagnitudeNumber(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } + public static System.Numerics.Vector4 MinNative(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } + public static System.Numerics.Vector4 MinNumber(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } public static System.Numerics.Vector4 Multiply(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 Multiply(System.Numerics.Vector4 left, float right) { throw null; } public static System.Numerics.Vector4 Multiply(float left, System.Numerics.Vector4 right) { throw null; } @@ -614,6 +730,9 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector4 operator *(float left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 operator -(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 operator -(System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector4 RadiansToDegrees(System.Numerics.Vector4 radians) { throw null; } + public static System.Numerics.Vector4 Round(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 Round(System.Numerics.Vector4 vector, System.MidpointRounding mode) { throw null; } public static System.Numerics.Vector4 SquareRoot(System.Numerics.Vector4 value) { throw null; } public static System.Numerics.Vector4 Subtract(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public override readonly string ToString() { throw null; } @@ -625,6 +744,7 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector4 Transform(System.Numerics.Vector3 value, System.Numerics.Quaternion rotation) { throw null; } public static System.Numerics.Vector4 Transform(System.Numerics.Vector4 vector, System.Numerics.Matrix4x4 matrix) { throw null; } public static System.Numerics.Vector4 Transform(System.Numerics.Vector4 value, System.Numerics.Quaternion rotation) { throw null; } + public static System.Numerics.Vector4 Truncate(System.Numerics.Vector4 vector) { throw null; } } public readonly partial struct Vector : System.IEquatable>, System.IFormattable { diff --git a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs index 02c7d3fa8a878..8caf901a258be 100644 --- a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -8,7 +8,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; -using System.Runtime.Intrinsics.Tests.Vectors; +using System.Tests; using Xunit; using Xunit.Sdk; @@ -4537,35 +4537,442 @@ private static void TestCreateSequence(T start, T step) } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + [MemberData(nameof(GenericMathTestMemberData.ExpDouble), MemberType = typeof(GenericMathTestMemberData))] + public void ExpDoubleTest(double value, double expectedResult, double variance) { - Vector actualResult = Vector.FusedMultiplyAdd(new Vector(left), new Vector(right), new Vector(addend)); - AssertEqual(new Vector(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector.Zero); + Vector actualResult = Vector.Exp(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Create(variance)); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.ExpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ExpSingleTest(float value, float expectedResult, float variance) { - Vector actualResult = Vector.FusedMultiplyAdd(new Vector(left), new Vector(right), new Vector(addend)); - AssertEqual(new Vector(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector.Zero); + Vector actualResult = Vector.Exp(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Create(variance)); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) + [MemberData(nameof(GenericMathTestMemberData.LogDouble), MemberType = typeof(GenericMathTestMemberData))] + public void LogDoubleTest(double value, double expectedResult, double variance) { - Vector actualResult = Vector.MultiplyAddEstimate(new Vector(left), new Vector(right), new Vector(addend)); - AssertEqual(new Vector(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector.Zero); + Vector actualResult = Vector.Log(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Create(variance)); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.LogSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LogSingleTest(float value, float expectedResult, float variance) { - Vector actualResult = Vector.MultiplyAddEstimate(new Vector(left), new Vector(right), new Vector(addend)); - AssertEqual(new Vector(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector.Zero); + Vector actualResult = Vector.Log(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.Log2Double), MemberType = typeof(GenericMathTestMemberData))] + public void Log2DoubleTest(double value, double expectedResult, double variance) + { + Vector actualResult = Vector.Log2(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] + public void Log2SingleTest(float value, float expectedResult, float variance) + { + Vector actualResult = Vector.Log2(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddDouble), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend, double expectedResult) + { + AssertEqual(Vector.Create(expectedResult), Vector.FusedMultiplyAdd(Vector.Create(left), Vector.Create(right), Vector.Create(addend)), Vector.Zero); + AssertEqual(Vector.Create(double.MultiplyAddEstimate(left, right, addend)), Vector.MultiplyAddEstimate(Vector.Create(left), Vector.Create(right), Vector.Create(addend)), Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddSingle), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend, float expectedResult) + { + AssertEqual(Vector.Create(expectedResult), Vector.FusedMultiplyAdd(Vector.Create(left), Vector.Create(right), Vector.Create(addend)), Vector.Zero); + AssertEqual(Vector.Create(float.MultiplyAddEstimate(left, right, addend)), Vector.MultiplyAddEstimate(Vector.Create(left), Vector.Create(right), Vector.Create(addend)), Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampDouble), MemberType = typeof(GenericMathTestMemberData))] + public void ClampDoubleTest(double x, double min, double max, double expectedResult) + { + Vector actualResult = Vector.Clamp(Vector.Create(x), Vector.Create(min), Vector.Create(max)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ClampSingleTest(float x, float min, float max, float expectedResult) + { + Vector actualResult = Vector.Clamp(Vector.Create(x), Vector.Create(min), Vector.Create(max)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignDouble), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignDoubleTest(double x, double y, double expectedResult) + { + Vector actualResult = Vector.CopySign(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignSingle), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignSingleTest(float x, float y, float expectedResult) + { + Vector actualResult = Vector.CopySign(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansDouble), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansDoubleTest(double value, double expectedResult, double variance) + { + Vector actualResult1 = Vector.DegreesToRadians(Vector.Create(-value)); + AssertEqual(Vector.Create(-expectedResult), actualResult1, Vector.Create(variance)); + + Vector actualResult2 = Vector.DegreesToRadians(Vector.Create(+value)); + AssertEqual(Vector.Create(+expectedResult), actualResult2, Vector.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansSingle), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector.Create(-expectedResult), Vector.DegreesToRadians(Vector.Create(-value)), Vector.Create(variance)); + AssertEqual(Vector.Create(+expectedResult), Vector.DegreesToRadians(Vector.Create(+value)), Vector.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotDouble), MemberType = typeof(GenericMathTestMemberData))] + public void HypotDoubleTest(double x, double y, double expectedResult, double variance) + { + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(-x), Vector.Create(-y)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(-x), Vector.Create(+y)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(+x), Vector.Create(-y)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(+x), Vector.Create(+y)), Vector.Create(variance)); + + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(-y), Vector.Create(-x)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(-y), Vector.Create(+x)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(+y), Vector.Create(-x)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(+y), Vector.Create(+x)), Vector.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotSingle), MemberType = typeof(GenericMathTestMemberData))] + public void HypotSingleTest(float x, float y, float expectedResult, float variance) + { + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(-x), Vector.Create(-y)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(-x), Vector.Create(+y)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(+x), Vector.Create(-y)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(+x), Vector.Create(+y)), Vector.Create(variance)); + + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(-y), Vector.Create(-x)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(-y), Vector.Create(+x)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(+y), Vector.Create(-x)), Vector.Create(variance)); + AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(+y), Vector.Create(+x)), Vector.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsNaN(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsNaN(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsNegative(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsNegative(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositive(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositive(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositiveInfinity(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositiveInfinity(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsZero(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsZero(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] + public void LerpDoubleTest(double x, double y, double amount, double expectedResult) + { + AssertEqual(Vector.Create(+expectedResult), Vector.Lerp(Vector.Create(+x), Vector.Create(+y), Vector.Create(amount)), Vector.Zero); + AssertEqual(Vector.Create((expectedResult == 0.0) ? expectedResult : -expectedResult), Vector.Lerp(Vector.Create(-x), Vector.Create(-y), Vector.Create(amount)), Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LerpSingleTest(float x, float y, float amount, float expectedResult) + { + AssertEqual(Vector.Create(+expectedResult), Vector.Lerp(Vector.Create(+x), Vector.Create(+y), Vector.Create(amount)), Vector.Zero); + AssertEqual(Vector.Create((expectedResult == 0.0f) ? expectedResult : -expectedResult), Vector.Lerp(Vector.Create(-x), Vector.Create(-y), Vector.Create(amount)), Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxDoubleTest(double x, double y, double expectedResult) + { + Vector actualResult = Vector.Max(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxSingleTest(float x, float y, float expectedResult) + { + Vector actualResult = Vector.Max(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector actualResult = Vector.MaxMagnitude(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector actualResult = Vector.MaxMagnitude(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector actualResult = Vector.MaxMagnitudeNumber(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector actualResult = Vector.MaxMagnitudeNumber(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberDoubleTest(double x, double y, double expectedResult) + { + Vector actualResult = Vector.MaxNumber(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberSingleTest(float x, float y, float expectedResult) + { + Vector actualResult = Vector.MaxNumber(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinDoubleTest(double x, double y, double expectedResult) + { + Vector actualResult = Vector.Min(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinSingleTest(float x, float y, float expectedResult) + { + Vector actualResult = Vector.Min(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector actualResult = Vector.MinMagnitude(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector actualResult = Vector.MinMagnitude(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector actualResult = Vector.MinMagnitudeNumber(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector actualResult = Vector.MinMagnitudeNumber(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberDoubleTest(double x, double y, double expectedResult) + { + Vector actualResult = Vector.MinNumber(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberSingleTest(float x, float y, float expectedResult) + { + Vector actualResult = Vector.MinNumber(Vector.Create(x), Vector.Create(y)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesDoubleTest(double value, double expectedResult, double variance) + { + AssertEqual(Vector.Create(-expectedResult), Vector.RadiansToDegrees(Vector.Create(-value)), Vector.Create(variance)); + AssertEqual(Vector.Create(+expectedResult), Vector.RadiansToDegrees(Vector.Create(+value)), Vector.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector.Create(-expectedResult), Vector.RadiansToDegrees(Vector.Create(-value)), Vector.Create(variance)); + AssertEqual(Vector.Create(+expectedResult), Vector.RadiansToDegrees(Vector.Create(+value)), Vector.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundDoubleTest(double value, double expectedResult) + { + Vector actualResult = Vector.Round(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundSingleTest(float value, float expectedResult) + { + Vector actualResult = Vector.Round(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroDoubleTest(double value, double expectedResult) + { + Vector actualResult = Vector.Round(Vector.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroSingleTest(float value, float expectedResult) + { + Vector actualResult = Vector.Round(Vector.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenDoubleTest(double value, double expectedResult) + { + Vector actualResult = Vector.Round(Vector.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenSingleTest(float value, float expectedResult) + { + Vector actualResult = Vector.Round(Vector.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateDouble), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateDoubleTest(double value, double expectedResult) + { + Vector actualResult = Vector.Truncate(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateSingle), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateSingleTest(float value, float expectedResult) + { + Vector actualResult = Vector.Truncate(Vector.Create(value)); + AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj b/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj index 243d1490ced0e..d6b26bdac8e45 100644 --- a/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj +++ b/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj @@ -18,6 +18,6 @@ - + diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs index 0472832009f4d..3d130d2655609 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.Tests.Vectors; +using System.Tests; using Xunit; namespace System.Numerics.Tests @@ -1300,19 +1300,186 @@ private class EmbeddedVectorObject } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.ExpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ExpSingleTest(float value, float expectedResult, float variance) { - Vector2 actualResult = Vector2.FusedMultiplyAdd(new Vector2(left), new Vector2(right), new Vector2(addend)); - AssertEqual(new Vector2(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector2.Zero); + Vector2 actualResult = Vector2.Exp(Vector2.Create(value)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Create(variance)); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.LogSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LogSingleTest(float value, float expectedResult, float variance) { - Vector2 actualResult = Vector2.MultiplyAddEstimate(new Vector2(left), new Vector2(right), new Vector2(addend)); - AssertEqual(new Vector2(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector2.Zero); + Vector2 actualResult = Vector2.Log(Vector2.Create(value)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] + public void Log2SingleTest(float value, float expectedResult, float variance) + { + Vector2 actualResult = Vector2.Log2(Vector2.Create(value)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddSingle), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend, float expectedResult) + { + AssertEqual(Vector2.Create(expectedResult), Vector2.FusedMultiplyAdd(Vector2.Create(left), Vector2.Create(right), Vector2.Create(addend)), Vector2.Zero); + AssertEqual(Vector2.Create(float.MultiplyAddEstimate(left, right, addend)), Vector2.MultiplyAddEstimate(Vector2.Create(left), Vector2.Create(right), Vector2.Create(addend)), Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ClampSingleTest(float x, float min, float max, float expectedResult) + { + Vector2 actualResult = Vector2.Clamp(Vector2.Create(x), Vector2.Create(min), Vector2.Create(max)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignSingle), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignSingleTest(float x, float y, float expectedResult) + { + Vector2 actualResult = Vector2.CopySign(Vector2.Create(x), Vector2.Create(y)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansSingle), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector2.Create(-expectedResult), Vector2.DegreesToRadians(Vector2.Create(-value)), Vector2.Create(variance)); + AssertEqual(Vector2.Create(+expectedResult), Vector2.DegreesToRadians(Vector2.Create(+value)), Vector2.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotSingle), MemberType = typeof(GenericMathTestMemberData))] + public void HypotSingleTest(float x, float y, float expectedResult, float variance) + { + AssertEqual(Vector2.Create(expectedResult), Vector2.Hypot(Vector2.Create(-x), Vector2.Create(-y)), Vector2.Create(variance)); + AssertEqual(Vector2.Create(expectedResult), Vector2.Hypot(Vector2.Create(-x), Vector2.Create(+y)), Vector2.Create(variance)); + AssertEqual(Vector2.Create(expectedResult), Vector2.Hypot(Vector2.Create(+x), Vector2.Create(-y)), Vector2.Create(variance)); + AssertEqual(Vector2.Create(expectedResult), Vector2.Hypot(Vector2.Create(+x), Vector2.Create(+y)), Vector2.Create(variance)); + + AssertEqual(Vector2.Create(expectedResult), Vector2.Hypot(Vector2.Create(-y), Vector2.Create(-x)), Vector2.Create(variance)); + AssertEqual(Vector2.Create(expectedResult), Vector2.Hypot(Vector2.Create(-y), Vector2.Create(+x)), Vector2.Create(variance)); + AssertEqual(Vector2.Create(expectedResult), Vector2.Hypot(Vector2.Create(+y), Vector2.Create(-x)), Vector2.Create(variance)); + AssertEqual(Vector2.Create(expectedResult), Vector2.Hypot(Vector2.Create(+y), Vector2.Create(+x)), Vector2.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LerpSingleTest(float x, float y, float amount, float expectedResult) + { + AssertEqual(Vector2.Create(+expectedResult), Vector2.Lerp(Vector2.Create(+x), Vector2.Create(+y), Vector2.Create(amount)), Vector2.Zero); + AssertEqual(Vector2.Create((expectedResult == 0.0f) ? expectedResult : -expectedResult), Vector2.Lerp(Vector2.Create(-x), Vector2.Create(-y), Vector2.Create(amount)), Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxSingleTest(float x, float y, float expectedResult) + { + Vector2 actualResult = Vector2.Max(Vector2.Create(x), Vector2.Create(y)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector2 actualResult = Vector2.MaxMagnitude(Vector2.Create(x), Vector2.Create(y)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector2 actualResult = Vector2.MaxMagnitudeNumber(Vector2.Create(x), Vector2.Create(y)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberSingleTest(float x, float y, float expectedResult) + { + Vector2 actualResult = Vector2.MaxNumber(Vector2.Create(x), Vector2.Create(y)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinSingleTest(float x, float y, float expectedResult) + { + Vector2 actualResult = Vector2.Min(Vector2.Create(x), Vector2.Create(y)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector2 actualResult = Vector2.MinMagnitude(Vector2.Create(x), Vector2.Create(y)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector2 actualResult = Vector2.MinMagnitudeNumber(Vector2.Create(x), Vector2.Create(y)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberSingleTest(float x, float y, float expectedResult) + { + Vector2 actualResult = Vector2.MinNumber(Vector2.Create(x), Vector2.Create(y)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector2.Create(-expectedResult), Vector2.RadiansToDegrees(Vector2.Create(-value)), Vector2.Create(variance)); + AssertEqual(Vector2.Create(+expectedResult), Vector2.RadiansToDegrees(Vector2.Create(+value)), Vector2.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundSingleTest(float value, float expectedResult) + { + Vector2 actualResult = Vector2.Round(Vector2.Create(value)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroSingleTest(float value, float expectedResult) + { + Vector2 actualResult = Vector2.Round(Vector2.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenSingleTest(float value, float expectedResult) + { + Vector2 actualResult = Vector2.Round(Vector2.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateSingle), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateSingleTest(float value, float expectedResult) + { + Vector2 actualResult = Vector2.Truncate(Vector2.Create(value)); + AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs index 4d0e97526a918..9ec5e50423938 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.Tests.Vectors; +using System.Tests; using Xunit; namespace System.Numerics.Tests @@ -1350,19 +1350,186 @@ private class EmbeddedVectorObject } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.ExpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ExpSingleTest(float value, float expectedResult, float variance) { - Vector3 actualResult = Vector3.FusedMultiplyAdd(new Vector3(left), new Vector3(right), new Vector3(addend)); - AssertEqual(new Vector3(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector3.Zero); + Vector3 actualResult = Vector3.Exp(Vector3.Create(value)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Create(variance)); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.LogSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LogSingleTest(float value, float expectedResult, float variance) { - Vector3 actualResult = Vector3.MultiplyAddEstimate(new Vector3(left), new Vector3(right), new Vector3(addend)); - AssertEqual(new Vector3(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector3.Zero); + Vector3 actualResult = Vector3.Log(Vector3.Create(value)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] + public void Log2SingleTest(float value, float expectedResult, float variance) + { + Vector3 actualResult = Vector3.Log2(Vector3.Create(value)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddSingle), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend, float expectedResult) + { + AssertEqual(Vector3.Create(expectedResult), Vector3.FusedMultiplyAdd(Vector3.Create(left), Vector3.Create(right), Vector3.Create(addend)), Vector3.Zero); + AssertEqual(Vector3.Create(float.MultiplyAddEstimate(left, right, addend)), Vector3.MultiplyAddEstimate(Vector3.Create(left), Vector3.Create(right), Vector3.Create(addend)), Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ClampSingleTest(float x, float min, float max, float expectedResult) + { + Vector3 actualResult = Vector3.Clamp(Vector3.Create(x), Vector3.Create(min), Vector3.Create(max)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignSingle), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignSingleTest(float x, float y, float expectedResult) + { + Vector3 actualResult = Vector3.CopySign(Vector3.Create(x), Vector3.Create(y)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansSingle), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector3.Create(-expectedResult), Vector3.DegreesToRadians(Vector3.Create(-value)), Vector3.Create(variance)); + AssertEqual(Vector3.Create(+expectedResult), Vector3.DegreesToRadians(Vector3.Create(+value)), Vector3.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotSingle), MemberType = typeof(GenericMathTestMemberData))] + public void HypotSingleTest(float x, float y, float expectedResult, float variance) + { + AssertEqual(Vector3.Create(expectedResult), Vector3.Hypot(Vector3.Create(-x), Vector3.Create(-y)), Vector3.Create(variance)); + AssertEqual(Vector3.Create(expectedResult), Vector3.Hypot(Vector3.Create(-x), Vector3.Create(+y)), Vector3.Create(variance)); + AssertEqual(Vector3.Create(expectedResult), Vector3.Hypot(Vector3.Create(+x), Vector3.Create(-y)), Vector3.Create(variance)); + AssertEqual(Vector3.Create(expectedResult), Vector3.Hypot(Vector3.Create(+x), Vector3.Create(+y)), Vector3.Create(variance)); + + AssertEqual(Vector3.Create(expectedResult), Vector3.Hypot(Vector3.Create(-y), Vector3.Create(-x)), Vector3.Create(variance)); + AssertEqual(Vector3.Create(expectedResult), Vector3.Hypot(Vector3.Create(-y), Vector3.Create(+x)), Vector3.Create(variance)); + AssertEqual(Vector3.Create(expectedResult), Vector3.Hypot(Vector3.Create(+y), Vector3.Create(-x)), Vector3.Create(variance)); + AssertEqual(Vector3.Create(expectedResult), Vector3.Hypot(Vector3.Create(+y), Vector3.Create(+x)), Vector3.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LerpSingleTest(float x, float y, float amount, float expectedResult) + { + AssertEqual(Vector3.Create(+expectedResult), Vector3.Lerp(Vector3.Create(+x), Vector3.Create(+y), Vector3.Create(amount)), Vector3.Zero); + AssertEqual(Vector3.Create((expectedResult == 0.0f) ? expectedResult : -expectedResult), Vector3.Lerp(Vector3.Create(-x), Vector3.Create(-y), Vector3.Create(amount)), Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxSingleTest(float x, float y, float expectedResult) + { + Vector3 actualResult = Vector3.Max(Vector3.Create(x), Vector3.Create(y)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector3 actualResult = Vector3.MaxMagnitude(Vector3.Create(x), Vector3.Create(y)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector3 actualResult = Vector3.MaxMagnitudeNumber(Vector3.Create(x), Vector3.Create(y)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberSingleTest(float x, float y, float expectedResult) + { + Vector3 actualResult = Vector3.MaxNumber(Vector3.Create(x), Vector3.Create(y)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinSingleTest(float x, float y, float expectedResult) + { + Vector3 actualResult = Vector3.Min(Vector3.Create(x), Vector3.Create(y)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector3 actualResult = Vector3.MinMagnitude(Vector3.Create(x), Vector3.Create(y)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector3 actualResult = Vector3.MinMagnitudeNumber(Vector3.Create(x), Vector3.Create(y)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberSingleTest(float x, float y, float expectedResult) + { + Vector3 actualResult = Vector3.MinNumber(Vector3.Create(x), Vector3.Create(y)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector3.Create(-expectedResult), Vector3.RadiansToDegrees(Vector3.Create(-value)), Vector3.Create(variance)); + AssertEqual(Vector3.Create(+expectedResult), Vector3.RadiansToDegrees(Vector3.Create(+value)), Vector3.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundSingleTest(float value, float expectedResult) + { + Vector3 actualResult = Vector3.Round(Vector3.Create(value)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroSingleTest(float value, float expectedResult) + { + Vector3 actualResult = Vector3.Round(Vector3.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenSingleTest(float value, float expectedResult) + { + Vector3 actualResult = Vector3.Round(Vector3.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateSingle), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateSingleTest(float value, float expectedResult) + { + Vector3 actualResult = Vector3.Truncate(Vector3.Create(value)); + AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs index b3759a716a028..d1144cdf3e5cd 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.Tests.Vectors; +using System.Tests; using Xunit; namespace System.Numerics.Tests @@ -1725,19 +1725,186 @@ public struct Level7 #pragma warning restore 0169 [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.ExpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ExpSingleTest(float value, float expectedResult, float variance) { - Vector4 actualResult = Vector4.FusedMultiplyAdd(new Vector4(left), new Vector4(right), new Vector4(addend)); - AssertEqual(new Vector4(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector4.Zero); + Vector4 actualResult = Vector4.Exp(Vector4.Create(value)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Create(variance)); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.LogSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LogSingleTest(float value, float expectedResult, float variance) { - Vector4 actualResult = Vector4.MultiplyAddEstimate(new Vector4(left), new Vector4(right), new Vector4(addend)); - AssertEqual(new Vector4(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector4.Zero); + Vector4 actualResult = Vector4.Log(Vector4.Create(value)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] + public void Log2SingleTest(float value, float expectedResult, float variance) + { + Vector4 actualResult = Vector4.Log2(Vector4.Create(value)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddSingle), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend, float expectedResult) + { + AssertEqual(Vector4.Create(expectedResult), Vector4.FusedMultiplyAdd(Vector4.Create(left), Vector4.Create(right), Vector4.Create(addend)), Vector4.Zero); + AssertEqual(Vector4.Create(float.MultiplyAddEstimate(left, right, addend)), Vector4.MultiplyAddEstimate(Vector4.Create(left), Vector4.Create(right), Vector4.Create(addend)), Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ClampSingleTest(float x, float min, float max, float expectedResult) + { + Vector4 actualResult = Vector4.Clamp(Vector4.Create(x), Vector4.Create(min), Vector4.Create(max)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignSingle), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignSingleTest(float x, float y, float expectedResult) + { + Vector4 actualResult = Vector4.CopySign(Vector4.Create(x), Vector4.Create(y)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansSingle), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector4.Create(-expectedResult), Vector4.DegreesToRadians(Vector4.Create(-value)), Vector4.Create(variance)); + AssertEqual(Vector4.Create(+expectedResult), Vector4.DegreesToRadians(Vector4.Create(+value)), Vector4.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotSingle), MemberType = typeof(GenericMathTestMemberData))] + public void HypotSingleTest(float x, float y, float expectedResult, float variance) + { + AssertEqual(Vector4.Create(expectedResult), Vector4.Hypot(Vector4.Create(-x), Vector4.Create(-y)), Vector4.Create(variance)); + AssertEqual(Vector4.Create(expectedResult), Vector4.Hypot(Vector4.Create(-x), Vector4.Create(+y)), Vector4.Create(variance)); + AssertEqual(Vector4.Create(expectedResult), Vector4.Hypot(Vector4.Create(+x), Vector4.Create(-y)), Vector4.Create(variance)); + AssertEqual(Vector4.Create(expectedResult), Vector4.Hypot(Vector4.Create(+x), Vector4.Create(+y)), Vector4.Create(variance)); + + AssertEqual(Vector4.Create(expectedResult), Vector4.Hypot(Vector4.Create(-y), Vector4.Create(-x)), Vector4.Create(variance)); + AssertEqual(Vector4.Create(expectedResult), Vector4.Hypot(Vector4.Create(-y), Vector4.Create(+x)), Vector4.Create(variance)); + AssertEqual(Vector4.Create(expectedResult), Vector4.Hypot(Vector4.Create(+y), Vector4.Create(-x)), Vector4.Create(variance)); + AssertEqual(Vector4.Create(expectedResult), Vector4.Hypot(Vector4.Create(+y), Vector4.Create(+x)), Vector4.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LerpSingleTest(float x, float y, float amount, float expectedResult) + { + AssertEqual(Vector4.Create(+expectedResult), Vector4.Lerp(Vector4.Create(+x), Vector4.Create(+y), Vector4.Create(amount)), Vector4.Zero); + AssertEqual(Vector4.Create((expectedResult == 0.0f) ? expectedResult : -expectedResult), Vector4.Lerp(Vector4.Create(-x), Vector4.Create(-y), Vector4.Create(amount)), Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxSingleTest(float x, float y, float expectedResult) + { + Vector4 actualResult = Vector4.Max(Vector4.Create(x), Vector4.Create(y)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector4 actualResult = Vector4.MaxMagnitude(Vector4.Create(x), Vector4.Create(y)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector4 actualResult = Vector4.MaxMagnitudeNumber(Vector4.Create(x), Vector4.Create(y)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberSingleTest(float x, float y, float expectedResult) + { + Vector4 actualResult = Vector4.MaxNumber(Vector4.Create(x), Vector4.Create(y)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinSingleTest(float x, float y, float expectedResult) + { + Vector4 actualResult = Vector4.Min(Vector4.Create(x), Vector4.Create(y)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector4 actualResult = Vector4.MinMagnitude(Vector4.Create(x), Vector4.Create(y)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector4 actualResult = Vector4.MinMagnitudeNumber(Vector4.Create(x), Vector4.Create(y)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberSingleTest(float x, float y, float expectedResult) + { + Vector4 actualResult = Vector4.MinNumber(Vector4.Create(x), Vector4.Create(y)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector4.Create(-expectedResult), Vector4.RadiansToDegrees(Vector4.Create(-value)), Vector4.Create(variance)); + AssertEqual(Vector4.Create(+expectedResult), Vector4.RadiansToDegrees(Vector4.Create(+value)), Vector4.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundSingleTest(float value, float expectedResult) + { + Vector4 actualResult = Vector4.Round(Vector4.Create(value)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroSingleTest(float value, float expectedResult) + { + Vector4 actualResult = Vector4.Round(Vector4.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenSingleTest(float value, float expectedResult) + { + Vector4 actualResult = Vector4.Round(Vector4.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateSingle), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateSingleTest(float value, float expectedResult) + { + Vector4 actualResult = Vector4.Truncate(Vector4.Create(value)); + AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 8d66af450f327..d38c67b916b18 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -874,7 +874,7 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinati public static int ILogB(double x) => Math.ILogB(x); /// - public static double Lerp(double value1, double value2, double amount) => (value1 * (1.0 - amount)) + (value2 * amount); + public static double Lerp(double value1, double value2, double amount) => MultiplyAddEstimate(value1, 1.0 - amount, value2 * amount); /// [Intrinsic] diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointIeee754.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointIeee754.cs index 4d3593f5c136f..08d0289f0c54a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointIeee754.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointIeee754.cs @@ -78,7 +78,7 @@ public interface IFloatingPointIeee754 /// A value, intended to be between 0 and 1, that indicates the weight of the interpolation. /// The interpolated value. /// This method presumes inputs are well formed and does not validate that value1 < value2 nor that 0 <= amount <= 1. - static virtual TSelf Lerp(TSelf value1, TSelf value2, TSelf amount) => (value1 * (TSelf.One - amount)) + (value2 * amount); + static virtual TSelf Lerp(TSelf value1, TSelf value2, TSelf amount) => TSelf.MultiplyAddEstimate(value1, TSelf.One - amount, value2 * amount); /// Computes an estimate of the reciprocal of a value. /// The value whose estimate of the reciprocal is to be computed. 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 509038ed4fac9..c4fbc114dc988 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -13,7 +13,7 @@ namespace System.Numerics [Intrinsic] public static unsafe partial class Vector { - internal static readonly nuint Alignment = (sizeof(Vector) == sizeof(Vector128)) ? (uint)(Vector128.Alignment) : (uint)(Vector256.Alignment); + internal static int Alignment => sizeof(Vector); /// Gets a value that indicates whether vector operations are subject to hardware acceleration through JIT intrinsic support. /// if vector operations are subject to hardware acceleration; otherwise, . @@ -207,6 +207,40 @@ public static Vector As(this Vector vector) [Intrinsic] public static Vector BitwiseOr(Vector left, Vector right) => left | right; + /// 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)] + internal static Vector Ceiling(Vector vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.Ceiling(vector.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + /// 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 . @@ -245,6 +279,22 @@ public static Vector Ceiling(Vector value) return result; } + /// + [Intrinsic] + public static Vector Clamp(Vector value, Vector min, Vector max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return Min(Max(value, min), max); + } + + /// + [Intrinsic] + public static Vector ClampNative(Vector value, Vector min, Vector max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return MinNative(MaxNative(value, min), max); + } + /// Conditionally selects a value from two vectors on a bitwise basis. /// The mask that is used to select a value from or . /// The vector that is selected when the corresponding bit in is one. @@ -487,6 +537,37 @@ public static Vector ConvertToUInt64Native(Vector value) return result; } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector CopySign(Vector value, Vector sign) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return value; + } + else if (IsHardwareAccelerated) + { + return VectorMath.CopySign, T>(value, sign); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T element = Scalar.CopySign(value.GetElementUnsafe(index), sign.GetElementUnsafe(index)); + result.SetElementUnsafe(index, element); + } + + 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. @@ -527,7 +608,7 @@ public static Vector Create(ReadOnlySpan values) /// 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) + internal static Vector CreateScalar(T value) { Vector result = Vector.Zero; result.SetElementUnsafe(0, value); @@ -562,6 +643,50 @@ internal static Vector CreateScalarUnsafe(T value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector CreateSequence(T start, T step) => (Vector.Indices * step) + Create(start); + internal static Vector DegreesToRadians(Vector degrees) + where T : ITrigonometricFunctions + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = T.DegreesToRadians(degrees.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector DegreesToRadians(Vector degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, double>(degrees); + } + else + { + return DegreesToRadians(degrees); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector DegreesToRadians(Vector degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, float>(degrees); + } + else + { + return DegreesToRadians(degrees); + } + } + /// Divides two vectors to compute their quotient. /// The vector that will be divided by . /// The vector that will divide . @@ -662,6 +787,82 @@ public static bool EqualsAny(Vector left, Vector right) return false; } + internal static Vector Exp(Vector vector) + where T : IExponentialFunctions + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = T.Exp(vector.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Exp(Vector vector) + { + if (IsHardwareAccelerated) + { + return VectorMath.ExpDouble, Vector, Vector>(vector); + } + else + { + return Exp(vector); + } + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Exp(Vector vector) + { + if (IsHardwareAccelerated) + { + return VectorMath.ExpSingle, Vector, Vector, Vector>(vector); + } + else + { + return Exp(vector); + } + } + + /// 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)] + internal static Vector Floor(Vector vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.Floor(vector.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + /// 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 . @@ -943,6 +1144,187 @@ public static bool GreaterThanOrEqualAny(Vector left, Vector right) return false; } + internal static Vector Hypot(Vector x, Vector y) + where T : IRootFunctions + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = T.Hypot(x.GetElementUnsafe(index), y.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Hypot(Vector x, Vector y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotDouble, Vector>(x, y); + } + else + { + return Hypot(x, y); + } + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Hypot(Vector x, Vector y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotSingle, Vector>(x, y); + } + else + { + return Hypot(x, y); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsNaN(Vector vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return ~Equals(vector, vector); + } + return Vector.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsNegative(Vector vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector.Zero; + } + else if (typeof(T) == typeof(float)) + { + return LessThan(vector.As(), Vector.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(vector.As(), Vector.Zero).As(); + } + else + { + return LessThan(vector, Vector.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsPositive(Vector vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector.AllBitsSet; + } + else if (typeof(T) == typeof(float)) + { + return GreaterThanOrEqual(vector.As(), Vector.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return GreaterThanOrEqual(vector.As(), Vector.Zero).As(); + } + else + { + return GreaterThanOrEqual(vector, Vector.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsPositiveInfinity(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.PositiveInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.PositiveInfinity).As()); + } + return Vector.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsZero(Vector vector) => Equals(vector, Vector.Zero); + + internal static Vector Lerp(Vector x, Vector y, Vector amount) + where T : IFloatingPointIeee754 + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = T.Lerp(x.GetElementUnsafe(index), y.GetElementUnsafe(index), amount.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// Performs a linear interpolation between two vectors based on the given weighting. + /// The first vector. + /// The second vector. + /// A value between 0 and 1 that indicates the weight of . + /// The interpolated vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Lerp(Vector x, Vector y, Vector amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, double>(x, y, amount); + } + else + { + return Lerp(x, y, amount); + } + } + + /// Performs a linear interpolation between two vectors based on the given weighting. + /// The first vector. + /// The second vector. + /// A value between 0 and 1 that indicates the weight of . + /// The interpolated vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Lerp(Vector x, Vector y, Vector amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, float>(x, y, amount); + } + else + { + return Lerp(x, y, amount); + } + } + /// Compares two vectors to determine which is less on a per-element basis. /// The vector to compare with . /// The vector to compare with . @@ -1141,7 +1523,7 @@ public static Vector LoadAligned(T* source) { ThrowHelper.ThrowForUnsupportedNumericsVectorBaseType(); - if (((nuint)(source) % Alignment) != 0) + if (((nuint)(source) % (uint)(Alignment)) != 0) { ThrowHelper.ThrowAccessViolationException(); } @@ -1190,46 +1572,320 @@ public static Vector LoadUnsafe(ref readonly T source, nuint elementOffset return Unsafe.ReadUnaligned>(in address); } - /// Computes the maximum of two vectors on a per-element basis. - /// The vector to compare with . - /// The vector to compare with . - /// The type of the elements in the vector. - /// A vector whose elements are the maximum of the corresponding elements in and . - [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector Max(Vector left, Vector right) + internal static Vector Log(Vector vector) + where T : ILogarithmicFunctions { Unsafe.SkipInit(out Vector result); for (int index = 0; index < Vector.Count; index++) { - T value = Scalar.GreaterThan(left.GetElementUnsafe(index), right.GetElementUnsafe(index)) ? left.GetElementUnsafe(index) : right.GetElementUnsafe(index); + T value = T.Log(vector.GetElementUnsafe(index)); result.SetElementUnsafe(index, value); } return result; } - /// Computes the minimum of two vectors on a per-element basis. - /// The vector to compare with . - /// The vector to compare with . - /// The type of the elements in the vector. - /// A vector whose elements are the minimum of the corresponding elements in and . - [Intrinsic] + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector Min(Vector left, Vector right) + public static Vector Log(Vector vector) + { + if (IsHardwareAccelerated) + { + return VectorMath.LogDouble, Vector, Vector>(vector); + } + else + { + return Log(vector); + } + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Log(Vector vector) + { + if (IsHardwareAccelerated) + { + return VectorMath.LogSingle, Vector, Vector>(vector); + } + else + { + return Log(vector); + } + } + + internal static Vector Log2(Vector vector) + where T : ILogarithmicFunctions { Unsafe.SkipInit(out Vector result); for (int index = 0; index < Vector.Count; index++) { - T value = Scalar.LessThan(left.GetElementUnsafe(index), right.GetElementUnsafe(index)) ? left.GetElementUnsafe(index) : right.GetElementUnsafe(index); + T value = T.Log2(vector.GetElementUnsafe(index)); result.SetElementUnsafe(index, value); } return result; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Log2(Vector vector) + { + if (IsHardwareAccelerated) + { + return VectorMath.Log2Double, Vector, Vector>(vector); + } + else + { + return Log2(vector); + } + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Log2(Vector vector) + { + if (IsHardwareAccelerated) + { + return VectorMath.Log2Single, Vector, Vector>(vector); + } + else + { + return Log2(vector); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Max(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return VectorMath.Max, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.Max(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MaxMagnitude(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxMagnitude, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.MaxMagnitude(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MaxMagnitudeNumber(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxMagnitudeNumber, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.MaxMagnitudeNumber(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MaxNative(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(GreaterThan(left, right), left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.GreaterThan(left.GetElementUnsafe(index), right.GetElementUnsafe(index)) ? left.GetElementUnsafe(index) : right.GetElementUnsafe(index); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MaxNumber(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxNumber, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.MaxNumber(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector Min(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return VectorMath.Min, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.Min(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MinMagnitude(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinMagnitude, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.MinMagnitude(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MinMagnitudeNumber(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinMagnitudeNumber, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.MinMagnitudeNumber(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MinNative(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(LessThan(left, right), left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.LessThan(left.GetElementUnsafe(index), right.GetElementUnsafe(index)) ? left.GetElementUnsafe(index) : right.GetElementUnsafe(index); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MinNumber(Vector left, Vector right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinNumber, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.MinNumber(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + /// Multiplies two vectors to compute their element-wise product. /// The vector to multiply with . /// The vector to multiply with . @@ -1254,6 +1910,21 @@ public static Vector Min(Vector left, Vector right) [Intrinsic] public static Vector Multiply(T left, Vector right) => right * left; + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector MultiplyAddEstimate(Vector left, Vector right, Vector addend) + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.MultiplyAddEstimate(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1479,6 +2150,95 @@ public static Vector Narrow(Vector low, Vector high) [Intrinsic] public static Vector OnesComplement(Vector value) => ~value; + internal static Vector RadiansToDegrees(Vector radians) + where T : ITrigonometricFunctions + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = T.RadiansToDegrees(radians.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// + [Intrinsic] + public static Vector RadiansToDegrees(Vector radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, double>(radians); + } + else + { + return RadiansToDegrees(radians); + } + } + + /// + [Intrinsic] + public static Vector RadiansToDegrees(Vector radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, float>(radians); + } + else + { + return RadiansToDegrees(radians); + } + } + + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector Round(Vector vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.Round(vector.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + public static Vector Round(Vector vector) => Round(vector); + + /// + [Intrinsic] + public static Vector Round(Vector vector) => Round(vector); + + /// + [Intrinsic] + public static Vector Round(Vector vector, MidpointRounding mode) => VectorMath.RoundDouble(vector, mode); + + /// + [Intrinsic] + public static Vector Round(Vector vector, MidpointRounding mode) => VectorMath.RoundSingle(vector, mode); + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -1706,7 +2466,7 @@ public static void StoreAligned(this Vector source, T* destination) { ThrowHelper.ThrowForUnsupportedNumericsVectorBaseType(); - if (((nuint)destination % Alignment) != 0) + if (((nuint)destination % (uint)(Alignment)) != 0) { ThrowHelper.ThrowAccessViolationException(); } @@ -1792,6 +2552,87 @@ public static T ToScalar(this Vector vector) return vector.GetElementUnsafe(0); } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector Truncate(Vector vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + T value = Scalar.Truncate(vector.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + public static Vector Truncate(Vector vector) => Truncate(vector); + + /// + [Intrinsic] + public static Vector Truncate(Vector vector) => Truncate(vector); + + /// Widens a into two . + /// The vector whose elements are to be widened. + /// A pair of vectors that contain the widened lower and upper halves of . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static (Vector Lower, Vector Upper) Widen(Vector source) => (WidenLower(source), WidenUpper(source)); + + /// Widens a into two . + /// The vector whose elements are to be widened. + /// A pair of vectors that contain the widened lower and upper halves of . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static (Vector Lower, Vector Upper) Widen(Vector source) => (WidenLower(source), WidenUpper(source)); + + /// Widens a into two . + /// The vector whose elements are to be widened. + /// A pair of vectors that contain the widened lower and upper halves of . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static (Vector Lower, Vector Upper) Widen(Vector source) => (WidenLower(source), WidenUpper(source)); + + /// Widens a into two . + /// The vector whose elements are to be widened. + /// A pair of vectors that contain the widened lower and upper halves of . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static (Vector Lower, Vector Upper) Widen(Vector source) => (WidenLower(source), WidenUpper(source)); + + /// Widens a into two . + /// The vector whose elements are to be widened. + /// A pair of vectors that contain the widened lower and upper halves of . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static (Vector Lower, Vector Upper) Widen(Vector source) => (WidenLower(source), WidenUpper(source)); + + /// Widens a into two . + /// The vector whose elements are to be widened. + /// A pair of vectors that contain the widened lower and upper halves of . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static (Vector Lower, Vector Upper) Widen(Vector source) => (WidenLower(source), WidenUpper(source)); + + /// Widens a into two . + /// The vector whose elements are to be widened. + /// A pair of vectors that contain the widened lower and upper halves of . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static (Vector Lower, Vector Upper) Widen(Vector source) => (WidenLower(source), WidenUpper(source)); + /// Widens a into two . /// The vector whose elements are to be widened. /// A vector that will contain the widened result of the lower half of . 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 cd4a2c5c0358e..e101a75ea9154 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -50,22 +50,69 @@ public Vector2(ReadOnlySpan values) this = Create(values); } - /// Returns a vector whose 2 elements are equal to zero. - /// A vector whose two elements are equal to zero (that is, it returns the vector (0,0). - public static Vector2 Zero + /// + public static Vector2 E { [Intrinsic] - get => default; + get => Create(float.E); } - /// Gets a vector whose 2 elements are equal to one. - /// A vector whose two elements are equal to one (that is, it returns the vector (1,1). + /// + public static Vector2 Epsilon + { + [Intrinsic] + get => Create(float.Epsilon); + } + + /// + public static Vector2 NaN + { + [Intrinsic] + get => Create(float.NaN); + } + + /// + public static Vector2 NegativeInfinity + { + [Intrinsic] + get => Create(float.NegativeInfinity); + } + + /// + public static Vector2 NegativeZero + { + [Intrinsic] + get => Create(float.NegativeZero); + } + + /// public static Vector2 One { [Intrinsic] get => Create(1.0f); } + /// + public static Vector2 Pi + { + [Intrinsic] + get => Create(float.Pi); + } + + /// + public static Vector2 PositiveInfinity + { + [Intrinsic] + get => Create(float.PositiveInfinity); + } + + /// + public static Vector2 Tau + { + [Intrinsic] + get => Create(float.Tau); + } + /// Gets the vector (1,0). /// The vector (1,0). public static Vector2 UnitX @@ -82,6 +129,13 @@ public static Vector2 UnitY get => Create(0.0f, 1.0f); } + /// + public static Vector2 Zero + { + [Intrinsic] + get => default; + } + /// Gets or sets the element at the specified index. /// The index of the element to get or set. /// The the element at . @@ -211,17 +265,20 @@ readonly get [Intrinsic] public static Vector2 Add(Vector2 left, Vector2 right) => left + right; - /// Restricts a vector between a minimum and a maximum value. - /// The vector to restrict. - /// The minimum value. - /// The maximum value. - /// The restricted vector. + /// [Intrinsic] - public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max) - { - // We must follow HLSL behavior in the case user specified min value is bigger than max value. - return Min(Max(value1, min), max); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max) => Vector128.Clamp(value1.AsVector128Unsafe(), min.AsVector128Unsafe(), max.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 ClampNative(Vector2 value1, Vector2 min, Vector2 max) => Vector128.ClampNative(value1.AsVector128Unsafe(), min.AsVector128Unsafe(), max.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 CopySign(Vector2 value, Vector2 sign) => Vector128.CopySign(value.AsVector128Unsafe(), sign.AsVector128Unsafe()).AsVector2(); /// Creates a new object whose two elements have the same value. /// The value to assign to all two elements. @@ -261,6 +318,11 @@ public static Vector2 Create(ReadOnlySpan values) [Intrinsic] internal static Vector2 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector2(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 DegreesToRadians(Vector2 degrees) => Vector128.DegreesToRadians(degrees.AsVector128Unsafe()).AsVector2(); + /// Computes the Euclidean distance between the two given points. /// The first point. /// The second point. @@ -297,39 +359,88 @@ public static Vector2 Create(ReadOnlySpan values) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Dot(Vector2 value1, Vector2 value2) => Vector128.Dot(value1.AsVector128(), value2.AsVector128()); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 Exp(Vector2 vector) => Vector128.Exp(vector.AsVector128Unsafe()).AsVector2(); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] 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. - /// The second vector. - /// A value between 0 and 1 that indicates the weight of . - /// The interpolated vector. - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount) => MultiplyAddEstimate(value1, Create(1.0f - amount), value2 * amount); + public static Vector2 Hypot(Vector2 x, Vector2 y) => Vector128.Hypot(x.AsVector128Unsafe(), y.AsVector128Unsafe()).AsVector2(); - /// Returns a vector whose elements are the maximum of each of the pairs of elements in two specified vectors. - /// The first vector. - /// The second vector. - /// The maximized vector. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount) => Lerp(value1, value2, Create(amount)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 Lerp(Vector2 value1, Vector2 value2, Vector2 amount) => Vector128.Lerp(value1.AsVector128Unsafe(), value2.AsVector128Unsafe(), amount.AsVector128Unsafe()).AsVector2(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 Log(Vector2 vector) => Vector128.Log(vector.AsVector128Unsafe()).AsVector2(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 Log2(Vector2 vector) => Vector128.Log2(vector.AsVector128Unsafe()).AsVector2(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] 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. - /// The second vector. - /// The minimized vector. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 MaxMagnitude(Vector2 value1, Vector2 value2) => Vector128.MaxMagnitude(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 MaxMagnitudeNumber(Vector2 value1, Vector2 value2) => Vector128.MaxMagnitudeNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 MaxNative(Vector2 value1, Vector2 value2) => Vector128.MaxNative(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 MaxNumber(Vector2 value1, Vector2 value2) => Vector128.MaxNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Min(Vector2 value1, Vector2 value2) => Vector128.Min(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 MinMagnitude(Vector2 value1, Vector2 value2) => Vector128.MinMagnitude(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 MinMagnitudeNumber(Vector2 value1, Vector2 value2) => Vector128.MinMagnitudeNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 MinNative(Vector2 value1, Vector2 value2) => Vector128.MinNative(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 MinNumber(Vector2 value1, Vector2 value2) => Vector128.MinNumber(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. /// The second vector. @@ -368,6 +479,11 @@ public static Vector2 Create(ReadOnlySpan values) [Intrinsic] public static Vector2 Normalize(Vector2 value) => value / value.Length(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 RadiansToDegrees(Vector2 radians) => Vector128.RadiansToDegrees(radians.AsVector128Unsafe()).AsVector2(); + /// Returns the reflection of a vector off a surface that has the specified normal. /// The source vector. /// The normal of the surface being reflected off. @@ -383,6 +499,14 @@ public static Vector2 Reflect(Vector2 vector, Vector2 normal) return MultiplyAddEstimate(-tmp, normal, vector); } + /// + [Intrinsic] + public static Vector2 Round(Vector2 vector) => Vector128.Round(vector.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + public static Vector2 Round(Vector2 vector, MidpointRounding mode) => Vector128.Round(vector.AsVector128Unsafe(), mode).AsVector2(); + /// Returns a vector whose elements are the square root of each of a specified vector's elements. /// A vector. /// The square root vector. @@ -453,6 +577,10 @@ internal static Vector2 TransformNormal(Vector2 normal, in Matrix4x4.Impl matrix return result.AsVector2(); } + /// + [Intrinsic] + public static Vector2 Truncate(Vector2 vector) => Vector128.Truncate(vector.AsVector128Unsafe()).AsVector2(); + /// Copies the elements of the vector to a specified array. /// The destination array. /// must have at least two elements. The method copies the vector's elements starting at index 0. 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 ec97d4a4f5d52..8519f382655de 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -63,22 +63,69 @@ public Vector3(ReadOnlySpan values) this = Create(values); } - /// Gets a vector whose 3 elements are equal to zero. - /// A vector whose three elements are equal to zero (that is, it returns the vector (0,0,0). - public static Vector3 Zero + /// + public static Vector3 E { [Intrinsic] - get => default; + get => Create(float.E); + } + + /// + public static Vector3 Epsilon + { + [Intrinsic] + get => Create(float.Epsilon); + } + + /// + public static Vector3 NaN + { + [Intrinsic] + get => Create(float.NaN); + } + + /// + public static Vector3 NegativeInfinity + { + [Intrinsic] + get => Create(float.NegativeInfinity); + } + + /// + public static Vector3 NegativeZero + { + [Intrinsic] + get => Create(float.NegativeZero); } - /// Gets a vector whose 3 elements are equal to one. - /// A vector whose three elements are equal to one (that is, it returns the vector (1,1,1). + /// public static Vector3 One { [Intrinsic] get => Create(1.0f); } + /// + public static Vector3 Pi + { + [Intrinsic] + get => Create(float.Pi); + } + + /// + public static Vector3 PositiveInfinity + { + [Intrinsic] + get => Create(float.PositiveInfinity); + } + + /// + public static Vector3 Tau + { + [Intrinsic] + get => Create(float.Tau); + } + /// Gets the vector (1,0,0). /// The vector (1,0,0). public static Vector3 UnitX @@ -103,6 +150,13 @@ public static Vector3 UnitZ get => Create(0.0f, 0.0f, 1.0f); } + /// + public static Vector3 Zero + { + [Intrinsic] + get => default; + } + /// Gets or sets the element at the specified index. /// The index of the element to get or set. /// The the element at . @@ -232,17 +286,20 @@ readonly get [Intrinsic] public static Vector3 Add(Vector3 left, Vector3 right) => left + right; - /// Restricts a vector between a minimum and a maximum value. - /// The vector to restrict. - /// The minimum value. - /// The maximum value. - /// The restricted vector. + /// [Intrinsic] - public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max) - { - // We must follow HLSL behavior in the case user specified min value is bigger than max value. - return Min(Max(value1, min), max); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max) => Vector128.Clamp(value1.AsVector128Unsafe(), min.AsVector128Unsafe(), max.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 ClampNative(Vector3 value1, Vector3 min, Vector3 max) => Vector128.ClampNative(value1.AsVector128Unsafe(), min.AsVector128Unsafe(), max.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 CopySign(Vector3 value, Vector3 sign) => Vector128.CopySign(value.AsVector128Unsafe(), sign.AsVector128Unsafe()).AsVector3(); /// Creates a new object whose three elements have the same value. /// The value to assign to all three elements. @@ -318,6 +375,11 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) ).AsVector3(); } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 DegreesToRadians(Vector3 degrees) => Vector128.DegreesToRadians(degrees.AsVector128Unsafe()).AsVector3(); + /// Computes the Euclidean distance between the two given points. /// The first point. /// The second point. @@ -354,36 +416,88 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Dot(Vector3 vector1, Vector3 vector2) => Vector128.Dot(vector1.AsVector128(), vector2.AsVector128()); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 Exp(Vector3 vector) => Vector128.Exp(vector.AsVector128Unsafe()).AsVector3(); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] 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. - /// The second vector. - /// A value between 0 and 1 that indicates the weight of . - /// The interpolated vector. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 Hypot(Vector3 x, Vector3 y) => Vector128.Hypot(x.AsVector128Unsafe(), y.AsVector128Unsafe()).AsVector3(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount) => MultiplyAddEstimate(value1, Create(1.0f - amount), value2 * amount); + public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount) => Lerp(value1, value2, Create(amount)); - /// Returns a vector whose elements are the maximum of each of the pairs of elements in two specified vectors. - /// The first vector. - /// The second vector. - /// The maximized vector. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 Lerp(Vector3 value1, Vector3 value2, Vector3 amount) => Vector128.Lerp(value1.AsVector128Unsafe(), value2.AsVector128Unsafe(), amount.AsVector128Unsafe()).AsVector3(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 Log(Vector3 vector) => Vector128.Log(vector.AsVector128Unsafe()).AsVector3(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 Log2(Vector3 vector) => Vector128.Log2(vector.AsVector128Unsafe()).AsVector3(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] 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. - /// The second vector. - /// The minimized vector. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 MaxMagnitude(Vector3 value1, Vector3 value2) => Vector128.MaxMagnitude(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 MaxMagnitudeNumber(Vector3 value1, Vector3 value2) => Vector128.MaxMagnitudeNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 MaxNative(Vector3 value1, Vector3 value2) => Vector128.MaxNative(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 MaxNumber(Vector3 value1, Vector3 value2) => Vector128.MaxNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Min(Vector3 value1, Vector3 value2) => Vector128.Min(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 MinMagnitude(Vector3 value1, Vector3 value2) => Vector128.MinMagnitude(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 MinMagnitudeNumber(Vector3 value1, Vector3 value2) => Vector128.MinMagnitudeNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 MinNative(Vector3 value1, Vector3 value2) => Vector128.MinNative(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 MinNumber(Vector3 value1, Vector3 value2) => Vector128.MinNumber(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. /// The second vector. @@ -422,6 +536,11 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) [Intrinsic] public static Vector3 Normalize(Vector3 value) => value / value.Length(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 RadiansToDegrees(Vector3 radians) => Vector128.RadiansToDegrees(radians.AsVector128Unsafe()).AsVector3(); + /// Returns the reflection of a vector off a surface that has the specified normal. /// The source vector. /// The normal of the surface being reflected off. @@ -437,6 +556,14 @@ public static Vector3 Reflect(Vector3 vector, Vector3 normal) return MultiplyAddEstimate(-tmp, normal, vector); } + /// + [Intrinsic] + public static Vector3 Round(Vector3 vector) => Vector128.Round(vector.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + public static Vector3 Round(Vector3 vector, MidpointRounding mode) => Vector128.Round(vector.AsVector128Unsafe(), mode).AsVector3(); + /// Returns a vector whose elements are the square root of each of a specified vector's elements. /// A vector. /// The square root vector. @@ -483,6 +610,10 @@ internal static Vector3 TransformNormal(Vector3 normal, in Matrix4x4.Impl matrix return result.AsVector3(); } + /// + [Intrinsic] + public static Vector3 Truncate(Vector3 vector) => Vector128.Truncate(vector.AsVector128Unsafe()).AsVector3(); + /// Copies the elements of the vector to a specified array. /// The destination array. /// must have at least three elements. The method copies the vector's elements starting at index 0. 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 2cbc385316ea4..9c7028520f762 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -76,23 +76,78 @@ public Vector4(ReadOnlySpan values) this = Create(values); } - /// Gets a vector whose 4 elements are equal to zero. - /// A vector whose four elements are equal to zero (that is, it returns the vector (0,0,0,0). - public static Vector4 Zero + /// Gets a vector whose elements are equal to . + /// A vector whose elements are equal to (that is, it returns the vector Create(float.E)). + public static Vector4 E { [Intrinsic] - get => default; + get => Create(float.E); + } + + /// Gets a vector whose elements are equal to . + /// A vector whose elements are equal to (that is, it returns the vector Create(float.Epsilon)). + public static Vector4 Epsilon + { + [Intrinsic] + get => Create(float.Epsilon); + } + + /// Gets a vector whose elements are equal to . + /// A vector whose elements are equal to (that is, it returns the vector Create(float.NaN)). + public static Vector4 NaN + { + [Intrinsic] + get => Create(float.NaN); + } + + /// Gets a vector whose elements are equal to . + /// A vector whose elements are equal to (that is, it returns the vector Create(float.NegativeInfinity)). + public static Vector4 NegativeInfinity + { + [Intrinsic] + get => Create(float.NegativeInfinity); + } + + /// Gets a vector whose elements are equal to . + /// A vector whose elements are equal to (that is, it returns the vector Create(float.NegativeZero)). + public static Vector4 NegativeZero + { + [Intrinsic] + get => Create(float.NegativeZero); } - /// Gets a vector whose 4 elements are equal to one. - /// Returns . - /// A vector whose four elements are equal to one (that is, it returns the vector (1,1,1,1). + /// Gets a vector whose elements are equal to one. + /// A vector whose elements are equal to one (that is, it returns the vector Create(1)). public static Vector4 One { [Intrinsic] get => Create(1); } + /// Gets a vector whose elements are equal to . + /// A vector whose elements are equal to (that is, it returns the vector Create(float.Pi)). + public static Vector4 Pi + { + [Intrinsic] + get => Create(float.Pi); + } + + /// Gets a vector whose elements are equal to . + /// A vector whose elements are equal to (that is, it returns the vector Create(float.PositiveInfinity)). + public static Vector4 PositiveInfinity + { + [Intrinsic] + get => Create(float.PositiveInfinity); + } + + /// Gets a vector whose elements are equal to . + /// A vector whose elements are equal to (that is, it returns the vector Create(float.Tau)). + public static Vector4 Tau + { + [Intrinsic] + get => Create(float.Tau); + } + /// Gets the vector (1,0,0,0). /// The vector (1,0,0,0). public static Vector4 UnitX @@ -125,6 +180,14 @@ public static Vector4 UnitW get => Create(0.0f, 0.0f, 0.0f, 1.0f); } + /// Gets a vector whose elements are equal to zero. + /// A vector whose elements are equal to zero (that is, it returns the vector Create(0)). + public static Vector4 Zero + { + [Intrinsic] + get => default; + } + /// Gets or sets the element at the specified index. /// The index of the element to get or set. /// The the element at . @@ -242,17 +305,20 @@ public float this[int index] [Intrinsic] public static Vector4 Add(Vector4 left, Vector4 right) => left + right; - /// Restricts a vector between a minimum and a maximum value. - /// The vector to restrict. - /// The minimum value. - /// The maximum value. - /// The restricted vector. + /// [Intrinsic] - public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max) - { - // We must follow HLSL behavior in the case user specified min value is bigger than max value. - return Min(Max(value1, min), max); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max) => Vector128.Clamp(value1.AsVector128(), min.AsVector128(), max.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 ClampNative(Vector4 value1, Vector4 min, Vector4 max) => Vector128.ClampNative(value1.AsVector128(), min.AsVector128(), max.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 CopySign(Vector4 value, Vector4 sign) => Vector128.CopySign(value.AsVector128(), sign.AsVector128()).AsVector4(); /// Creates a new object whose four elements have the same value. /// The value to assign to all four elements. @@ -314,6 +380,11 @@ public static Vector4 Create(Vector3 vector, float w) [Intrinsic] internal static Vector4 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector4(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 DegreesToRadians(Vector4 degrees) => Vector128.DegreesToRadians(degrees.AsVector128()).AsVector4(); + /// Computes the Euclidean distance between the two given points. /// The first point. /// The second point. @@ -350,39 +421,91 @@ public static Vector4 Create(Vector3 vector, float w) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Dot(Vector4 vector1, Vector4 vector2) => Vector128.Dot(vector1.AsVector128(), vector2.AsVector128()); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Exp(Vector4 vector) => Vector128.Exp(vector.AsVector128()).AsVector4(); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 FusedMultiplyAdd(Vector4 left, Vector4 right, Vector4 addend) => Vector128.FusedMultiplyAdd(left.AsVector128(), right.AsVector128(), addend.AsVector128()).AsVector4(); - /// Performs a linear interpolation between two vectors based on the given weighting. - /// The first vector. - /// The second vector. - /// A value between 0 and 1 that indicates the weight of . - /// The interpolated vector. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Hypot(Vector4 x, Vector4 y) => Vector128.Hypot(x.AsVector128(), y.AsVector128()).AsVector4(); + + /// /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Lerp(Vector4 value1, Vector4 value2, float amount) => MultiplyAddEstimate(value1, Create(1.0f - amount), value2 * amount); + public static Vector4 Lerp(Vector4 value1, Vector4 value2, float amount) => Lerp(value1, value2, Create(amount)); - /// Returns a vector whose elements are the maximum of each of the pairs of elements in two specified vectors. - /// The first vector. - /// The second vector. - /// The maximized vector. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lerp(Vector4 value1, Vector4 value2, Vector4 amount) => Vector128.Lerp(value1.AsVector128(), value2.AsVector128(), amount.AsVector128()).AsVector4(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Log(Vector4 vector) => Vector128.Log(vector.AsVector128()).AsVector4(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Log2(Vector4 vector) => Vector128.Log2(vector.AsVector128()).AsVector4(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Max(Vector4 value1, Vector4 value2) => Vector128.Max(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// Returns a vector whose elements are the minimum of each of the pairs of elements in two specified vectors. - /// The first vector. - /// The second vector. - /// The minimized vector. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 MaxMagnitude(Vector4 value1, Vector4 value2) => Vector128.MaxMagnitude(value1.AsVector128(), value2.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 MaxMagnitudeNumber(Vector4 value1, Vector4 value2) => Vector128.MaxMagnitudeNumber(value1.AsVector128(), value2.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 MaxNative(Vector4 value1, Vector4 value2) => Vector128.MaxNative(value1.AsVector128(), value2.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 MaxNumber(Vector4 value1, Vector4 value2) => Vector128.MaxNumber(value1.AsVector128(), value2.AsVector128()).AsVector4(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Min(Vector4 value1, Vector4 value2) => Vector128.Min(value1.AsVector128(), value2.AsVector128()).AsVector4(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 MinMagnitude(Vector4 value1, Vector4 value2) => Vector128.MinMagnitude(value1.AsVector128(), value2.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 MinMagnitudeNumber(Vector4 value1, Vector4 value2) => Vector128.MinMagnitudeNumber(value1.AsVector128(), value2.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 MinNative(Vector4 value1, Vector4 value2) => Vector128.MinNative(value1.AsVector128(), value2.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 MinNumber(Vector4 value1, Vector4 value2) => Vector128.MinNumber(value1.AsVector128(), value2.AsVector128()).AsVector4(); + /// Returns a new vector whose values are the product of each pair of elements in two specified vectors. /// The first vector. /// The second vector. @@ -421,6 +544,19 @@ public static Vector4 Create(Vector3 vector, float w) [Intrinsic] public static Vector4 Normalize(Vector4 vector) => vector / vector.Length(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 RadiansToDegrees(Vector4 radians) => Vector128.RadiansToDegrees(radians.AsVector128()).AsVector4(); + + /// + [Intrinsic] + public static Vector4 Round(Vector4 vector) => Vector128.Round(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + public static Vector4 Round(Vector4 vector, MidpointRounding mode) => Vector128.Round(vector.AsVector128(), mode).AsVector4(); + /// Returns a vector whose elements are the square root of each of a specified vector's elements. /// A vector. /// The square root vector. @@ -518,6 +654,10 @@ public static Vector4 Transform(Vector4 value, Quaternion rotation) return Quaternion.Concatenate(temp, rotation).AsVector4(); } + /// + [Intrinsic] + public static Vector4 Truncate(Vector4 vector) => Vector128.Truncate(vector.AsVector128()).AsVector4(); + /// Copies the elements of the vector to a specified array. /// The destination array. /// must have at least four elements. The method copies the vector's elements starting at index 0. 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 79a66dca0a6f5..0910caadcf37c 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 @@ -28,7 +28,7 @@ namespace System.Numerics [Intrinsic] [DebuggerDisplay("{DisplayString,nq}")] [DebuggerTypeProxy(typeof(VectorDebugView<>))] - public readonly struct Vector : IEquatable>, IFormattable + public readonly unsafe struct Vector : ISimdVector, T>, IFormattable { // These fields exist to ensure the alignment is 8, rather than 1. internal readonly ulong _00; @@ -107,7 +107,7 @@ public Vector(ReadOnlySpan values) /// A new with its elements set to the first sizeof() elements from . /// The length of is less than sizeof(). [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe Vector(ReadOnlySpan values) + public Vector(ReadOnlySpan values) { // We explicitly don't check for `null` because historically this has thrown `NullReferenceException` for perf reasons ThrowHelper.ThrowForUnsupportedNumericsVectorBaseType(); @@ -139,7 +139,7 @@ public static Vector AllBitsSet #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// Gets the number of that are in a . /// The type of the current instance () is not supported. - public static unsafe int Count + public static int Count { [Intrinsic] get @@ -655,7 +655,7 @@ public void CopyTo(T[] destination, int startIndex) /// The span to which the current instance is copied. /// The length of is less than sizeof(). [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe void CopyTo(Span destination) + public void CopyTo(Span destination) { ThrowHelper.ThrowForUnsupportedNumericsVectorBaseType(); @@ -776,7 +776,7 @@ public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] strin /// The span to which the current instance is copied. /// true if the current instance was successfully copied to ; otherwise, false if the length of is less than sizeof(). [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe bool TryCopyTo(Span destination) + public bool TryCopyTo(Span destination) { ThrowHelper.ThrowForUnsupportedNumericsVectorBaseType(); @@ -803,5 +803,285 @@ public bool TryCopyTo(Span destination) Unsafe.WriteUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(destination)), this); return true; } + + // + // ISimdVector + // + + /// + static int ISimdVector, T>.Alignment => Vector.Alignment; + + /// + static bool ISimdVector, T>.IsHardwareAccelerated => Vector.IsHardwareAccelerated; + + /// + static Vector ISimdVector, T>.Abs(Vector vector) => Vector.Abs(vector); + + /// + static Vector ISimdVector, T>.Add(Vector left, Vector right) => left + right; + + /// + static Vector ISimdVector, T>.AndNot(Vector left, Vector right) => Vector.AndNot(left, right); + + /// + static Vector ISimdVector, T>.BitwiseAnd(Vector left, Vector right) => left & right; + + /// + static Vector ISimdVector, T>.BitwiseOr(Vector left, Vector right) => left | right; + + /// + static Vector ISimdVector, T>.Ceiling(Vector vector) => Vector.Ceiling(vector); + + /// + static Vector ISimdVector, T>.Clamp(Vector value, Vector min, Vector max) => Vector.Clamp(value, min, max); + + /// + static Vector ISimdVector, T>.ClampNative(Vector value, Vector min, Vector max) => Vector.ClampNative(value, min, max); + + /// + static Vector ISimdVector, T>.ConditionalSelect(Vector condition, Vector left, Vector right) => Vector.ConditionalSelect(condition, left, right); + + /// + static Vector ISimdVector, T>.CopySign(Vector value, Vector sign) => Vector.CopySign(value, sign); + + /// + static void ISimdVector, T>.CopyTo(Vector vector, T[] destination) => vector.CopyTo(destination); + + /// + static void ISimdVector, T>.CopyTo(Vector vector, T[] destination, int startIndex) => vector.CopyTo(destination, startIndex); + + /// + static void ISimdVector, T>.CopyTo(Vector vector, Span destination) => vector.CopyTo(destination); + + /// + static Vector ISimdVector, T>.Create(T value) => Vector.Create(value); + + /// + static Vector ISimdVector, T>.Create(T[] values) => new Vector(values); + + /// + static Vector ISimdVector, T>.Create(T[] values, int index) => new Vector(values, index); + + /// + static Vector ISimdVector, T>.Create(ReadOnlySpan values) => Vector.Create(values); + + /// + static Vector ISimdVector, T>.CreateScalar(T value) => Vector.CreateScalar(value); + + /// + static Vector ISimdVector, T>.CreateScalarUnsafe(T value) => Vector.CreateScalarUnsafe(value); + + /// + static Vector ISimdVector, T>.Divide(Vector left, Vector right) => left / right; + + /// + static Vector ISimdVector, T>.Divide(Vector left, T right) => left / right; + + /// + static T ISimdVector, T>.Dot(Vector left, Vector right) => Vector.Dot(left, right); + + /// + static Vector ISimdVector, T>.Equals(Vector left, Vector right) => Vector.Equals(left, right); + + /// + static bool ISimdVector, T>.EqualsAll(Vector left, Vector right) => left == right; + + /// + static bool ISimdVector, T>.EqualsAny(Vector left, Vector right) => Vector.EqualsAny(left, right); + + /// + static Vector ISimdVector, T>.Floor(Vector vector) => Vector.Floor(vector); + + /// + static T ISimdVector, T>.GetElement(Vector vector, int index) => vector.GetElement(index); + + /// + static Vector ISimdVector, T>.GreaterThan(Vector left, Vector right) => Vector.GreaterThan(left, right); + + /// + static bool ISimdVector, T>.GreaterThanAll(Vector left, Vector right) => Vector.GreaterThanAll(left, right); + + /// + static bool ISimdVector, T>.GreaterThanAny(Vector left, Vector right) => Vector.GreaterThanAny(left, right); + + /// + static Vector ISimdVector, T>.GreaterThanOrEqual(Vector left, Vector right) => Vector.GreaterThanOrEqual(left, right); + + /// + static bool ISimdVector, T>.GreaterThanOrEqualAll(Vector left, Vector right) => Vector.GreaterThanOrEqualAll(left, right); + + /// + static bool ISimdVector, T>.GreaterThanOrEqualAny(Vector left, Vector right) => Vector.GreaterThanOrEqualAny(left, right); + + /// + static Vector ISimdVector, T>.LessThan(Vector left, Vector right) => Vector.LessThan(left, right); + + /// + static bool ISimdVector, T>.LessThanAll(Vector left, Vector right) => Vector.LessThanAll(left, right); + + /// + static bool ISimdVector, T>.LessThanAny(Vector left, Vector right) => Vector.LessThanAny(left, right); + + /// + static Vector ISimdVector, T>.LessThanOrEqual(Vector left, Vector right) => Vector.LessThanOrEqual(left, right); + + /// + static bool ISimdVector, T>.LessThanOrEqualAll(Vector left, Vector right) => Vector.LessThanOrEqualAll(left, right); + + /// + static bool ISimdVector, T>.LessThanOrEqualAny(Vector left, Vector right) => Vector.LessThanOrEqualAny(left, right); + +#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') + /// + static Vector ISimdVector, T>.Load(T* source) => Vector.Load(source); + + /// + static Vector ISimdVector, T>.LoadAligned(T* source) => Vector.LoadAligned(source); + + /// + static Vector ISimdVector, T>.LoadAlignedNonTemporal(T* source) => Vector.LoadAlignedNonTemporal(source); +#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') + + /// + static Vector ISimdVector, T>.LoadUnsafe(ref readonly T source) => Vector.LoadUnsafe(in source); + + /// + static Vector ISimdVector, T>.LoadUnsafe(ref readonly T source, nuint elementOffset) => Vector.LoadUnsafe(in source, elementOffset); + + /// + static Vector ISimdVector, T>.Max(Vector left, Vector right) => Vector.Max(left, right); + + /// + static Vector ISimdVector, T>.MaxMagnitude(Vector left, Vector right) => Vector.MaxMagnitude(left, right); + + /// + static Vector ISimdVector, T>.MaxMagnitudeNumber(Vector left, Vector right) => Vector.MaxMagnitudeNumber(left, right); + + /// + static Vector ISimdVector, T>.MaxNative(Vector left, Vector right) => Vector.MaxNative(left, right); + + /// + static Vector ISimdVector, T>.MaxNumber(Vector left, Vector right) => Vector.MaxNumber(left, right); + + /// + static Vector ISimdVector, T>.Min(Vector left, Vector right) => Vector.Min(left, right); + + /// + static Vector ISimdVector, T>.MinMagnitude(Vector left, Vector right) => Vector.MinMagnitude(left, right); + + /// + static Vector ISimdVector, T>.MinMagnitudeNumber(Vector left, Vector right) => Vector.MinMagnitudeNumber(left, right); + + /// + static Vector ISimdVector, T>.MinNative(Vector left, Vector right) => Vector.MinNative(left, right); + + /// + static Vector ISimdVector, T>.MinNumber(Vector left, Vector right) => Vector.MinNumber(left, right); + + /// + static Vector ISimdVector, T>.Multiply(Vector left, Vector right) => left * right; + + /// + static Vector ISimdVector, T>.Multiply(Vector left, T right) => left * right; + + /// + static Vector ISimdVector, T>.MultiplyAddEstimate(Vector left, Vector right, Vector addend) => Vector.MultiplyAddEstimate(left, right, addend); + + /// + static Vector ISimdVector, T>.Negate(Vector vector) => -vector; + + /// + static Vector ISimdVector, T>.OnesComplement(Vector vector) => ~vector; + + /// + static Vector ISimdVector, T>.Round(Vector vector) => Vector.Round(vector); + + /// + static Vector ISimdVector, T>.ShiftLeft(Vector vector, int shiftCount) => vector << shiftCount; + + /// + static Vector ISimdVector, T>.ShiftRightArithmetic(Vector vector, int shiftCount) => vector >> shiftCount; + + /// + static Vector ISimdVector, T>.ShiftRightLogical(Vector vector, int shiftCount) => vector >>> shiftCount; + + /// + static Vector ISimdVector, T>.Sqrt(Vector vector) => Vector.SquareRoot(vector); + +#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') + /// + static void ISimdVector, T>.Store(Vector source, T* destination) => source.Store(destination); + + /// + static void ISimdVector, T>.StoreAligned(Vector source, T* destination) => source.StoreAligned(destination); + + /// + static void ISimdVector, T>.StoreAlignedNonTemporal(Vector source, T* destination) => source.StoreAlignedNonTemporal(destination); +#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') + + /// + static void ISimdVector, T>.StoreUnsafe(Vector vector, ref T destination) => vector.StoreUnsafe(ref destination); + + /// + static void ISimdVector, T>.StoreUnsafe(Vector vector, ref T destination, nuint elementOffset) => vector.StoreUnsafe(ref destination, elementOffset); + + /// + static Vector ISimdVector, T>.Subtract(Vector left, Vector right) => left - right; + + /// + static T ISimdVector, T>.Sum(Vector vector) => Vector.Sum(vector); + + /// + static T ISimdVector, T>.ToScalar(Vector vector) => vector.ToScalar(); + + /// + static Vector ISimdVector, T>.Truncate(Vector vector) => Vector.Truncate(vector); + + /// + static bool ISimdVector, T>.TryCopyTo(Vector vector, Span destination) => vector.TryCopyTo(destination); + + /// + static Vector ISimdVector, T>.WithElement(Vector vector, int index, T value) => vector.WithElement(index, value); + + /// + static Vector ISimdVector, T>.Xor(Vector left, Vector right) => left ^ right; + + // + // New Surface Area + // + + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector vector) => Vector.EqualsAny(vector, AllBitsSet); + + static bool ISimdVector, T>.Any(Vector vector, T value) => Vector.EqualsAny(vector, Vector.Create(value)); + + static int ISimdVector, T>.IndexOfLastMatch(Vector vector) + { + if (sizeof(Vector) == 64) + { + ulong mask = vector.AsVector512().ExtractMostSignificantBits(); + return 63 - BitOperations.LeadingZeroCount(mask); // 63 = 64 (bits in Int64) - 1 (indexing from zero) + } + else if (sizeof(Vector) == 32) + { + uint mask = vector.AsVector256().ExtractMostSignificantBits(); + return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) + } + else + { + Debug.Assert(sizeof(Vector) == 16); + uint mask = vector.AsVector128().ExtractMostSignificantBits(); + return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) + } + } + + static Vector ISimdVector, T>.IsNaN(Vector vector) => Vector.IsNaN(vector); + + static Vector ISimdVector, T>.IsNegative(Vector vector) => Vector.IsNegative(vector); + + static Vector ISimdVector, T>.IsPositive(Vector vector) => Vector.IsPositive(vector); + + static Vector ISimdVector, T>.IsPositiveInfinity(Vector vector) => Vector.IsPositiveInfinity(vector); + + static Vector ISimdVector, T>.IsZero(Vector vector) => Vector.IsZero(vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs index a88b5f0dec6a1..eaa9a524be175 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs @@ -118,6 +118,22 @@ internal unsafe interface ISimdVector /// A vector whose elements are the ceiling of the elements in . static abstract TSelf Ceiling(TSelf vector); + /// Restricts a vector between a minimum and a maximum value. + /// The vector to restrict. + /// The minimum value. + /// The maximum value. + /// The restricted vector. + /// The type of the elements in the vector () is not supported. + static abstract TSelf Clamp(TSelf value, TSelf min, TSelf max); + + /// Restricts a vector between a minimum and a maximum value using platform specific behavior for NaN and NegativeZero.. + /// The vector to restrict. + /// The minimum value. + /// The maximum value. + /// The restricted vector. + /// The type of the elements in the vector () is not supported. + static abstract TSelf ClampNative(TSelf value, TSelf min, TSelf max); + /// Conditionally selects bits from two vectors based on a given condition. /// The mask that is used to select a value from or . /// The vector that is selected when the corresponding bit in is one. @@ -126,6 +142,12 @@ internal unsafe interface ISimdVector /// The type of the elements in the vector () is not supported. static virtual TSelf ConditionalSelect(TSelf condition, TSelf left, TSelf right) => (left & condition) | (right & ~condition); + /// Copies the per-element sign of a vector to the per-element sign of another vector. + /// The vector whose magnitude is used in the result. + /// The vector whose sign is used in the result. + /// A vector with the magnitude of and the sign of . + static abstract TSelf CopySign(TSelf value, TSelf sign); + /// Copies a vector to a given array. /// The vector to be copied. /// The array to which is copied. @@ -310,6 +332,31 @@ static virtual TSelf CreateScalarUnsafe(T value) /// The type of the elements in the vector () is not supported. static abstract bool GreaterThanOrEqualAny(TSelf left, TSelf right); + /// Determines which elements in a vector are NaN. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were NaN. + static abstract TSelf IsNaN(TSelf vector); + + /// Determines which elements in a vector represents negative real numbers. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were negative. + static abstract TSelf IsNegative(TSelf vector); + + /// Determines which elements in a vector represents positive real numbers. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were positive. + static abstract TSelf IsPositive(TSelf vector); + + /// Determines which elements in a vector are positive infinity. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were positive infinity. + static abstract TSelf IsPositiveInfinity(TSelf vector); + + /// Determines which elements in a vector are zero. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were zero. + static abstract TSelf IsZero(TSelf vector); + /// Compares two vectors to determine which is less on a per-element basis. /// The vector to compare with . /// The vector to compare with . @@ -393,20 +440,84 @@ static virtual TSelf LoadAligned(T* source) /// The type of the elements in the vector () is not supported. static abstract TSelf LoadUnsafe(ref readonly T source, nuint elementOffset); - /// Computes the maximum of two vectors on a per-element basis. + /// Compare two vectors to determine which is greater on a per-element basis. /// The vector to compare with . /// The vector to compare with . - /// A vector whose elements are the maximum of the corresponding elements in and . + /// A vector where the corresponding element comes from if it is greater than ; otherwise, . + /// For this method matches the IEEE 754:2019 maximum function.This requires NaN inputs to be propagated back to the caller and for -0.0 to be treated as less than +0.0. /// The type of the elements in the vector () is not supported. static abstract TSelf Max(TSelf left, TSelf right); - /// Computes the minimum of two vectors on a per-element basis. + /// Compares two vectors to compute which has the greater magnitude on a per-element basis. /// The vector to compare with . /// The vector to compare with . - /// A vector whose elements are the minimum of the corresponding elements in and . + /// A vector where the corresponding element comes from if it has a greater magnitude than ; otherwise, . + /// For this method matches the IEEE 754:2019 maximumMagnitude function. This requires NaN inputs to be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// The type of the elements in the vector () is not supported. + static abstract TSelf MaxMagnitude(TSelf left, TSelf right); + + /// Compares two vectors, on a per-element basis, to compute which has the greater magnitude and returning the other value if an input is NaN. + /// The vector to compare with . + /// The vector to compare with . + /// A vector where the corresponding element comes from if it has a greater magnitude than ; otherwise, . + /// For this method matches the IEEE 754:2019 maximumMagnitudeNumber function. This requires NaN inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// The type of the elements in the vector () is not supported. + static abstract TSelf MaxMagnitudeNumber(TSelf left, TSelf right); + + /// Compare two vectors to determine which is greater on a per-element basis using platform specific behavior for NaN and NegativeZero. + /// The vector to compare with . + /// The vector to compare with . + /// A vector where the corresponding element comes from if it is greater than ; otherwise, . + /// The type of the elements in the vector () is not supported. + static abstract TSelf MaxNative(TSelf left, TSelf right); + + /// Compares two vectors, on a per-element basis, to compute which is greater and returning the other value if an element is NaN. + /// The vector to compare with . + /// The vector to compare with . + /// A vector where the corresponding element comes from if it is greater than ; otherwise, . + /// For this method matches the IEEE 754:2019 maximumNumber function. This requires NaN inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// The type of the elements in the vector () is not supported. + static abstract TSelf MaxNumber(TSelf left, TSelf right); + + /// Compare two vectors to determine which is lesser on a per-element basis. + /// The vector to compare with . + /// The vector to compare with . + /// A vector where the corresponding element comes from if it is lesser than ; otherwise, . + /// For this method matches the IEEE 754:2019 minimum function.This requires NaN inputs to be propagated back to the caller and for -0.0 to be treated as less than +0.0. /// The type of the elements in the vector () is not supported. static abstract TSelf Min(TSelf left, TSelf right); + /// Compares two vectors to compute which has the lesser magnitude on a per-element basis. + /// The vector to compare with . + /// The vector to compare with . + /// A vector where the corresponding element comes from if it has a lesser magnitude than ; otherwise, . + /// For this method matches the IEEE 754:2019 minimumMagnitude function. This requires NaN inputs to be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// The type of the elements in the vector () is not supported. + static abstract TSelf MinMagnitude(TSelf left, TSelf right); + + /// Compares two vectors, on a per-element basis, to compute which has the lesser magnitude and returning the other value if an input is NaN. + /// The vector to compare with . + /// The vector to compare with . + /// A vector where the corresponding element comes from if it has a lesser magnitude than ; otherwise, . + /// For this method matches the IEEE 754:2019 minimumMagnitudeNumber function. This requires NaN inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// The type of the elements in the vector () is not supported. + static abstract TSelf MinMagnitudeNumber(TSelf left, TSelf right); + + /// Compare two vectors to determine which is lesser on a per-element basis using platform specific behavior for NaN and NegativeZero. + /// The vector to compare with . + /// The vector to compare with . + /// A vector where the corresponding element comes from if it is lesser than ; otherwise, . + /// The type of the elements in the vector () is not supported. + static abstract TSelf MinNative(TSelf left, TSelf right); + + /// Compares two vectors, on a per-element basis, to compute which is lesser and returning the other value if an element is NaN. + /// The vector to compare with . + /// The vector to compare with . + /// A vector where the corresponding element comes from if it is lesser than ; otherwise, . + /// For this method matches the IEEE 754:2019 minimumNumber function. This requires NaN inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// The type of the elements in the vector () is not supported. + static abstract TSelf MinNumber(TSelf left, TSelf right); + /// Multiplies two vectors to compute their element-wise product. /// The vector to multiply with . /// The vector to multiply with . @@ -421,6 +532,17 @@ static virtual TSelf LoadAligned(T* source) /// The type of and () is not supported. static virtual TSelf Multiply(TSelf left, T right) => left * right; + /// Computes an estimate of ( * ) + . + /// The vector to be multiplied with . + /// The vector to be multiplied with . + /// The vector to be added to the result of multiplied by . + /// An estimate of ( * ) + . + /// + /// On hardware that natively supports FusedMultiplyAdd, this may return a result that was rounded as one ternary operation. + /// On hardware without specialized support, this may just return ( * ) + . + /// + static abstract TSelf MultiplyAddEstimate(TSelf left, TSelf right, TSelf addend); + /// Negates a vector. /// The vector to negate. /// A vector whose elements are the negation of the corresponding elements in . @@ -433,6 +555,11 @@ static virtual TSelf LoadAligned(T* source) /// The type of () is not supported. static virtual TSelf OnesComplement(TSelf vector) => ~vector; + /// Rounds each element in a vector to the nearest integer using the default rounding mode (). + /// The vector to round. + /// The result of rounding each element in to the nearest integer using the default rounding mode. + static abstract TSelf Round(TSelf vector); + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -517,6 +644,11 @@ static virtual void StoreAligned(TSelf source, T* destination) /// The type of the elements in the vector () is not supported. static virtual T ToScalar(TSelf vector) => TSelf.GetElement(vector, 0); + /// Truncates each element in a vector. + /// The vector to truncate. + /// The truncation of each element in . + static abstract TSelf Truncate(TSelf vector); + /// Tries to copy a to a given span. /// The vector to copy. /// The span to which is copied. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Scalar.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Scalar.cs index 1bccb11859d01..deb6ef6af4d3d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Scalar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Scalar.cs @@ -334,6 +334,46 @@ public static T Convert(int value) } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T CopySign(T value, T sign) + { + // byte, ushort, uint, and ulong should have already been handled + // avoid Math.Abs for integers since it throws for MinValue + if (typeof(T) == typeof(double)) + { + return (T)(object)double.CopySign((double)(object)value, (double)(object)sign); + } + else if (typeof(T) == typeof(short)) + { + return (T)(object)short.CopySign((short)(object)value, (short)(object)sign); + } + else if (typeof(T) == typeof(int)) + { + return (T)(object)int.CopySign((int)(object)value, (int)(object)sign); + } + else if (typeof(T) == typeof(long)) + { + return (T)(object)long.CopySign((long)(object)value, (long)(object)sign); + } + else if (typeof(T) == typeof(nint)) + { + return (T)(object)nint.CopySign((nint)(object)value, (nint)(object)sign); + } + else if (typeof(T) == typeof(sbyte)) + { + return (T)(object)sbyte.CopySign((sbyte)(object)value, (sbyte)(object)sign); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.CopySign((float)(object)value, (float)(object)sign); + } + else + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported); + return default!; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Divide(T left, T right) { @@ -780,6 +820,272 @@ public static bool LessThanOrEqual(T left, T right) } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Max(T left, T right) + { + if (typeof(T) == typeof(byte)) + { + return (T)(object)byte.Max((byte)(object)left, (byte)(object)right); + } + else if (typeof(T) == typeof(double)) + { + return (T)(object)double.Max((double)(object)left, (double)(object)right); + } + else if (typeof(T) == typeof(short)) + { + return (T)(object)short.Max((short)(object)left, (short)(object)right); + } + else if (typeof(T) == typeof(int)) + { + return (T)(object)int.Max((int)(object)left, (int)(object)right); + } + else if (typeof(T) == typeof(long)) + { + return (T)(object)long.Max((long)(object)left, (long)(object)right); + } + else if (typeof(T) == typeof(nint)) + { + return (T)(object)nint.Max((nint)(object)left, (nint)(object)right); + } + else if (typeof(T) == typeof(nuint)) + { + return (T)(object)nuint.Max((nuint)(object)left, (nuint)(object)right); + } + else if (typeof(T) == typeof(sbyte)) + { + return (T)(object)sbyte.Max((sbyte)(object)left, (sbyte)(object)right); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.Max((float)(object)left, (float)(object)right); + } + else if (typeof(T) == typeof(ushort)) + { + return (T)(object)ushort.Max((ushort)(object)left, (ushort)(object)right); + } + else if (typeof(T) == typeof(uint)) + { + return (T)(object)uint.Max((uint)(object)left, (uint)(object)right); + } + else if (typeof(T) == typeof(ulong)) + { + return (T)(object)ulong.Max((ulong)(object)left, (ulong)(object)right); + } + else + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported); + return default!; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MaxMagnitude(T left, T right) + { + if (typeof(T) == typeof(double)) + { + return (T)(object)double.MaxMagnitude((double)(object)left, (double)(object)right); + } + else if (typeof(T) == typeof(short)) + { + return (T)(object)short.MaxMagnitude((short)(object)left, (short)(object)right); + } + else if (typeof(T) == typeof(int)) + { + return (T)(object)int.MaxMagnitude((int)(object)left, (int)(object)right); + } + else if (typeof(T) == typeof(long)) + { + return (T)(object)long.MaxMagnitude((long)(object)left, (long)(object)right); + } + else if (typeof(T) == typeof(nint)) + { + return (T)(object)nint.MaxMagnitude((nint)(object)left, (nint)(object)right); + } + else if (typeof(T) == typeof(nuint)) + { + return (T)(object)nuint.Max((nuint)(object)left, (nuint)(object)right); + } + else if (typeof(T) == typeof(sbyte)) + { + return (T)(object)sbyte.MaxMagnitude((sbyte)(object)left, (sbyte)(object)right); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.MaxMagnitude((float)(object)left, (float)(object)right); + } + else + { + return Max(left, right); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MaxMagnitudeNumber(T left, T right) + { + if (typeof(T) == typeof(double)) + { + return (T)(object)double.MaxMagnitudeNumber((double)(object)left, (double)(object)right); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.MaxMagnitudeNumber((float)(object)left, (float)(object)right); + } + else + { + return MaxMagnitude(left, right); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MaxNumber(T left, T right) + { + if (typeof(T) == typeof(double)) + { + return (T)(object)double.MaxNumber((double)(object)left, (double)(object)right); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.MaxNumber((float)(object)left, (float)(object)right); + } + else + { + return Max(left, right); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Min(T left, T right) + { + if (typeof(T) == typeof(byte)) + { + return (T)(object)byte.Min((byte)(object)left, (byte)(object)right); + } + else if (typeof(T) == typeof(double)) + { + return (T)(object)double.Min((double)(object)left, (double)(object)right); + } + else if (typeof(T) == typeof(short)) + { + return (T)(object)short.Min((short)(object)left, (short)(object)right); + } + else if (typeof(T) == typeof(int)) + { + return (T)(object)int.Min((int)(object)left, (int)(object)right); + } + else if (typeof(T) == typeof(long)) + { + return (T)(object)long.Min((long)(object)left, (long)(object)right); + } + else if (typeof(T) == typeof(nint)) + { + return (T)(object)nint.Min((nint)(object)left, (nint)(object)right); + } + else if (typeof(T) == typeof(nuint)) + { + return (T)(object)nuint.Min((nuint)(object)left, (nuint)(object)right); + } + else if (typeof(T) == typeof(sbyte)) + { + return (T)(object)sbyte.Min((sbyte)(object)left, (sbyte)(object)right); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.Min((float)(object)left, (float)(object)right); + } + else if (typeof(T) == typeof(ushort)) + { + return (T)(object)ushort.Min((ushort)(object)left, (ushort)(object)right); + } + else if (typeof(T) == typeof(uint)) + { + return (T)(object)uint.Min((uint)(object)left, (uint)(object)right); + } + else if (typeof(T) == typeof(ulong)) + { + return (T)(object)ulong.Min((ulong)(object)left, (ulong)(object)right); + } + else + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported); + return default!; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MinMagnitude(T left, T right) + { + if (typeof(T) == typeof(double)) + { + return (T)(object)double.MinMagnitude((double)(object)left, (double)(object)right); + } + else if (typeof(T) == typeof(short)) + { + return (T)(object)short.MinMagnitude((short)(object)left, (short)(object)right); + } + else if (typeof(T) == typeof(int)) + { + return (T)(object)int.MinMagnitude((int)(object)left, (int)(object)right); + } + else if (typeof(T) == typeof(long)) + { + return (T)(object)long.MinMagnitude((long)(object)left, (long)(object)right); + } + else if (typeof(T) == typeof(nint)) + { + return (T)(object)nint.MinMagnitude((nint)(object)left, (nint)(object)right); + } + else if (typeof(T) == typeof(nuint)) + { + return (T)(object)nuint.Min((nuint)(object)left, (nuint)(object)right); + } + else if (typeof(T) == typeof(sbyte)) + { + return (T)(object)sbyte.MinMagnitude((sbyte)(object)left, (sbyte)(object)right); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.MinMagnitude((float)(object)left, (float)(object)right); + } + else + { + return Min(left, right); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MinMagnitudeNumber(T left, T right) + { + if (typeof(T) == typeof(double)) + { + return (T)(object)double.MinMagnitudeNumber((double)(object)left, (double)(object)right); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.MinMagnitudeNumber((float)(object)left, (float)(object)right); + } + else + { + return MinMagnitude(left, right); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MinNumber(T left, T right) + { + if (typeof(T) == typeof(double)) + { + return (T)(object)double.MinNumber((double)(object)left, (double)(object)right); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.MinNumber((float)(object)left, (float)(object)right); + } + else + { + return Min(left, right); + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Multiply(T left, T right) { @@ -838,6 +1144,64 @@ public static T Multiply(T left, T right) } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MultiplyAddEstimate(T left, T right, T addend) + { + if (typeof(T) == typeof(byte)) + { + return (T)(object)(byte)((((byte)(object)left * (byte)(object)right)) + (byte)(object)addend); + } + else if (typeof(T) == typeof(double)) + { + return (T)(object)double.MultiplyAddEstimate((double)(object)left, (double)(object)right, (double)(object)addend); + } + else if (typeof(T) == typeof(short)) + { + return (T)(object)(short)((((short)(object)left * (short)(object)right)) + (short)(object)addend); + } + else if (typeof(T) == typeof(int)) + { + return (T)(object)(int)((((int)(object)left * (int)(object)right)) + (int)(object)addend); + } + else if (typeof(T) == typeof(long)) + { + return (T)(object)(long)((((long)(object)left * (long)(object)right)) + (long)(object)addend); + } + else if (typeof(T) == typeof(nint)) + { + return (T)(object)(nint)((((nint)(object)left * (nint)(object)right)) + (nint)(object)addend); + } + else if (typeof(T) == typeof(nuint)) + { + return (T)(object)(nuint)((((nuint)(object)left * (nuint)(object)right)) + (nuint)(object)addend); + } + else if (typeof(T) == typeof(sbyte)) + { + return (T)(object)(sbyte)((((sbyte)(object)left * (sbyte)(object)right)) + (sbyte)(object)addend); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)float.MultiplyAddEstimate((float)(object)left, (float)(object)right, (float)(object)addend); + } + else if (typeof(T) == typeof(ushort)) + { + return (T)(object)(ushort)((((ushort)(object)left * (ushort)(object)right)) + (ushort)(object)addend); + } + else if (typeof(T) == typeof(uint)) + { + return (T)(object)(uint)((((uint)(object)left * (uint)(object)right)) + (uint)(object)addend); + } + else if (typeof(T) == typeof(ulong)) + { + return (T)(object)(ulong)((((ulong)(object)left * (ulong)(object)right)) + (ulong)(object)addend); + } + else + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported); + return default!; + } + } + public static bool ObjectEquals(T left, T right) { if (typeof(T) == typeof(byte)) @@ -895,6 +1259,24 @@ public static bool ObjectEquals(T left, T right) } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Round(T value) + { + if (typeof(T) == typeof(double)) + { + return (T)(object)Math.Round((double)(object)value); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)MathF.Round((float)(object)value); + } + else + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported); + return default!; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T ShiftLeft(T value, int shiftCount) { @@ -1196,6 +1578,24 @@ public static T Subtract(T left, T right) return default!; } } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Truncate(T value) + { + if (typeof(T) == typeof(double)) + { + return (T)(object)Math.Truncate((double)(object)value); + } + else if (typeof(T) == typeof(float)) + { + return (T)(object)MathF.Truncate((float)(object)value); + } + else + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported); + return default!; + } + } } } 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 0d98b599a5b2d..2011025c0455d 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 @@ -448,6 +448,22 @@ internal static Vector128 Ceiling(Vector128 vector) [Intrinsic] public static Vector128 Ceiling(Vector128 vector) => Ceiling(vector); + /// + [Intrinsic] + public static Vector128 Clamp(Vector128 value, Vector128 min, Vector128 max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return Min(Max(value, min), max); + } + + /// + [Intrinsic] + public static Vector128 ClampNative(Vector128 value, Vector128 min, Vector128 max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return MinNative(MaxNative(value, min), max); + } + /// Conditionally selects a value from two vectors on a bitwise basis. /// The type of the elements in the vector. /// The mask that is used to select a value from or . @@ -718,6 +734,32 @@ public static unsafe Vector128 ConvertToUInt64Native(Vector128 ve ); } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 CopySign(Vector128 value, Vector128 sign) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return value; + } + else if (IsHardwareAccelerated) + { + return VectorMath.CopySign, T>(value, sign); + } + else + { + return Create( + Vector64.CopySign(value._lower, sign._lower), + Vector64.CopySign(value._upper, sign._upper) + ); + } + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. @@ -963,7 +1005,7 @@ public static Vector128 Create(ReadOnlySpan values) public static unsafe Vector128 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7, byte e8, byte e9, byte e10, byte e11, byte e12, byte e13, byte e14, byte e15) { return Create( - Vector64.Create(e0, e1, e2, e3, e4, e5, e6, e7), + Vector64.Create(e0, e1, e2, e3, e4, e5, e6, e7), Vector64.Create(e8, e9, e10, e11, e12, e13, e14, e15) ); } @@ -1061,7 +1103,7 @@ public static unsafe Vector128 Create(long e0, long e1) public static unsafe Vector128 Create(sbyte e0, sbyte e1, sbyte e2, sbyte e3, sbyte e4, sbyte e5, sbyte e6, sbyte e7, sbyte e8, sbyte e9, sbyte e10, sbyte e11, sbyte e12, sbyte e13, sbyte e14, sbyte e15) { return Create( - Vector64.Create(e0, e1, e2, e3, e4, e5, e6, e7), + Vector64.Create(e0, e1, e2, e3, e4, e5, e6, e7), Vector64.Create(e8, e9, e10, e11, e12, e13, e14, e15) ); } @@ -1441,6 +1483,42 @@ public static Vector128 CreateScalarUnsafe(T value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 CreateSequence(T start, T step) => (Vector128.Indices * step) + Create(start); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 DegreesToRadians(Vector128 degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, double>(degrees); + } + else + { + return Create( + Vector64.DegreesToRadians(degrees._lower), + Vector64.DegreesToRadians(degrees._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 DegreesToRadians(Vector128 degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, float>(degrees); + } + else + { + return Create( + Vector64.DegreesToRadians(degrees._lower), + Vector64.DegreesToRadians(degrees._upper) + ); + } + } + /// Divides two vectors to compute their quotient. /// The type of the elements in the vector. /// The vector that will be divided by . @@ -1754,6 +1832,163 @@ public static bool GreaterThanOrEqualAny(Vector128 left, Vector128 righ || Vector64.GreaterThanOrEqualAny(left._upper, right._upper); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 Hypot(Vector128 x, Vector128 y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotDouble, Vector128>(x, y); + } + else + { + return Create( + Vector64.Hypot(x._lower, y._lower), + Vector64.Hypot(x._upper, y._upper) + ); + } + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 Hypot(Vector128 x, Vector128 y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotSingle, Vector128>(x, y); + } + else + { + return Create( + Vector64.Hypot(x._lower, y._lower), + Vector64.Hypot(x._upper, y._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsNaN(Vector128 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return ~Equals(vector, vector); + } + return Vector128.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsNegative(Vector128 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector128.Zero; + } + else if (typeof(T) == typeof(float)) + { + return LessThan(vector.AsInt32(), Vector128.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(vector.AsInt64(), Vector128.Zero).As(); + } + else + { + return LessThan(vector, Vector128.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsPositive(Vector128 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector128.AllBitsSet; + } + else if (typeof(T) == typeof(float)) + { + return GreaterThanOrEqual(vector.AsInt32(), Vector128.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return GreaterThanOrEqual(vector.AsInt64(), Vector128.Zero).As(); + } + else + { + return GreaterThanOrEqual(vector, Vector128.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsPositiveInfinity(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.PositiveInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.PositiveInfinity).As()); + } + return Vector128.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsZero(Vector128 vector) => Equals(vector, Vector128.Zero); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 Lerp(Vector128 x, Vector128 y, Vector128 amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, double>(x, y, amount); + } + else + { + return Create( + Vector64.Lerp(x._lower, y._lower, amount._lower), + Vector64.Lerp(x._upper, y._upper, amount._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 Lerp(Vector128 x, Vector128 y, Vector128 amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, float>(x, y, amount); + } + else + { + return Create( + Vector64.Lerp(x._lower, y._lower, amount._lower), + Vector64.Lerp(x._upper, y._upper, amount._upper) + ); + } + } + /// Compares two vectors to determine which is less on a per-element basis. /// The type of the elements in the vector. /// The vector to compare with . @@ -1992,36 +2227,184 @@ public static Vector128 Log2(Vector128 vector) } } - /// Computes the maximum of two vectors on a per-element basis. - /// The type of the elements in the vector. - /// The vector to compare with . - /// The vector to compare with . - /// A vector whose elements are the maximum of the corresponding elements in and . - /// The type of and () is not supported. + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Max(Vector128 left, Vector128 right) { - return Create( - Vector64.Max(left._lower, right._lower), - Vector64.Max(left._upper, right._upper) - ); + if (IsHardwareAccelerated) + { + return VectorMath.Max, T>(left, right); + } + else + { + return Create( + Vector64.Max(left._lower, right._lower), + Vector64.Max(left._upper, right._upper) + ); + } } - /// Computes the minimum of two vectors on a per-element basis. - /// The type of the elements in the vector. - /// The vector to compare with . - /// The vector to compare with . - /// A vector whose elements are the minimum of the corresponding elements in and . - /// The type of and () is not supported. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MaxMagnitude(Vector128 left, Vector128 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxMagnitude, T>(left, right); + } + else + { + return Create( + Vector64.MaxMagnitude(left._lower, right._lower), + Vector64.MaxMagnitude(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MaxMagnitudeNumber(Vector128 left, Vector128 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxMagnitudeNumber, T>(left, right); + } + else + { + return Create( + Vector64.MaxMagnitudeNumber(left._lower, right._lower), + Vector64.MaxMagnitudeNumber(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MaxNative(Vector128 left, Vector128 right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(GreaterThan(left, right), left, right); + } + else + { + return Create( + Vector64.MaxNative(left._lower, right._lower), + Vector64.MaxNative(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MaxNumber(Vector128 left, Vector128 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxNumber, T>(left, right); + } + else + { + return Create( + Vector64.MaxNumber(left._lower, right._lower), + Vector64.MaxNumber(left._upper, right._upper) + ); + } + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Min(Vector128 left, Vector128 right) { - return Create( - Vector64.Min(left._lower, right._lower), - Vector64.Min(left._upper, right._upper) - ); + if (IsHardwareAccelerated) + { + return VectorMath.Min, T>(left, right); + } + else + { + return Create( + Vector64.Min(left._lower, right._lower), + Vector64.Min(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MinMagnitude(Vector128 left, Vector128 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinMagnitude, T>(left, right); + } + else + { + return Create( + Vector64.MinMagnitude(left._lower, right._lower), + Vector64.MinMagnitude(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MinMagnitudeNumber(Vector128 left, Vector128 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinMagnitudeNumber, T>(left, right); + } + else + { + return Create( + Vector64.MinMagnitudeNumber(left._lower, right._lower), + Vector64.MinMagnitudeNumber(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MinNative(Vector128 left, Vector128 right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(LessThan(left, right), left, right); + } + else + { + return Create( + Vector64.MinNative(left._lower, right._lower), + Vector64.MinNative(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MinNumber(Vector128 left, Vector128 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinNumber, T>(left, right); + } + else + { + return Create( + Vector64.MinNumber(left._lower, right._lower), + Vector64.MinNumber(left._upper, right._upper) + ); + } } /// Multiplies two vectors to compute their element-wise product. @@ -2051,6 +2434,16 @@ public static Vector128 Min(Vector128 left, Vector128 right) [Intrinsic] public static Vector128 Multiply(T left, Vector128 right) => right * left; + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128 MultiplyAddEstimate(Vector128 left, Vector128 right, Vector128 addend) + { + return Create( + Vector64.MultiplyAddEstimate(left._lower, right._lower, addend._lower), + Vector64.MultiplyAddEstimate(left._upper, right._upper, addend._upper) + ); + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2124,10 +2517,10 @@ public static unsafe Vector128 Narrow(Vector128 lower, Vector128 Narrow(Vector128 lower, Vector128 upper) { - return Create( - Vector64.Narrow(lower._lower, lower._upper), - Vector64.Narrow(upper._lower, upper._upper) - ); + return Create( + Vector64.Narrow(lower._lower, lower._upper), + Vector64.Narrow(upper._lower, upper._upper) + ); } /// Narrows two instances into one . @@ -2191,6 +2584,84 @@ public static unsafe Vector128 Narrow(Vector128 lower, Vector128
    OnesComplement(Vector128 vector) => ~vector; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 RadiansToDegrees(Vector128 radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, double>(radians); + } + else + { + return Create( + Vector64.RadiansToDegrees(radians._lower), + Vector64.RadiansToDegrees(radians._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 RadiansToDegrees(Vector128 radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, float>(radians); + } + else + { + return Create( + Vector64.RadiansToDegrees(radians._lower), + Vector64.RadiansToDegrees(radians._upper) + ); + } + } + + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128 Round(Vector128 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector64.Round(vector._lower), + Vector64.Round(vector._upper) + ); + } + } + + /// + [Intrinsic] + public static Vector128 Round(Vector128 vector) => Round(vector); + + /// + [Intrinsic] + public static Vector128 Round(Vector128 vector) => Round(vector); + + /// + [Intrinsic] + public static Vector128 Round(Vector128 vector, MidpointRounding mode) => VectorMath.RoundDouble(vector, mode); + + /// + [Intrinsic] + public static Vector128 Round(Vector128 vector, MidpointRounding mode) => VectorMath.RoundSingle(vector, mode); + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -2851,6 +3322,40 @@ public static unsafe Vector256 ToVector256Unsafe(this Vector128 vector) return result; } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128 Truncate(Vector128 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector64.Truncate(vector._lower), + Vector64.Truncate(vector._upper) + ); + } + } + + /// + [Intrinsic] + public static Vector128 Truncate(Vector128 vector) => Truncate(vector); + + /// + [Intrinsic] + public static Vector128 Truncate(Vector128 vector) => Truncate(vector); + /// Tries to copy a to a given span. /// The type of the input vector. /// The vector to copy. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs index 23891dcc2b67d..d6118dbc84455 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs @@ -479,9 +479,18 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static Vector128 ISimdVector, T>.Ceiling(Vector128 vector) => Vector128.Ceiling(vector); + /// + static Vector128 ISimdVector, T>.Clamp(Vector128 value, Vector128 min, Vector128 max) => Vector128.Clamp(value, min, max); + + /// + static Vector128 ISimdVector, T>.ClampNative(Vector128 value, Vector128 min, Vector128 max) => Vector128.ClampNative(value, min, max); + /// static Vector128 ISimdVector, T>.ConditionalSelect(Vector128 condition, Vector128 left, Vector128 right) => Vector128.ConditionalSelect(condition, left, right); + /// + static Vector128 ISimdVector, T>.CopySign(Vector128 value, Vector128 sign) => Vector128.CopySign(value, sign); + /// static void ISimdVector, T>.CopyTo(Vector128 vector, T[] destination) => vector.CopyTo(destination); @@ -589,21 +598,51 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static Vector128 ISimdVector, T>.Max(Vector128 left, Vector128 right) => Vector128.Max(left, right); + /// + static Vector128 ISimdVector, T>.MaxMagnitude(Vector128 left, Vector128 right) => Vector128.MaxMagnitude(left, right); + + /// + static Vector128 ISimdVector, T>.MaxMagnitudeNumber(Vector128 left, Vector128 right) => Vector128.MaxMagnitudeNumber(left, right); + + /// + static Vector128 ISimdVector, T>.MaxNative(Vector128 left, Vector128 right) => Vector128.MaxNative(left, right); + + /// + static Vector128 ISimdVector, T>.MaxNumber(Vector128 left, Vector128 right) => Vector128.MaxNumber(left, right); + /// static Vector128 ISimdVector, T>.Min(Vector128 left, Vector128 right) => Vector128.Min(left, right); + /// + static Vector128 ISimdVector, T>.MinMagnitude(Vector128 left, Vector128 right) => Vector128.MinMagnitude(left, right); + + /// + static Vector128 ISimdVector, T>.MinMagnitudeNumber(Vector128 left, Vector128 right) => Vector128.MinMagnitudeNumber(left, right); + + /// + static Vector128 ISimdVector, T>.MinNative(Vector128 left, Vector128 right) => Vector128.MinNative(left, right); + + /// + static Vector128 ISimdVector, T>.MinNumber(Vector128 left, Vector128 right) => Vector128.MinNumber(left, right); + /// static Vector128 ISimdVector, T>.Multiply(Vector128 left, Vector128 right) => left * right; /// static Vector128 ISimdVector, T>.Multiply(Vector128 left, T right) => left * right; + /// + static Vector128 ISimdVector, T>.MultiplyAddEstimate(Vector128 left, Vector128 right, Vector128 addend) => Vector128.MultiplyAddEstimate(left, right, addend); + /// static Vector128 ISimdVector, T>.Negate(Vector128 vector) => -vector; /// static Vector128 ISimdVector, T>.OnesComplement(Vector128 vector) => ~vector; + /// + static Vector128 ISimdVector, T>.Round(Vector128 vector) => Vector128.Round(vector); + /// static Vector128 ISimdVector, T>.ShiftLeft(Vector128 vector, int shiftCount) => vector << shiftCount; @@ -642,6 +681,9 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static T ISimdVector, T>.ToScalar(Vector128 vector) => vector.ToScalar(); + /// + static Vector128 ISimdVector, T>.Truncate(Vector128 vector) => Vector128.Truncate(vector); + /// static bool ISimdVector, T>.TryCopyTo(Vector128 vector, Span destination) => vector.TryCopyTo(destination); @@ -664,5 +706,15 @@ static int ISimdVector, T>.IndexOfLastMatch(Vector128 vector) uint mask = vector.ExtractMostSignificantBits(); return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) } + + static Vector128 ISimdVector, T>.IsNaN(Vector128 vector) => Vector128.IsNaN(vector); + + static Vector128 ISimdVector, T>.IsNegative(Vector128 vector) => Vector128.IsNegative(vector); + + static Vector128 ISimdVector, T>.IsPositive(Vector128 vector) => Vector128.IsPositive(vector); + + static Vector128 ISimdVector, T>.IsPositiveInfinity(Vector128 vector) => Vector128.IsPositiveInfinity(vector); + + static Vector128 ISimdVector, T>.IsZero(Vector128 vector) => Vector128.IsZero(vector); } } 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 4278e01d5f3fc..d1dde486f5803 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 @@ -313,6 +313,22 @@ internal static Vector256 Ceiling(Vector256 vector) [Intrinsic] public static Vector256 Ceiling(Vector256 vector) => Ceiling(vector); + /// + [Intrinsic] + public static Vector256 Clamp(Vector256 value, Vector256 min, Vector256 max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return Min(Max(value, min), max); + } + + /// + [Intrinsic] + public static Vector256 ClampNative(Vector256 value, Vector256 min, Vector256 max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return MinNative(MaxNative(value, min), max); + } + /// Conditionally selects a value from two vectors on a bitwise basis. /// The type of the elements in the vector. /// The mask that is used to select a value from or . @@ -557,6 +573,32 @@ public static Vector256 ConvertToUInt64Native(Vector256 vector) ); } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 CopySign(Vector256 value, Vector256 sign) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return value; + } + else if (IsHardwareAccelerated) + { + return VectorMath.CopySign, T>(value, sign); + } + else + { + return Create( + Vector128.CopySign(value._lower, sign._lower), + Vector128.CopySign(value._upper, sign._upper) + ); + } + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. @@ -1359,6 +1401,42 @@ public static Vector256 CreateScalarUnsafe(T value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 CreateSequence(T start, T step) => (Vector256.Indices * step) + Create(start); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 DegreesToRadians(Vector256 degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, double>(degrees); + } + else + { + return Create( + Vector128.DegreesToRadians(degrees._lower), + Vector128.DegreesToRadians(degrees._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 DegreesToRadians(Vector256 degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, float>(degrees); + } + else + { + return Create( + Vector128.DegreesToRadians(degrees._lower), + Vector128.DegreesToRadians(degrees._upper) + ); + } + } + /// Divides two vectors to compute their quotient. /// The type of the elements in the vector. /// The vector that will be divided by . @@ -1670,6 +1748,163 @@ public static bool GreaterThanOrEqualAny(Vector256 left, Vector256 righ || Vector128.GreaterThanOrEqualAny(left._upper, right._upper); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Hypot(Vector256 x, Vector256 y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotDouble, Vector256>(x, y); + } + else + { + return Create( + Vector128.Hypot(x._lower, y._lower), + Vector128.Hypot(x._upper, y._upper) + ); + } + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Hypot(Vector256 x, Vector256 y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotSingle, Vector256>(x, y); + } + else + { + return Create( + Vector128.Hypot(x._lower, y._lower), + Vector128.Hypot(x._upper, y._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsNaN(Vector256 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return ~Equals(vector, vector); + } + return Vector256.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsNegative(Vector256 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector256.Zero; + } + else if (typeof(T) == typeof(float)) + { + return LessThan(vector.AsInt32(), Vector256.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(vector.AsInt64(), Vector256.Zero).As(); + } + else + { + return LessThan(vector, Vector256.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsPositive(Vector256 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector256.AllBitsSet; + } + else if (typeof(T) == typeof(float)) + { + return GreaterThanOrEqual(vector.AsInt32(), Vector256.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return GreaterThanOrEqual(vector.AsInt64(), Vector256.Zero).As(); + } + else + { + return GreaterThanOrEqual(vector, Vector256.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsPositiveInfinity(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.PositiveInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.PositiveInfinity).As()); + } + return Vector256.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsZero(Vector256 vector) => Equals(vector, Vector256.Zero); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Lerp(Vector256 x, Vector256 y, Vector256 amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, double>(x, y, amount); + } + else + { + return Create( + Vector128.Lerp(x._lower, y._lower, amount._lower), + Vector128.Lerp(x._upper, y._upper, amount._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Lerp(Vector256 x, Vector256 y, Vector256 amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, float>(x, y, amount); + } + else + { + return Create( + Vector128.Lerp(x._lower, y._lower, amount._lower), + Vector128.Lerp(x._upper, y._upper, amount._upper) + ); + } + } + /// Compares two vectors to determine which is less on a per-element basis. /// The type of the elements in the vector. /// The vector to compare with . @@ -1908,36 +2143,184 @@ public static Vector256 Log2(Vector256 vector) } } - /// Computes the maximum of two vectors on a per-element basis. - /// The type of the elements in the vector. - /// The vector to compare with . - /// The vector to compare with . - /// A vector whose elements are the maximum of the corresponding elements in and . - /// The type of and () is not supported. + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Max(Vector256 left, Vector256 right) { - return Create( - Vector128.Max(left._lower, right._lower), - Vector128.Max(left._upper, right._upper) - ); + if (IsHardwareAccelerated) + { + return VectorMath.Max, T>(left, right); + } + else + { + return Create( + Vector128.Max(left._lower, right._lower), + Vector128.Max(left._upper, right._upper) + ); + } } - /// Computes the minimum of two vectors on a per-element basis. - /// The type of the elements in the vector. - /// The vector to compare with . - /// The vector to compare with . - /// A vector whose elements are the minimum of the corresponding elements in and . - /// The type of and () is not supported. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MaxMagnitude(Vector256 left, Vector256 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxMagnitude, T>(left, right); + } + else + { + return Create( + Vector128.MaxMagnitude(left._lower, right._lower), + Vector128.MaxMagnitude(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MaxMagnitudeNumber(Vector256 left, Vector256 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxMagnitudeNumber, T>(left, right); + } + else + { + return Create( + Vector128.MaxMagnitudeNumber(left._lower, right._lower), + Vector128.MaxMagnitudeNumber(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MaxNative(Vector256 left, Vector256 right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(GreaterThan(left, right), left, right); + } + else + { + return Create( + Vector128.MaxNative(left._lower, right._lower), + Vector128.MaxNative(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MaxNumber(Vector256 left, Vector256 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxNumber, T>(left, right); + } + else + { + return Create( + Vector128.MaxNumber(left._lower, right._lower), + Vector128.MaxNumber(left._upper, right._upper) + ); + } + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Min(Vector256 left, Vector256 right) { - return Create( - Vector128.Min(left._lower, right._lower), - Vector128.Min(left._upper, right._upper) - ); + if (IsHardwareAccelerated) + { + return VectorMath.Min, T>(left, right); + } + else + { + return Create( + Vector128.Min(left._lower, right._lower), + Vector128.Min(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MinMagnitude(Vector256 left, Vector256 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinMagnitude, T>(left, right); + } + else + { + return Create( + Vector128.MinMagnitude(left._lower, right._lower), + Vector128.MinMagnitude(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MinMagnitudeNumber(Vector256 left, Vector256 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinMagnitudeNumber, T>(left, right); + } + else + { + return Create( + Vector128.MinMagnitudeNumber(left._lower, right._lower), + Vector128.MinMagnitudeNumber(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MinNative(Vector256 left, Vector256 right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(LessThan(left, right), left, right); + } + else + { + return Create( + Vector128.MinNative(left._lower, right._lower), + Vector128.MinNative(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MinNumber(Vector256 left, Vector256 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinNumber, T>(left, right); + } + else + { + return Create( + Vector128.MinNumber(left._lower, right._lower), + Vector128.MinNumber(left._upper, right._upper) + ); + } } /// Multiplies two vectors to compute their element-wise product. @@ -1967,6 +2350,16 @@ public static Vector256 Min(Vector256 left, Vector256 right) [Intrinsic] public static Vector256 Multiply(T left, Vector256 right) => right * left; + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector256 MultiplyAddEstimate(Vector256 left, Vector256 right, Vector256 addend) + { + return Create( + Vector128.MultiplyAddEstimate(left._lower, right._lower, addend._lower), + Vector128.MultiplyAddEstimate(left._upper, right._upper, addend._upper) + ); + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2107,6 +2500,84 @@ public static Vector256 Narrow(Vector256 lower, Vector256 up [Intrinsic] public static Vector256 OnesComplement(Vector256 vector) => ~vector; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 RadiansToDegrees(Vector256 radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, double>(radians); + } + else + { + return Create( + Vector128.RadiansToDegrees(radians._lower), + Vector128.RadiansToDegrees(radians._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 RadiansToDegrees(Vector256 radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, float>(radians); + } + else + { + return Create( + Vector128.RadiansToDegrees(radians._lower), + Vector128.RadiansToDegrees(radians._upper) + ); + } + } + + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector256 Round(Vector256 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector128.Round(vector._lower), + Vector128.Round(vector._upper) + ); + } + } + + /// + [Intrinsic] + public static Vector256 Round(Vector256 vector) => Round(vector); + + /// + [Intrinsic] + public static Vector256 Round(Vector256 vector) => Round(vector); + + /// + [Intrinsic] + public static Vector256 Round(Vector256 vector, MidpointRounding mode) => VectorMath.RoundDouble(vector, mode); + + /// + [Intrinsic] + public static Vector256 Round(Vector256 vector, MidpointRounding mode) => VectorMath.RoundSingle(vector, mode); + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -2716,6 +3187,40 @@ public static unsafe Vector512 ToVector512Unsafe(this Vector256 vector) return result; } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector256 Truncate(Vector256 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector128.Truncate(vector._lower), + Vector128.Truncate(vector._upper) + ); + } + } + + /// + [Intrinsic] + public static Vector256 Truncate(Vector256 vector) => Truncate(vector); + + /// + [Intrinsic] + public static Vector256 Truncate(Vector256 vector) => Truncate(vector); + /// Tries to copy a to a given span. /// The type of the input vector. /// The vector to copy. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs index c4120a2c2febe..f886b55e18d91 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs @@ -468,9 +468,18 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static Vector256 ISimdVector, T>.Ceiling(Vector256 vector) => Vector256.Ceiling(vector); + /// + static Vector256 ISimdVector, T>.Clamp(Vector256 value, Vector256 min, Vector256 max) => Vector256.Clamp(value, min, max); + + /// + static Vector256 ISimdVector, T>.ClampNative(Vector256 value, Vector256 min, Vector256 max) => Vector256.ClampNative(value, min, max); + /// static Vector256 ISimdVector, T>.ConditionalSelect(Vector256 condition, Vector256 left, Vector256 right) => Vector256.ConditionalSelect(condition, left, right); + /// + static Vector256 ISimdVector, T>.CopySign(Vector256 value, Vector256 sign) => Vector256.CopySign(value, sign); + /// static void ISimdVector, T>.CopyTo(Vector256 vector, T[] destination) => vector.CopyTo(destination); @@ -578,21 +587,51 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static Vector256 ISimdVector, T>.Max(Vector256 left, Vector256 right) => Vector256.Max(left, right); + /// + static Vector256 ISimdVector, T>.MaxMagnitude(Vector256 left, Vector256 right) => Vector256.MaxMagnitude(left, right); + + /// + static Vector256 ISimdVector, T>.MaxMagnitudeNumber(Vector256 left, Vector256 right) => Vector256.MaxMagnitudeNumber(left, right); + + /// + static Vector256 ISimdVector, T>.MaxNative(Vector256 left, Vector256 right) => Vector256.MaxNative(left, right); + + /// + static Vector256 ISimdVector, T>.MaxNumber(Vector256 left, Vector256 right) => Vector256.MaxNumber(left, right); + /// static Vector256 ISimdVector, T>.Min(Vector256 left, Vector256 right) => Vector256.Min(left, right); + /// + static Vector256 ISimdVector, T>.MinMagnitude(Vector256 left, Vector256 right) => Vector256.MinMagnitude(left, right); + + /// + static Vector256 ISimdVector, T>.MinMagnitudeNumber(Vector256 left, Vector256 right) => Vector256.MinMagnitudeNumber(left, right); + + /// + static Vector256 ISimdVector, T>.MinNative(Vector256 left, Vector256 right) => Vector256.MinNative(left, right); + + /// + static Vector256 ISimdVector, T>.MinNumber(Vector256 left, Vector256 right) => Vector256.MinNumber(left, right); + /// static Vector256 ISimdVector, T>.Multiply(Vector256 left, Vector256 right) => left * right; /// static Vector256 ISimdVector, T>.Multiply(Vector256 left, T right) => left * right; + /// + static Vector256 ISimdVector, T>.MultiplyAddEstimate(Vector256 left, Vector256 right, Vector256 addend) => Vector256.MultiplyAddEstimate(left, right, addend); + /// static Vector256 ISimdVector, T>.Negate(Vector256 vector) => -vector; /// static Vector256 ISimdVector, T>.OnesComplement(Vector256 vector) => ~vector; + /// + static Vector256 ISimdVector, T>.Round(Vector256 vector) => Vector256.Round(vector); + /// static Vector256 ISimdVector, T>.ShiftLeft(Vector256 vector, int shiftCount) => vector << shiftCount; @@ -631,6 +670,9 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static T ISimdVector, T>.ToScalar(Vector256 vector) => vector.ToScalar(); + /// + static Vector256 ISimdVector, T>.Truncate(Vector256 vector) => Vector256.Truncate(vector); + /// static bool ISimdVector, T>.TryCopyTo(Vector256 vector, Span destination) => vector.TryCopyTo(destination); @@ -653,5 +695,15 @@ static int ISimdVector, T>.IndexOfLastMatch(Vector256 vector) uint mask = vector.ExtractMostSignificantBits(); return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) } + + static Vector256 ISimdVector, T>.IsNaN(Vector256 vector) => Vector256.IsNaN(vector); + + static Vector256 ISimdVector, T>.IsNegative(Vector256 vector) => Vector256.IsNegative(vector); + + static Vector256 ISimdVector, T>.IsPositive(Vector256 vector) => Vector256.IsPositive(vector); + + static Vector256 ISimdVector, T>.IsPositiveInfinity(Vector256 vector) => Vector256.IsPositiveInfinity(vector); + + static Vector256 ISimdVector, T>.IsZero(Vector256 vector) => Vector256.IsZero(vector); } } 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 2a51991749e8e..7a22ec7681824 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 @@ -313,6 +313,22 @@ internal static Vector512 Ceiling(Vector512 vector) [Intrinsic] public static Vector512 Ceiling(Vector512 vector) => Ceiling(vector); + /// + [Intrinsic] + public static Vector512 Clamp(Vector512 value, Vector512 min, Vector512 max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return Min(Max(value, min), max); + } + + /// + [Intrinsic] + public static Vector512 ClampNative(Vector512 value, Vector512 min, Vector512 max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return MinNative(MaxNative(value, min), max); + } + /// Conditionally selects a value from two vectors on a bitwise basis. /// The type of the elements in the vector. /// The mask that is used to select a value from or . @@ -486,6 +502,32 @@ public static Vector512 ConvertToUInt64Native(Vector512 vector) ); } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 CopySign(Vector512 value, Vector512 sign) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return value; + } + else if (IsHardwareAccelerated) + { + return VectorMath.CopySign, T>(value, sign); + } + else + { + return Create( + Vector256.CopySign(value._lower, sign._lower), + Vector256.CopySign(value._upper, sign._upper) + ); + } + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. @@ -1421,6 +1463,42 @@ public static Vector512 CreateScalarUnsafe(T value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 CreateSequence(T start, T step) => (Vector512.Indices * step) + Create(start); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 DegreesToRadians(Vector512 degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, double>(degrees); + } + else + { + return Create( + Vector256.DegreesToRadians(degrees._lower), + Vector256.DegreesToRadians(degrees._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 DegreesToRadians(Vector512 degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, float>(degrees); + } + else + { + return Create( + Vector256.DegreesToRadians(degrees._lower), + Vector256.DegreesToRadians(degrees._upper) + ); + } + } + /// Divides two vectors to compute their quotient. /// The type of the elements in the vector. /// The vector that will be divided by . @@ -1733,6 +1811,163 @@ public static bool GreaterThanOrEqualAny(Vector512 left, Vector512 righ || Vector256.GreaterThanOrEqualAny(left._upper, right._upper); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Hypot(Vector512 x, Vector512 y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotDouble, Vector512>(x, y); + } + else + { + return Create( + Vector256.Hypot(x._lower, y._lower), + Vector256.Hypot(x._upper, y._upper) + ); + } + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Hypot(Vector512 x, Vector512 y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotSingle, Vector512>(x, y); + } + else + { + return Create( + Vector256.Hypot(x._lower, y._lower), + Vector256.Hypot(x._upper, y._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsNaN(Vector512 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return ~Equals(vector, vector); + } + return Vector512.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsNegative(Vector512 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector512.Zero; + } + else if (typeof(T) == typeof(float)) + { + return LessThan(vector.AsInt32(), Vector512.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(vector.AsInt64(), Vector512.Zero).As(); + } + else + { + return LessThan(vector, Vector512.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsPositive(Vector512 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector512.AllBitsSet; + } + else if (typeof(T) == typeof(float)) + { + return GreaterThanOrEqual(vector.AsInt32(), Vector512.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return GreaterThanOrEqual(vector.AsInt64(), Vector512.Zero).As(); + } + else + { + return GreaterThanOrEqual(vector, Vector512.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsPositiveInfinity(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.PositiveInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.PositiveInfinity).As()); + } + return Vector512.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsZero(Vector512 vector) => Equals(vector, Vector512.Zero); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Lerp(Vector512 x, Vector512 y, Vector512 amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, double>(x, y, amount); + } + else + { + return Create( + Vector256.Lerp(x._lower, y._lower, amount._lower), + Vector256.Lerp(x._upper, y._upper, amount._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Lerp(Vector512 x, Vector512 y, Vector512 amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, float>(x, y, amount); + } + else + { + return Create( + Vector256.Lerp(x._lower, y._lower, amount._lower), + Vector256.Lerp(x._upper, y._upper, amount._upper) + ); + } + } + /// Compares two vectors to determine which is less on a per-element basis. /// The type of the elements in the vector. /// The vector to compare with . @@ -1971,36 +2206,184 @@ public static Vector512 Log2(Vector512 vector) } } - /// Computes the maximum of two vectors on a per-element basis. - /// The type of the elements in the vector. - /// The vector to compare with . - /// The vector to compare with . - /// A vector whose elements are the maximum of the corresponding elements in and . - /// The type of and () is not supported. + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Max(Vector512 left, Vector512 right) { - return Create( - Vector256.Max(left._lower, right._lower), - Vector256.Max(left._upper, right._upper) - ); + if (IsHardwareAccelerated) + { + return VectorMath.Max, T>(left, right); + } + else + { + return Create( + Vector256.Max(left._lower, right._lower), + Vector256.Max(left._upper, right._upper) + ); + } } - /// Computes the minimum of two vectors on a per-element basis. - /// The type of the elements in the vector. - /// The vector to compare with . - /// The vector to compare with . - /// A vector whose elements are the minimum of the corresponding elements in and . - /// The type of and () is not supported. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 MaxMagnitude(Vector512 left, Vector512 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxMagnitude, T>(left, right); + } + else + { + return Create( + Vector256.MaxMagnitude(left._lower, right._lower), + Vector256.MaxMagnitude(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 MaxMagnitudeNumber(Vector512 left, Vector512 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxMagnitudeNumber, T>(left, right); + } + else + { + return Create( + Vector256.MaxMagnitudeNumber(left._lower, right._lower), + Vector256.MaxMagnitudeNumber(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 MaxNative(Vector512 left, Vector512 right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(GreaterThan(left, right), left, right); + } + else + { + return Create( + Vector256.MaxNative(left._lower, right._lower), + Vector256.MaxNative(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 MaxNumber(Vector512 left, Vector512 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxNumber, T>(left, right); + } + else + { + return Create( + Vector256.MaxNumber(left._lower, right._lower), + Vector256.MaxNumber(left._upper, right._upper) + ); + } + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Min(Vector512 left, Vector512 right) { - return Create( - Vector256.Min(left._lower, right._lower), - Vector256.Min(left._upper, right._upper) - ); + if (IsHardwareAccelerated) + { + return VectorMath.Min, T>(left, right); + } + else + { + return Create( + Vector256.Min(left._lower, right._lower), + Vector256.Min(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 MinMagnitude(Vector512 left, Vector512 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinMagnitude, T>(left, right); + } + else + { + return Create( + Vector256.MinMagnitude(left._lower, right._lower), + Vector256.MinMagnitude(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 MinMagnitudeNumber(Vector512 left, Vector512 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinMagnitudeNumber, T>(left, right); + } + else + { + return Create( + Vector256.MinMagnitudeNumber(left._lower, right._lower), + Vector256.MinMagnitudeNumber(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 MinNative(Vector512 left, Vector512 right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(LessThan(left, right), left, right); + } + else + { + return Create( + Vector256.MinNative(left._lower, right._lower), + Vector256.MinNative(left._upper, right._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 MinNumber(Vector512 left, Vector512 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinNumber, T>(left, right); + } + else + { + return Create( + Vector256.MinNumber(left._lower, right._lower), + Vector256.MinNumber(left._upper, right._upper) + ); + } } /// Multiplies two vectors to compute their element-wise product. @@ -2030,6 +2413,16 @@ public static Vector512 Min(Vector512 left, Vector512 right) [Intrinsic] public static Vector512 Multiply(T left, Vector512 right) => right * left; + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector512 MultiplyAddEstimate(Vector512 left, Vector512 right, Vector512 addend) + { + return Create( + Vector256.MultiplyAddEstimate(left._lower, right._lower, addend._lower), + Vector256.MultiplyAddEstimate(left._upper, right._upper, addend._upper) + ); + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2169,6 +2562,84 @@ public static Vector512 Narrow(Vector512 lower, Vector512 up [Intrinsic] public static Vector512 OnesComplement(Vector512 vector) => ~vector; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 RadiansToDegrees(Vector512 radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, double>(radians); + } + else + { + return Create( + Vector256.RadiansToDegrees(radians._lower), + Vector256.RadiansToDegrees(radians._upper) + ); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 RadiansToDegrees(Vector512 radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, float>(radians); + } + else + { + return Create( + Vector256.RadiansToDegrees(radians._lower), + Vector256.RadiansToDegrees(radians._upper) + ); + } + } + + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector512 Round(Vector512 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector256.Round(vector._lower), + Vector256.Round(vector._upper) + ); + } + } + + /// + [Intrinsic] + public static Vector512 Round(Vector512 vector) => Round(vector); + + /// + [Intrinsic] + public static Vector512 Round(Vector512 vector) => Round(vector); + + /// + [Intrinsic] + public static Vector512 Round(Vector512 vector, MidpointRounding mode) => VectorMath.RoundDouble(vector, mode); + + /// + [Intrinsic] + public static Vector512 Round(Vector512 vector, MidpointRounding mode) => VectorMath.RoundSingle(vector, mode); + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -2745,6 +3216,40 @@ public static T ToScalar(this Vector512 vector) return vector.GetElementUnsafe(0); } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector512 Truncate(Vector512 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector256.Truncate(vector._lower), + Vector256.Truncate(vector._upper) + ); + } + } + + /// + [Intrinsic] + public static Vector512 Truncate(Vector512 vector) => Truncate(vector); + + /// + [Intrinsic] + public static Vector512 Truncate(Vector512 vector) => Truncate(vector); + /// Tries to copy a to a given span. /// The type of the input vector. /// The vector to copy. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs index 86a8acd823660..7fb65ad7583e0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs @@ -468,9 +468,18 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static Vector512 ISimdVector, T>.Ceiling(Vector512 vector) => Vector512.Ceiling(vector); + /// + static Vector512 ISimdVector, T>.Clamp(Vector512 value, Vector512 min, Vector512 max) => Vector512.Clamp(value, min, max); + + /// + static Vector512 ISimdVector, T>.ClampNative(Vector512 value, Vector512 min, Vector512 max) => Vector512.ClampNative(value, min, max); + /// static Vector512 ISimdVector, T>.ConditionalSelect(Vector512 condition, Vector512 left, Vector512 right) => Vector512.ConditionalSelect(condition, left, right); + /// + static Vector512 ISimdVector, T>.CopySign(Vector512 value, Vector512 sign) => Vector512.CopySign(value, sign); + /// static void ISimdVector, T>.CopyTo(Vector512 vector, T[] destination) => vector.CopyTo(destination); @@ -578,21 +587,51 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static Vector512 ISimdVector, T>.Max(Vector512 left, Vector512 right) => Vector512.Max(left, right); + /// + static Vector512 ISimdVector, T>.MaxMagnitude(Vector512 left, Vector512 right) => Vector512.MaxMagnitude(left, right); + + /// + static Vector512 ISimdVector, T>.MaxMagnitudeNumber(Vector512 left, Vector512 right) => Vector512.MaxMagnitudeNumber(left, right); + + /// + static Vector512 ISimdVector, T>.MaxNative(Vector512 left, Vector512 right) => Vector512.MaxNative(left, right); + + /// + static Vector512 ISimdVector, T>.MaxNumber(Vector512 left, Vector512 right) => Vector512.MaxNumber(left, right); + /// static Vector512 ISimdVector, T>.Min(Vector512 left, Vector512 right) => Vector512.Min(left, right); + /// + static Vector512 ISimdVector, T>.MinMagnitude(Vector512 left, Vector512 right) => Vector512.MinMagnitude(left, right); + + /// + static Vector512 ISimdVector, T>.MinMagnitudeNumber(Vector512 left, Vector512 right) => Vector512.MinMagnitudeNumber(left, right); + + /// + static Vector512 ISimdVector, T>.MinNative(Vector512 left, Vector512 right) => Vector512.MinNative(left, right); + + /// + static Vector512 ISimdVector, T>.MinNumber(Vector512 left, Vector512 right) => Vector512.MinNumber(left, right); + /// static Vector512 ISimdVector, T>.Multiply(Vector512 left, Vector512 right) => left * right; /// static Vector512 ISimdVector, T>.Multiply(Vector512 left, T right) => left * right; + /// + static Vector512 ISimdVector, T>.MultiplyAddEstimate(Vector512 left, Vector512 right, Vector512 addend) => Vector512.MultiplyAddEstimate(left, right, addend); + /// static Vector512 ISimdVector, T>.Negate(Vector512 vector) => -vector; /// static Vector512 ISimdVector, T>.OnesComplement(Vector512 vector) => ~vector; + /// + static Vector512 ISimdVector, T>.Round(Vector512 vector) => Vector512.Round(vector); + /// static Vector512 ISimdVector, T>.ShiftLeft(Vector512 vector, int shiftCount) => vector << shiftCount; @@ -631,6 +670,9 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static T ISimdVector, T>.ToScalar(Vector512 vector) => vector.ToScalar(); + /// + static Vector512 ISimdVector, T>.Truncate(Vector512 vector) => Vector512.Truncate(vector); + /// static bool ISimdVector, T>.TryCopyTo(Vector512 vector, Span destination) => vector.TryCopyTo(destination); @@ -653,5 +695,15 @@ static int ISimdVector, T>.IndexOfLastMatch(Vector512 vector) ulong mask = vector.ExtractMostSignificantBits(); return 63 - BitOperations.LeadingZeroCount(mask); // 63 = 64 (bits in Int64) - 1 (indexing from zero) } + + static Vector512 ISimdVector, T>.IsNaN(Vector512 vector) => Vector512.IsNaN(vector); + + static Vector512 ISimdVector, T>.IsNegative(Vector512 vector) => Vector512.IsNegative(vector); + + static Vector512 ISimdVector, T>.IsPositive(Vector512 vector) => Vector512.IsPositive(vector); + + static Vector512 ISimdVector, T>.IsPositiveInfinity(Vector512 vector) => Vector512.IsPositiveInfinity(vector); + + static Vector512 ISimdVector, T>.IsZero(Vector512 vector) => Vector512.IsZero(vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index 7e1b87c985f72..7203311532d70 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -263,6 +263,22 @@ internal static Vector64 Ceiling(Vector64 vector) [Intrinsic] public static Vector64 Ceiling(Vector64 vector) => Ceiling(vector); + /// + [Intrinsic] + public static Vector64 Clamp(Vector64 value, Vector64 min, Vector64 max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return Min(Max(value, min), max); + } + + /// + [Intrinsic] + public static Vector64 ClampNative(Vector64 value, Vector64 min, Vector64 max) + { + // We must follow HLSL behavior in the case user specified min value is bigger than max value. + return MinNative(MaxNative(value, min), max); + } + /// Conditionally selects a value from two vectors on a bitwise basis. /// The type of the elements in the vector. /// The mask that is used to select a value from or . @@ -496,6 +512,37 @@ public static unsafe Vector64 ConvertToUInt64Native(Vector64 vect return result; } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 CopySign(Vector64 value, Vector64 sign) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return value; + } + else if (IsHardwareAccelerated) + { + return VectorMath.CopySign, T>(value, sign); + } + else + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T element = Scalar.CopySign(value.GetElementUnsafe(index), sign.GetElementUnsafe(index)); + result.SetElementUnsafe(index, element); + } + + return result; + } + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. @@ -1054,6 +1101,54 @@ public static Vector64 CreateScalarUnsafe(T value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector64 CreateSequence(T start, T step) => (Vector64.Indices * step) + Create(start); + internal static Vector64 DegreesToRadians(Vector64 degrees) + where T : ITrigonometricFunctions + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = T.DegreesToRadians(degrees.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// Converts a given vector from degrees to radians. + /// The vector to convert to radians. + /// The vector of converted to radians. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 DegreesToRadians(Vector64 degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, double>(degrees); + } + else + { + return DegreesToRadians(degrees); + } + } + + /// Converts a given vector from degrees to radians. + /// The vector to convert to radians. + /// The vector of converted to radians. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 DegreesToRadians(Vector64 degrees) + { + if (IsHardwareAccelerated) + { + return VectorMath.DegreesToRadians, float>(degrees); + } + else + { + return DegreesToRadians(degrees); + } + } + /// Divides two vectors to compute their quotient. /// The type of the elements in the vector. /// The vector that will be divided by . @@ -1439,6 +1534,193 @@ public static bool GreaterThanOrEqualAny(Vector64 left, Vector64 right) return false; } + internal static Vector64 Hypot(Vector64 x, Vector64 y) + where T : IRootFunctions + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = T.Hypot(x.GetElementUnsafe(index), y.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// Computes the hypotenuse given two vectors representing the lengths of the shorter sides in a right-angled triangle. + /// The vector to square and add to . + /// The vector to square and add to . + /// The square root of -squared plus -squared. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 Hypot(Vector64 x, Vector64 y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotDouble, Vector64>(x, y); + } + else + { + return Hypot(x, y); + } + } + + /// Computes the hypotenuse given two vectors representing the lengths of the shorter sides in a right-angled triangle. + /// The vector to square and add to . + /// The vector to square and add to . + /// The square root of -squared plus -squared. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 Hypot(Vector64 x, Vector64 y) + { + if (IsHardwareAccelerated) + { + return VectorMath.HypotSingle, Vector64>(x, y); + } + else + { + return Hypot(x, y); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsNaN(Vector64 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return ~Equals(vector, vector); + } + return Vector64.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsNegative(Vector64 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector64.Zero; + } + else if (typeof(T) == typeof(float)) + { + return LessThan(vector.AsInt32(), Vector64.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(vector.AsInt64(), Vector64.Zero).As(); + } + else + { + return LessThan(vector, Vector64.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsPositive(Vector64 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return Vector64.AllBitsSet; + } + else if (typeof(T) == typeof(float)) + { + return GreaterThanOrEqual(vector.AsInt32(), Vector64.Zero).As(); + } + else if (typeof(T) == typeof(double)) + { + return GreaterThanOrEqual(vector.AsInt64(), Vector64.Zero).As(); + } + else + { + return GreaterThanOrEqual(vector, Vector64.Zero); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsPositiveInfinity(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.PositiveInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.PositiveInfinity).As()); + } + return Vector64.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsZero(Vector64 vector) => Equals(vector, Vector64.Zero); + + internal static Vector64 Lerp(Vector64 x, Vector64 y, Vector64 amount) + where T : IFloatingPointIeee754 + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = T.Lerp(x.GetElementUnsafe(index), y.GetElementUnsafe(index), amount.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// Performs a linear interpolation between two vectors based on the given weighting. + /// The first vector. + /// The second vector. + /// A value between 0 and 1 that indicates the weight of . + /// The interpolated vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 Lerp(Vector64 x, Vector64 y, Vector64 amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, double>(x, y, amount); + } + else + { + return Lerp(x, y, amount); + } + } + + /// Performs a linear interpolation between two vectors based on the given weighting. + /// The first vector. + /// The second vector. + /// A value between 0 and 1 that indicates the weight of . + /// The interpolated vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 Lerp(Vector64 x, Vector64 y, Vector64 amount) + { + if (IsHardwareAccelerated) + { + return VectorMath.Lerp, float>(x, y, amount); + } + else + { + return Lerp(x, y, amount); + } + } + /// Compares two vectors to determine which is less on a per-element basis. /// The type of the elements in the vector. /// The vector to compare with . @@ -1728,46 +2010,234 @@ public static Vector64 Log2(Vector64 vector) } } - /// Computes the maximum of two vectors on a per-element basis. - /// The type of the elements in the vector. - /// The vector to compare with . - /// The vector to compare with . - /// A vector whose elements are the maximum of the corresponding elements in and . - /// The type of and () is not supported. + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector64 Max(Vector64 left, Vector64 right) { - Unsafe.SkipInit(out Vector64 result); + if (IsHardwareAccelerated) + { + return VectorMath.Max, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector64 result); - for (int index = 0; index < Vector64.Count; index++) + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.Max(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MaxMagnitude(Vector64 left, Vector64 right) + { + if (IsHardwareAccelerated) { - T value = Scalar.GreaterThan(left.GetElementUnsafe(index), right.GetElementUnsafe(index)) ? left.GetElementUnsafe(index) : right.GetElementUnsafe(index); - result.SetElementUnsafe(index, value); + return VectorMath.MaxMagnitude, T>(left, right); } + else + { + Unsafe.SkipInit(out Vector64 result); - return result; + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.MaxMagnitude(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } } - /// Computes the minimum of two vectors on a per-element basis. - /// The type of the elements in the vector. - /// The vector to compare with . - /// The vector to compare with . - /// A vector whose elements are the minimum of the corresponding elements in and . - /// The type of and () is not supported. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MaxMagnitudeNumber(Vector64 left, Vector64 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxMagnitudeNumber, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.MaxMagnitudeNumber(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MaxNative(Vector64 left, Vector64 right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(GreaterThan(left, right), left, right); + } + else + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.GreaterThan(left.GetElementUnsafe(index), right.GetElementUnsafe(index)) ? left.GetElementUnsafe(index) : right.GetElementUnsafe(index); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MaxNumber(Vector64 left, Vector64 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MaxNumber, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.MaxNumber(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector64 Min(Vector64 left, Vector64 right) { - Unsafe.SkipInit(out Vector64 result); + if (IsHardwareAccelerated) + { + return VectorMath.Min, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector64 result); - for (int index = 0; index < Vector64.Count; index++) + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.Min(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MinMagnitude(Vector64 left, Vector64 right) + { + if (IsHardwareAccelerated) { - T value = Scalar.LessThan(left.GetElementUnsafe(index), right.GetElementUnsafe(index)) ? left.GetElementUnsafe(index) : right.GetElementUnsafe(index); - result.SetElementUnsafe(index, value); + return VectorMath.MinMagnitude, T>(left, right); } + else + { + Unsafe.SkipInit(out Vector64 result); - return result; + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.MinMagnitude(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MinMagnitudeNumber(Vector64 left, Vector64 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinMagnitudeNumber, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.MinMagnitudeNumber(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MinNative(Vector64 left, Vector64 right) + { + if (IsHardwareAccelerated) + { + return ConditionalSelect(LessThan(left, right), left, right); + } + else + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.LessThan(left.GetElementUnsafe(index), right.GetElementUnsafe(index)) ? left.GetElementUnsafe(index) : right.GetElementUnsafe(index); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MinNumber(Vector64 left, Vector64 right) + { + if (IsHardwareAccelerated) + { + return VectorMath.MinNumber, T>(left, right); + } + else + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.MinNumber(left.GetElementUnsafe(index), right.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } } /// Multiplies two vectors to compute their element-wise product. @@ -1797,6 +2267,21 @@ public static Vector64 Min(Vector64 left, Vector64 right) [Intrinsic] public static Vector64 Multiply(T left, Vector64 right) => right * left; + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector64 MultiplyAddEstimate(Vector64 left, Vector64 right, Vector64 addend) + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.MultiplyAddEstimate(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + /// Computes an estimate of ( * ) + . /// The vector to be multiplied with . /// The vector to be multiplied with . @@ -2040,6 +2525,107 @@ public static unsafe Vector64 Narrow(Vector64 lower, Vector64 OnesComplement(Vector64 vector) => ~vector; + internal static Vector64 RadiansToDegrees(Vector64 radians) + where T : ITrigonometricFunctions + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = T.RadiansToDegrees(radians.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// Converts a given vector from radians to degrees. + /// The vector to convert to degrees. + /// The vector of converted to degrees. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 RadiansToDegrees(Vector64 radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, double>(radians); + } + else + { + return RadiansToDegrees(radians); + } + } + + /// Converts a given vector from radians to degrees. + /// The vector to convert to degrees. + /// The vector of converted to degrees. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 RadiansToDegrees(Vector64 radians) + { + if (IsHardwareAccelerated) + { + return VectorMath.RadiansToDegrees, float>(radians); + } + else + { + return RadiansToDegrees(radians); + } + } + + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector64 Round(Vector64 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.Round(vector.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + public static Vector64 Round(Vector64 vector) => Round(vector); + + /// + [Intrinsic] + public static Vector64 Round(Vector64 vector) => Round(vector); + + /// Rounds each element in a vector to the nearest integer using the specified rounding mode. + /// The vector to round. + /// The mode under which should be rounded. + /// The result of rounding each element in to the nearest integer using . + [Intrinsic] + public static Vector64 Round(Vector64 vector, MidpointRounding mode) => VectorMath.RoundDouble(vector, mode); + + /// Rounds each element in a vector to the nearest integer using the specified rounding mode. + /// The vector to round. + /// The mode under which should be rounded. + /// The result of rounding each element in to the nearest integer using . + [Intrinsic] + public static Vector64 Round(Vector64 vector, MidpointRounding mode) => VectorMath.RoundSingle(vector, mode); + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -2584,6 +3170,45 @@ public static unsafe Vector128 ToVector128Unsafe(this Vector64 vector) return result; } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector64 Truncate(Vector64 vector) + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + T value = Scalar.Truncate(vector.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + } + + /// + [Intrinsic] + public static Vector64 Truncate(Vector64 vector) => Truncate(vector); + + /// + [Intrinsic] + public static Vector64 Truncate(Vector64 vector) => Truncate(vector); + /// Tries to copy a to a given span. /// The type of the input vector. /// The vector to copy. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs index cca51261cf659..64fc7f07b7ffe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs @@ -536,9 +536,18 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static Vector64 ISimdVector, T>.Ceiling(Vector64 vector) => Vector64.Ceiling(vector); + /// + static Vector64 ISimdVector, T>.Clamp(Vector64 value, Vector64 min, Vector64 max) => Vector64.Clamp(value, min, max); + + /// + static Vector64 ISimdVector, T>.ClampNative(Vector64 value, Vector64 min, Vector64 max) => Vector64.ClampNative(value, min, max); + /// static Vector64 ISimdVector, T>.ConditionalSelect(Vector64 condition, Vector64 left, Vector64 right) => Vector64.ConditionalSelect(condition, left, right); + /// + static Vector64 ISimdVector, T>.CopySign(Vector64 value, Vector64 sign) => Vector64.CopySign(value, sign); + /// static void ISimdVector, T>.CopyTo(Vector64 vector, T[] destination) => vector.CopyTo(destination); @@ -646,21 +655,51 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static Vector64 ISimdVector, T>.Max(Vector64 left, Vector64 right) => Vector64.Max(left, right); + /// + static Vector64 ISimdVector, T>.MaxMagnitude(Vector64 left, Vector64 right) => Vector64.MaxMagnitude(left, right); + + /// + static Vector64 ISimdVector, T>.MaxMagnitudeNumber(Vector64 left, Vector64 right) => Vector64.MaxMagnitudeNumber(left, right); + + /// + static Vector64 ISimdVector, T>.MaxNative(Vector64 left, Vector64 right) => Vector64.MaxNative(left, right); + + /// + static Vector64 ISimdVector, T>.MaxNumber(Vector64 left, Vector64 right) => Vector64.MaxNumber(left, right); + /// static Vector64 ISimdVector, T>.Min(Vector64 left, Vector64 right) => Vector64.Min(left, right); + /// + static Vector64 ISimdVector, T>.MinMagnitude(Vector64 left, Vector64 right) => Vector64.MinMagnitude(left, right); + + /// + static Vector64 ISimdVector, T>.MinMagnitudeNumber(Vector64 left, Vector64 right) => Vector64.MinMagnitudeNumber(left, right); + + /// + static Vector64 ISimdVector, T>.MinNative(Vector64 left, Vector64 right) => Vector64.MinNative(left, right); + + /// + static Vector64 ISimdVector, T>.MinNumber(Vector64 left, Vector64 right) => Vector64.MinNumber(left, right); + /// static Vector64 ISimdVector, T>.Multiply(Vector64 left, Vector64 right) => left * right; /// static Vector64 ISimdVector, T>.Multiply(Vector64 left, T right) => left * right; + /// + static Vector64 ISimdVector, T>.MultiplyAddEstimate(Vector64 left, Vector64 right, Vector64 addend) => Vector64.MultiplyAddEstimate(left, right, addend); + /// static Vector64 ISimdVector, T>.Negate(Vector64 vector) => -vector; /// static Vector64 ISimdVector, T>.OnesComplement(Vector64 vector) => ~vector; + /// + static Vector64 ISimdVector, T>.Round(Vector64 vector) => Vector64.Round(vector); + /// static Vector64 ISimdVector, T>.ShiftLeft(Vector64 vector, int shiftCount) => vector << shiftCount; @@ -699,6 +738,9 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static T ISimdVector, T>.ToScalar(Vector64 vector) => vector.ToScalar(); + /// + static Vector64 ISimdVector, T>.Truncate(Vector64 vector) => Vector64.Truncate(vector); + /// static bool ISimdVector, T>.TryCopyTo(Vector64 vector, Span destination) => vector.TryCopyTo(destination); @@ -721,5 +763,15 @@ static int ISimdVector, T>.IndexOfLastMatch(Vector64 vector) uint mask = vector.ExtractMostSignificantBits(); return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) } + + static Vector64 ISimdVector, T>.IsNaN(Vector64 vector) => Vector64.IsNaN(vector); + + static Vector64 ISimdVector, T>.IsNegative(Vector64 vector) => Vector64.IsNegative(vector); + + static Vector64 ISimdVector, T>.IsPositive(Vector64 vector) => Vector64.IsPositive(vector); + + static Vector64 ISimdVector, T>.IsPositiveInfinity(Vector64 vector) => Vector64.IsPositiveInfinity(vector); + + static Vector64 ISimdVector, T>.IsZero(Vector64 vector) => Vector64.IsZero(vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/VectorMath.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/VectorMath.cs index 5b37fbfb3f85d..fbe07cc62a9af 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/VectorMath.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/VectorMath.cs @@ -2,12 +2,54 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Numerics; +using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; namespace System.Runtime.Intrinsics { - internal static class VectorMath + internal static unsafe class VectorMath { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector CopySign(TVector value, TVector sign) + where TVector : unmanaged, ISimdVector + { + Debug.Assert((typeof(T) != typeof(byte)) + && (typeof(T) != typeof(ushort)) + && (typeof(T) != typeof(uint)) + && (typeof(T) != typeof(ulong)) + && (typeof(T) != typeof(nuint))); + + if (typeof(T) == typeof(float)) + { + return TVector.ConditionalSelect(Create(-0.0f), sign, value); + } + else if (typeof(T) == typeof(double)) + { + return TVector.ConditionalSelect(Create(-0.0), sign, value); + } + else + { + // All values are two's complement and so `value ^ sign` will produce a positive + // number if the signs match and a negative number if the signs differ. When the + // signs differ we want to negate the value and otherwise take the value as is. + return TVector.ConditionalSelect(TVector.IsNegative(value ^ sign), -value, value); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector DegreesToRadians(TVector degrees) + where TVector : unmanaged, ISimdVector + where T : IFloatingPointIeee754 + { + // NOTE: Don't change the algorithm without consulting the DIM + // which elaborates on why this implementation was chosen + + return (degrees * TVector.Create(T.Pi)) / TVector.Create(T.CreateTruncating(180)); + } + public static TVectorDouble ExpDouble(TVectorDouble x) where TVectorDouble : unmanaged, ISimdVector where TVectorUInt64 : unmanaged, ISimdVector @@ -59,21 +101,19 @@ public static TVectorDouble ExpDouble(dn); @@ -83,18 +123,33 @@ public static TVectorDouble ExpDouble( @@ -243,6 +309,178 @@ public static TVectorSingle ExpSingle(TVectorDouble x, TVectorDouble y) + where TVectorDouble : unmanaged, ISimdVector + where TVectorUInt64 : unmanaged, ISimdVector + { + // This code is based on `hypot` from amd/aocl-libm-ose + // Copyright (C) 2008-2020 Advanced Micro Devices, Inc. All rights reserved. + // + // Licensed under the BSD 3-Clause "New" or "Revised" License + // See THIRD-PARTY-NOTICES.TXT for the full license text + + TVectorDouble ax = TVectorDouble.Abs(x); + TVectorDouble ay = TVectorDouble.Abs(y); + + TVectorDouble infinityMask = TVectorDouble.IsPositiveInfinity(ax) | TVectorDouble.IsPositiveInfinity(ay); + TVectorDouble nanMask = TVectorDouble.IsNaN(ax) | TVectorDouble.IsNaN(ay); + + TVectorUInt64 xBits = Unsafe.BitCast(ax); + TVectorUInt64 yBits = Unsafe.BitCast(ay); + + TVectorUInt64 shiftedExponentMask = TVectorUInt64.Create(double.ShiftedExponentMask); + TVectorUInt64 xExp = (xBits >> double.BiasedExponentShift) & shiftedExponentMask; + TVectorUInt64 yExp = (yBits >> double.BiasedExponentShift) & shiftedExponentMask; + + TVectorUInt64 expDiff = xExp - yExp; + + // Cover cases where x or y is insignifican compared to the other + TVectorDouble insignificanMask = Unsafe.BitCast( + TVectorUInt64.GreaterThanOrEqual(expDiff, TVectorUInt64.Create(double.SignificandLength + 1)) & + TVectorUInt64.LessThanOrEqual(expDiff, TVectorUInt64.Create(unchecked((ulong)(-double.SignificandLength - 1)))) + ); + TVectorDouble insignificantResult = ax + ay; + + // To prevent overflow, scale down by 2^+600 + TVectorUInt64 expBiasP500 = TVectorUInt64.Create(double.ExponentBias + 500); + TVectorUInt64 scaleDownMask = TVectorUInt64.GreaterThan(xExp, expBiasP500) | TVectorUInt64.GreaterThan(yExp, expBiasP500); + TVectorDouble expFix = TVectorDouble.ConditionalSelect(Unsafe.BitCast(scaleDownMask), TVectorDouble.Create(4.149515568880993E+180), TVectorDouble.One); + TVectorUInt64 bitsFix = scaleDownMask & TVectorUInt64.Create(0xDA80000000000000); + + // To prevent underflow, scale up by 2^-600, but only if we didn't scale down already + TVectorUInt64 expBiasM500 = TVectorUInt64.Create(double.ExponentBias - 500); + TVectorUInt64 scaleUpMask = TVectorUInt64.AndNot(TVectorUInt64.LessThan(xExp, expBiasM500) | TVectorUInt64.LessThan(yExp, expBiasM500), scaleDownMask); + expFix = TVectorDouble.ConditionalSelect(Unsafe.BitCast(scaleUpMask), TVectorDouble.Create(2.409919865102884E-181), expFix); + bitsFix = TVectorUInt64.ConditionalSelect(scaleUpMask, TVectorUInt64.Create(0x2580000000000000), bitsFix); + + xBits += bitsFix; + yBits += bitsFix; + + // For subnormal values when scaling up, do an additional fixing + // up changing the adjustment to scale up by 2^601 instead and then + // subtract a correction of 2^601 to account for the implicit bit. + + TVectorDouble subnormalFix = TVectorDouble.Create(9.232978617785736E-128); + TVectorUInt64 subnormalBitsFix = TVectorUInt64.Create(0x0010000000000000); + + TVectorUInt64 xSubnormalMask = TVectorUInt64.IsZero(xExp) & scaleUpMask; + xBits += subnormalBitsFix & xSubnormalMask; + ax = Unsafe.BitCast(xBits); + ax -= subnormalFix & Unsafe.BitCast(xSubnormalMask); + + TVectorUInt64 ySubnormalMask = TVectorUInt64.IsZero(yExp) & scaleUpMask; + yBits += subnormalBitsFix & ySubnormalMask; + ay = Unsafe.BitCast(yBits); + ay -= subnormalFix & Unsafe.BitCast(ySubnormalMask); + + xBits = Unsafe.BitCast(ax); + yBits = Unsafe.BitCast(ay); + + // Sort so ax is greater than ay + TVectorDouble lessThanMask = TVectorDouble.LessThan(ax, ay); + + TVectorDouble tmp = ax; + ax = TVectorDouble.ConditionalSelect(lessThanMask, ay, ax); + ay = TVectorDouble.ConditionalSelect(lessThanMask, tmp, ay); + + TVectorUInt64 tmpBits = xBits; + xBits = TVectorUInt64.ConditionalSelect(Unsafe.BitCast(lessThanMask), yBits, xBits); + yBits = TVectorUInt64.ConditionalSelect(Unsafe.BitCast(lessThanMask), tmpBits, yBits); + + Debug.Assert(TVectorDouble.GreaterThanOrEqualAll(ax, ay)); + + // Split ax and ay into a head and tail portion + + TVectorUInt64 headMask = TVectorUInt64.Create(0xFFFF_FFFF_F800_0000); + TVectorDouble xHead = Unsafe.BitCast(xBits & headMask); + TVectorDouble yHead = Unsafe.BitCast(yBits & headMask); + + TVectorDouble xTail = ax - xHead; + TVectorDouble yTail = ay - yHead; + + // Compute (x * x) + (y * y) with extra precision + // + // This includes taking into account expFix which may + // cause an underflow or overflow, but if it does that + // will still be the correct result. + + TVectorDouble xx = ax * ax; + TVectorDouble yy = ay * ay; + + TVectorDouble rHead = xx + yy; + TVectorDouble rTail = (xx - rHead) + yy; + + rTail += TVectorDouble.MultiplyAddEstimate(xHead, xHead, -xx); + rTail = TVectorDouble.MultiplyAddEstimate(xHead * 2, xTail, rTail); + rTail = TVectorDouble.MultiplyAddEstimate(xTail, xTail, rTail); + + // We only need to do extra accounting when ax and ay have equal exponents + TVectorDouble equalExponentsMask = Unsafe.BitCast(TVectorUInt64.IsZero(expDiff)); + + TVectorDouble rTailTmp = rTail; + + rTailTmp += TVectorDouble.MultiplyAddEstimate(yHead, yHead, -yy); + rTailTmp = TVectorDouble.MultiplyAddEstimate(yHead * 2, yTail, rTailTmp); + rTailTmp = TVectorDouble.MultiplyAddEstimate(yTail, yTail, rTailTmp); + + rTail = TVectorDouble.ConditionalSelect(equalExponentsMask, rTailTmp, rTail); + + TVectorDouble result = TVectorDouble.Sqrt(rHead + rTail) * expFix; + + // IEEE 754 requires that we return +Infinity + // if either input is Infinity, even if one of + // the inputs is NaN. Otherwise if either input + // is NaN, we return NaN + + result = TVectorDouble.ConditionalSelect(insignificanMask, insignificantResult, result); + result = TVectorDouble.ConditionalSelect(nanMask, TVectorDouble.Create(double.NaN), result); + result = TVectorDouble.ConditionalSelect(infinityMask, TVectorDouble.Create(double.PositiveInfinity), result); + + return result; + } + + public static TVectorSingle HypotSingle(TVectorSingle x, TVectorSingle y) + where TVectorSingle : unmanaged, ISimdVector + where TVectorDouble : unmanaged, ISimdVector + { + // This code is based on `hypotf` from amd/aocl-libm-ose + // Copyright (C) 2008-2020 Advanced Micro Devices, Inc. All rights reserved. + // + // Licensed under the BSD 3-Clause "New" or "Revised" License + // See THIRD-PARTY-NOTICES.TXT for the full license text + + TVectorSingle ax = TVectorSingle.Abs(x); + TVectorSingle ay = TVectorSingle.Abs(y); + + TVectorSingle infinityMask = TVectorSingle.IsPositiveInfinity(ax) | TVectorSingle.IsPositiveInfinity(ay); + TVectorSingle nanMask = TVectorSingle.IsNaN(ax) | TVectorSingle.IsNaN(ay); + + (TVectorDouble xxLower, TVectorDouble xxUpper) = Widen(ax); + (TVectorDouble yyLower, TVectorDouble yyUpper) = Widen(ay); + + TVectorSingle result = Narrow( + TVectorDouble.Sqrt(TVectorDouble.MultiplyAddEstimate(xxLower, xxLower, yyLower * yyLower)), + TVectorDouble.Sqrt(TVectorDouble.MultiplyAddEstimate(xxUpper, xxUpper, yyUpper * yyUpper)) + ); + + // IEEE 754 requires that we return +Infinity + // if either input is Infinity, even if one of + // the inputs is NaN. Otherwise if either input + // is NaN, we return NaN + + result = TVectorSingle.ConditionalSelect(nanMask, TVectorSingle.Create(float.NaN), result); + result = TVectorSingle.ConditionalSelect(infinityMask, TVectorSingle.Create(float.PositiveInfinity), result); + + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector Lerp(TVector x, TVector y, TVector amount) + where TVector : unmanaged, ISimdVector + { + return TVector.MultiplyAddEstimate(x, TVector.One - amount, y * amount); + } + public static TVectorDouble LogDouble(TVectorDouble x) where TVectorDouble : unmanaged, ISimdVector where TVectorInt64 : unmanaged, ISimdVector @@ -310,19 +548,17 @@ public static TVectorDouble LogDouble(x); - - // (x < 0) ? float.NaN : x - TVectorDouble lessThanZeroMask = Unsafe.BitCast(TVectorInt64.LessThan(xBits, TVectorInt64.Zero)); + // double.IsNegative(x) ? double.NaN : x + TVectorDouble isNegativeMask = TVectorDouble.IsNegative(x); specialResult = TVectorDouble.ConditionalSelect( - lessThanZeroMask, + isNegativeMask, TVectorDouble.Create(double.NaN), specialResult ); // double.IsZero(x) ? double.NegativeInfinity : x - TVectorDouble zeroMask = Unsafe.BitCast(TVectorInt64.Equals(xBits << 1, TVectorInt64.Zero)); + TVectorDouble zeroMask = TVectorDouble.IsZero(x); specialResult = TVectorDouble.ConditionalSelect( zeroMask, @@ -330,10 +566,11 @@ public static TVectorDouble LogDouble(TVectorInt64.GreaterThanOrEqual(xBits, TVectorInt64.Create((long)double.PositiveInfinityBits))); + | isNegativeMask + | TVectorDouble.IsNaN(x) + | TVectorDouble.IsPositiveInfinity(x); // subnormal TVectorDouble subnormalMask = TVectorDouble.AndNot(Unsafe.BitCast(specialMask), temp); @@ -364,21 +601,50 @@ public static TVectorDouble LogDouble(specialMask), specialResult, - (n * LN2_HEAD) + ((n * LN2_TAIL) + poly) + TVectorDouble.MultiplyAddEstimate( + n, + TVectorDouble.Create(LN2_HEAD), + TVectorDouble.MultiplyAddEstimate(n, TVectorDouble.Create(LN2_TAIL), poly) + ) ); } @@ -446,16 +712,14 @@ public static TVectorSingle LogSingle(specialMask), temp); @@ -512,16 +776,30 @@ public static TVectorSingle LogSingle(specialMask), specialResult, - n * TVectorSingle.Create(V_LN2) + q + TVectorSingle.MultiplyAddEstimate(n, TVectorSingle.Create(V_LN2), q) ); } @@ -590,19 +868,17 @@ public static TVectorDouble Log2Double(x); - - // (x < 0) ? float.NaN : x - TVectorDouble lessThanZeroMask = Unsafe.BitCast(TVectorInt64.LessThan(xBits, TVectorInt64.Zero)); + // double.IsNegative(x) ? double.NaN : x + TVectorDouble isNegativeMask = TVectorDouble.IsNegative(x); specialResult = TVectorDouble.ConditionalSelect( - lessThanZeroMask, + isNegativeMask, TVectorDouble.Create(double.NaN), specialResult ); // double.IsZero(x) ? double.NegativeInfinity : x - TVectorDouble zeroMask = Unsafe.BitCast(TVectorInt64.Equals(xBits << 1, TVectorInt64.Zero)); + TVectorDouble zeroMask = TVectorDouble.IsZero(x); specialResult = TVectorDouble.ConditionalSelect( zeroMask, @@ -610,10 +886,11 @@ public static TVectorDouble Log2Double(TVectorInt64.GreaterThanOrEqual(xBits, TVectorInt64.Create((long)double.PositiveInfinityBits))); + | isNegativeMask + | TVectorDouble.IsNaN(x) + | TVectorDouble.IsPositiveInfinity(x); // subnormal TVectorDouble subnormalMask = TVectorDouble.AndNot(Unsafe.BitCast(specialMask), temp); @@ -644,21 +921,50 @@ public static TVectorDouble Log2Double(specialMask), specialResult, - (poly * LN2_HEAD) + ((poly * LN2_TAIL) + n) + TVectorDouble.MultiplyAddEstimate( + poly, + TVectorDouble.Create(LN2_HEAD), + TVectorDouble.MultiplyAddEstimate(poly, TVectorDouble.Create(LN2_TAIL), n) + ) ); } @@ -739,19 +1045,17 @@ public static TVectorSingle Log2Single(x); - - // (x < 0) ? float.NaN : x - TVectorSingle lessThanZeroMask = Unsafe.BitCast(TVectorInt32.LessThan(xBits, TVectorInt32.Zero)); + // float.IsNegative(x) ? float.NaN : x + TVectorSingle isNegativeMask = TVectorSingle.IsNegative(x); specialResult = TVectorSingle.ConditionalSelect( - lessThanZeroMask, + isNegativeMask, TVectorSingle.Create(float.NaN), specialResult ); // float.IsZero(x) ? float.NegativeInfinity : x - TVectorSingle zeroMask = Unsafe.BitCast(TVectorInt32.Equals(xBits << 1, TVectorInt32.Zero)); + TVectorSingle zeroMask = TVectorSingle.IsZero(x); specialResult = TVectorSingle.ConditionalSelect( zeroMask, @@ -759,10 +1063,11 @@ public static TVectorSingle Log2Single(TVectorInt32.GreaterThanOrEqual(xBits, TVectorInt32.Create((int)float.PositiveInfinityBits))); + | isNegativeMask + | TVectorSingle.IsNaN(x) + | TVectorSingle.IsPositiveInfinity(x); // subnormal TVectorSingle subnormalMask = TVectorSingle.AndNot(Unsafe.BitCast(specialMask), temp); @@ -792,11 +1097,22 @@ public static TVectorSingle Log2Single(specialMask), @@ -805,6 +1121,281 @@ public static TVectorSingle Log2Single(TVector x, TVector y) + where TVector : unmanaged, ISimdVector + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return TVector.ConditionalSelect( + TVector.LessThan(y, x) | TVector.IsNaN(x) | (TVector.Equals(x, y) & TVector.IsNegative(y)), + x, + y + ); + } + return TVector.ConditionalSelect(TVector.GreaterThan(x, y), x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector MaxMagnitude(TVector x, TVector y) + where TVector : unmanaged, ISimdVector + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + TVector xMag = TVector.Abs(x); + TVector yMag = TVector.Abs(y); + return TVector.ConditionalSelect( + TVector.GreaterThan(xMag, yMag) | TVector.IsNaN(xMag) | (TVector.Equals(xMag, yMag) & TVector.IsPositive(x)), + x, + y + ); + } + return MaxMagnitudeNumber(x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector MaxMagnitudeNumber(TVector x, TVector y) + where TVector : unmanaged, ISimdVector + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return TVector.Max(x, y); + } + + TVector xMag = TVector.Abs(x); + TVector yMag = TVector.Abs(y); + + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return TVector.ConditionalSelect( + TVector.GreaterThan(xMag, yMag) | TVector.IsNaN(yMag) | (TVector.Equals(xMag, yMag) & TVector.IsPositive(x)), + x, + y + ); + } + + Debug.Assert((typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint))); + + return TVector.ConditionalSelect( + (TVector.GreaterThan(xMag, yMag) & TVector.IsPositive(yMag)) | (TVector.Equals(xMag, yMag) & TVector.IsNegative(y)) | TVector.IsNegative(xMag), + x, + y + ); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector MaxNumber(TVector x, TVector y) + where TVector : unmanaged, ISimdVector + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return TVector.ConditionalSelect( + TVector.LessThan(y, x) | TVector.IsNaN(y) | (TVector.Equals(x, y) & TVector.IsNegative(y)), + x, + y + ); + } + + return TVector.Max(x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector Min(TVector x, TVector y) + where TVector : unmanaged, ISimdVector + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return TVector.ConditionalSelect( + TVector.LessThan(x, y) | TVector.IsNaN(x) | (TVector.Equals(x, y) & TVector.IsNegative(x)), + x, + y + ); + } + return TVector.ConditionalSelect(TVector.LessThan(x, y), x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector MinMagnitude(TVector x, TVector y) + where TVector : unmanaged, ISimdVector + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + TVector xMag = TVector.Abs(x); + TVector yMag = TVector.Abs(y); + + return TVector.ConditionalSelect( + TVector.LessThan(xMag, yMag) | TVector.IsNaN(xMag) | (TVector.Equals(xMag, yMag) & TVector.IsNegative(x)), + x, + y + ); + } + return MinMagnitudeNumber(x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector MinMagnitudeNumber(TVector x, TVector y) + where TVector : unmanaged, ISimdVector + { + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return TVector.Min(x, y); + } + + TVector xMag = TVector.Abs(x); + TVector yMag = TVector.Abs(y); + + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return TVector.ConditionalSelect( + TVector.LessThan(xMag, yMag) | TVector.IsNaN(yMag) | (TVector.Equals(xMag, yMag) & TVector.IsNegative(x)), + x, + y + ); + } + + Debug.Assert((typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint))); + + return TVector.ConditionalSelect( + (TVector.LessThan(xMag, yMag) & TVector.IsPositive(xMag)) | (TVector.Equals(xMag, yMag) & TVector.IsNegative(x)) | TVector.IsNegative(yMag), + x, + y + ); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector MinNumber(TVector x, TVector y) + where TVector : unmanaged, ISimdVector + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return TVector.ConditionalSelect( + TVector.LessThan(x, y) | TVector.IsNaN(y) | (TVector.Equals(x, y) & TVector.IsNegative(x)), + x, + y + ); + } + return TVector.Min(x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVector RadiansToDegrees(TVector radians) + where TVector : unmanaged, ISimdVector + where T : IFloatingPointIeee754 + { + // NOTE: Don't change the algorithm without consulting the DIM + // which elaborates on why this implementation was chosen + + return (radians * TVector.Create(T.CreateTruncating(180))) / TVector.Create(T.Pi); + } + + public static TVectorDouble RoundDouble(TVectorDouble vector, MidpointRounding mode) + where TVectorDouble : unmanaged, ISimdVector + { + switch (mode) + { + // Rounds to the nearest value; if the number falls midway, + // it is rounded to the nearest value above (for positive numbers) or below (for negative numbers) + case MidpointRounding.AwayFromZero: + { + // manually fold BitDecrement(0.5) + return TVectorDouble.Truncate(vector + CopySign(TVectorDouble.Create(0.49999999999999994), vector)); + } + + // Rounds to the nearest value; if the number falls midway, + // it is rounded to the nearest value with an even least significant digit + case MidpointRounding.ToEven: + { + return TVectorDouble.Round(vector); + } + + // Directed rounding: Round to the nearest value, toward to zero + case MidpointRounding.ToZero: + { + return TVectorDouble.Truncate(vector); + } + + // Directed Rounding: Round down to the next value, toward negative infinity + case MidpointRounding.ToNegativeInfinity: + { + return TVectorDouble.Floor(vector); + } + + // Directed rounding: Round up to the next value, toward positive infinity + case MidpointRounding.ToPositiveInfinity: + { + return TVectorDouble.Ceiling(vector); + } + + default: + { + ThrowHelper.ThrowArgumentException_InvalidEnumValue(mode); + return default; + } + } + } + + public static TVectorSingle RoundSingle(TVectorSingle vector, MidpointRounding mode) + where TVectorSingle : unmanaged, ISimdVector + { + switch (mode) + { + // Rounds to the nearest value; if the number falls midway, + // it is rounded to the nearest value above (for positive numbers) or below (for negative numbers) + case MidpointRounding.AwayFromZero: + { + // manually fold BitDecrement(0.5) + return TVectorSingle.Truncate(vector + CopySign(TVectorSingle.Create(0.49999997f), vector)); + } + + // Rounds to the nearest value; if the number falls midway, + // it is rounded to the nearest value with an even least significant digit + case MidpointRounding.ToEven: + { + return TVectorSingle.Round(vector); + } + + // Directed rounding: Round to the nearest value, toward to zero + case MidpointRounding.ToZero: + { + return TVectorSingle.Truncate(vector); + } + + // Directed Rounding: Round down to the next value, toward negative infinity + case MidpointRounding.ToNegativeInfinity: + { + return TVectorSingle.Floor(vector); + } + + // Directed rounding: Round up to the next value, toward positive infinity + case MidpointRounding.ToPositiveInfinity: + { + return TVectorSingle.Ceiling(vector); + } + + default: + { + ThrowHelper.ThrowArgumentException_InvalidEnumValue(mode); + return default; + } + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static TVectorDouble ConvertToDouble(TVectorInt64 vector) where TVectorDouble : unmanaged, ISimdVector @@ -812,7 +1403,11 @@ private static TVectorDouble ConvertToDouble(TVecto { Unsafe.SkipInit(out TVectorDouble result); - if (typeof(TVectorInt64) == typeof(Vector64)) + if (typeof(TVectorInt64) == typeof(Vector)) + { + result = (TVectorDouble)(object)Vector.ConvertToDouble((Vector)(object)vector); + } + else if (typeof(TVectorInt64) == typeof(Vector64)) { result = (TVectorDouble)(object)Vector64.ConvertToDouble((Vector64)(object)vector); } @@ -843,7 +1438,11 @@ private static TVectorSingle ConvertToSingle(TVecto { Unsafe.SkipInit(out TVectorSingle result); - if (typeof(TVectorInt32) == typeof(Vector64)) + if (typeof(TVectorInt32) == typeof(Vector)) + { + result = (TVectorSingle)(object)Vector.ConvertToSingle((Vector)(object)vector); + } + else if (typeof(TVectorInt32) == typeof(Vector64)) { result = (TVectorSingle)(object)Vector64.ConvertToSingle((Vector64)(object)vector); } @@ -867,6 +1466,74 @@ private static TVectorSingle ConvertToSingle(TVecto return result; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static TVector Create(double value) + where TVector : unmanaged, ISimdVector + { + Unsafe.SkipInit(out TVector result); + + if (typeof(TVector) == typeof(Vector)) + { + result = (TVector)(object)Vector.Create(value); + } + else if (typeof(TVector) == typeof(Vector64)) + { + result = (TVector)(object)Vector64.Create(value); + } + else if (typeof(TVector) == typeof(Vector128)) + { + result = (TVector)(object)Vector128.Create(value); + } + else if (typeof(TVector) == typeof(Vector256)) + { + result = (TVector)(object)Vector256.Create(value); + } + else if (typeof(TVector) == typeof(Vector512)) + { + result = (TVector)(object)Vector512.Create(value); + } + else + { + ThrowHelper.ThrowNotSupportedException(); + } + + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static TVector Create(float value) + where TVector : unmanaged, ISimdVector + { + Unsafe.SkipInit(out TVector result); + + if (typeof(TVector) == typeof(Vector)) + { + result = (TVector)(object)Vector.Create(value); + } + else if (typeof(TVector) == typeof(Vector64)) + { + result = (TVector)(object)Vector64.Create(value); + } + else if (typeof(TVector) == typeof(Vector128)) + { + result = (TVector)(object)Vector128.Create(value); + } + else if (typeof(TVector) == typeof(Vector256)) + { + result = (TVector)(object)Vector256.Create(value); + } + else if (typeof(TVector) == typeof(Vector512)) + { + result = (TVector)(object)Vector512.Create(value); + } + else + { + ThrowHelper.ThrowNotSupportedException(); + } + + return result; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static TVectorSingle Narrow(TVectorDouble lower, TVectorDouble upper) where TVectorDouble : unmanaged, ISimdVector @@ -874,7 +1541,12 @@ private static TVectorSingle Narrow(TVectorDouble { Unsafe.SkipInit(out TVectorSingle result); - if (typeof(TVectorDouble) == typeof(Vector64)) + if (typeof(TVectorDouble) == typeof(Vector)) + { + Debug.Assert(typeof(TVectorSingle) == typeof(Vector)); + result = (TVectorSingle)(object)Vector.Narrow((Vector)(object)lower, (Vector)(object)upper); + } + else if (typeof(TVectorDouble) == typeof(Vector64)) { Debug.Assert(typeof(TVectorSingle) == typeof(Vector64)); result = (TVectorSingle)(object)Vector64.Narrow((Vector64)(object)lower, (Vector64)(object)upper); @@ -909,7 +1581,12 @@ private static (TVectorDouble Lower, TVectorDouble Upper) Widen)) + if (typeof(TVectorSingle) == typeof(Vector)) + { + Debug.Assert(typeof(TVectorDouble) == typeof(Vector)); + result = ((TVectorDouble, TVectorDouble))(object)Vector.Widen((Vector)(object)vector); + } + else if (typeof(TVectorSingle) == typeof(Vector64)) { Debug.Assert(typeof(TVectorDouble) == typeof(Vector64)); result = ((TVectorDouble, TVectorDouble))(object)Vector64.Widen((Vector64)(object)vector); diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index 7ee394a0d8f4c..92cc094044018 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -857,7 +857,7 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinatio public static int ILogB(float x) => MathF.ILogB(x); /// - public static float Lerp(float value1, float value2, float amount) => (value1 * (1.0f - amount)) + (value2 * amount); + public static float Lerp(float value1, float value2, float amount) => MultiplyAddEstimate(value1, 1.0f - amount, value2 * amount); /// [Intrinsic] 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 3df9a05b405ba..dcb46c9d28e95 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -46,6 +46,8 @@ public static partial class Vector128 public static System.Runtime.Intrinsics.Vector128 BitwiseOr(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Ceiling(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Ceiling(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Clamp(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 min, System.Runtime.Intrinsics.Vector128 max) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ClampNative(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 min, System.Runtime.Intrinsics.Vector128 max) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConditionalSelect(System.Runtime.Intrinsics.Vector128 condition, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToDouble(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] @@ -65,6 +67,7 @@ public static partial class Vector128 public static System.Runtime.Intrinsics.Vector128 ConvertToUInt64(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 CopySign(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 sign) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination, int startIndex) { } @@ -159,6 +162,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static System.Runtime.Intrinsics.Vector128 Create(T value) { throw null; } public static System.Runtime.Intrinsics.Vector128 Create(T[] values) { throw null; } public static System.Runtime.Intrinsics.Vector128 Create(T[] values, int index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DegreesToRadians(System.Runtime.Intrinsics.Vector128 degrees) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DegreesToRadians(System.Runtime.Intrinsics.Vector128 degrees) { throw null; } public static System.Runtime.Intrinsics.Vector128 Divide(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Divide(System.Runtime.Intrinsics.Vector128 left, T right) { throw null; } public static T Dot(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } @@ -182,6 +187,15 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static bool GreaterThanOrEqualAny(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 GreaterThanOrEqual(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 GreaterThan(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Hypot(System.Runtime.Intrinsics.Vector128 x, System.Runtime.Intrinsics.Vector128 y) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Hypot(System.Runtime.Intrinsics.Vector128 x, System.Runtime.Intrinsics.Vector128 y) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsNaN(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsNegative(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsPositive(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsPositiveInfinity(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsZero(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Lerp(System.Runtime.Intrinsics.Vector128 x, System.Runtime.Intrinsics.Vector128 y, System.Runtime.Intrinsics.Vector128 amount) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Lerp(System.Runtime.Intrinsics.Vector128 x, System.Runtime.Intrinsics.Vector128 y, System.Runtime.Intrinsics.Vector128 amount) { throw null; } public static bool LessThanAll(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static bool LessThanAny(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static bool LessThanOrEqualAll(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } @@ -204,7 +218,15 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static System.Runtime.Intrinsics.Vector128 Log2(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Log2(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Max(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MaxMagnitude(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MaxMagnitudeNumber(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MaxNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MaxNumber(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Min(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MinMagnitude(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MinMagnitudeNumber(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MinNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MinNumber(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Multiply(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Multiply(System.Runtime.Intrinsics.Vector128 left, T right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Multiply(T left, System.Runtime.Intrinsics.Vector128 right) { throw null; } @@ -223,6 +245,12 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) { throw null; } public static System.Runtime.Intrinsics.Vector128 Negate(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 OnesComplement(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 RadiansToDegrees(System.Runtime.Intrinsics.Vector128 radians) { throw null; } + public static System.Runtime.Intrinsics.Vector128 RadiansToDegrees(System.Runtime.Intrinsics.Vector128 radians) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Round(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Round(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Round(System.Runtime.Intrinsics.Vector128 vector, System.MidpointRounding mode) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Round(System.Runtime.Intrinsics.Vector128 vector, System.MidpointRounding mode) { throw null; } public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) { throw null; } public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) { throw null; } public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) { throw null; } @@ -290,6 +318,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static T ToScalar(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ToVector256Unsafe(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ToVector256(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Truncate(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 Truncate(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static bool TryCopyTo(this System.Runtime.Intrinsics.Vector128 vector, System.Span destination) { throw null; } [System.CLSCompliantAttribute(false)] public static (System.Runtime.Intrinsics.Vector128 Lower, System.Runtime.Intrinsics.Vector128 Upper) Widen(System.Runtime.Intrinsics.Vector128 source) { throw null; } @@ -392,6 +422,8 @@ public static partial class Vector256 public static System.Runtime.Intrinsics.Vector256 BitwiseOr(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 Ceiling(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Ceiling(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Clamp(System.Runtime.Intrinsics.Vector256 value, System.Runtime.Intrinsics.Vector256 min, System.Runtime.Intrinsics.Vector256 max) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ClampNative(System.Runtime.Intrinsics.Vector256 value, System.Runtime.Intrinsics.Vector256 min, System.Runtime.Intrinsics.Vector256 max) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConditionalSelect(System.Runtime.Intrinsics.Vector256 condition, System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToDouble(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] @@ -411,6 +443,7 @@ public static partial class Vector256 public static System.Runtime.Intrinsics.Vector256 ConvertToUInt64(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 CopySign(System.Runtime.Intrinsics.Vector256 value, System.Runtime.Intrinsics.Vector256 sign) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination, int startIndex) { } @@ -506,6 +539,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static System.Runtime.Intrinsics.Vector256 Create(T value) { throw null; } public static System.Runtime.Intrinsics.Vector256 Create(T[] values) { throw null; } public static System.Runtime.Intrinsics.Vector256 Create(T[] values, int index) { throw null; } + public static System.Runtime.Intrinsics.Vector256 DegreesToRadians(System.Runtime.Intrinsics.Vector256 degrees) { throw null; } + public static System.Runtime.Intrinsics.Vector256 DegreesToRadians(System.Runtime.Intrinsics.Vector256 degrees) { throw null; } public static System.Runtime.Intrinsics.Vector256 Divide(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 Divide(System.Runtime.Intrinsics.Vector256 left, T right) { throw null; } public static T Dot(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } @@ -529,6 +564,15 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static bool GreaterThanOrEqualAny(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 GreaterThanOrEqual(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 GreaterThan(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Hypot(System.Runtime.Intrinsics.Vector256 x, System.Runtime.Intrinsics.Vector256 y) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Hypot(System.Runtime.Intrinsics.Vector256 x, System.Runtime.Intrinsics.Vector256 y) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsNaN(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsNegative(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsPositive(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsPositiveInfinity(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsZero(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Lerp(System.Runtime.Intrinsics.Vector256 x, System.Runtime.Intrinsics.Vector256 y, System.Runtime.Intrinsics.Vector256 amount) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Lerp(System.Runtime.Intrinsics.Vector256 x, System.Runtime.Intrinsics.Vector256 y, System.Runtime.Intrinsics.Vector256 amount) { throw null; } public static bool LessThanAll(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static bool LessThanAny(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static bool LessThanOrEqualAll(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } @@ -551,7 +595,15 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static System.Runtime.Intrinsics.Vector256 Log2(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Log2(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Max(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MaxMagnitude(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MaxMagnitudeNumber(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MaxNative(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MaxNumber(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 Min(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MinMagnitude(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MinMagnitudeNumber(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MinNative(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MinNumber(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 Multiply(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 Multiply(System.Runtime.Intrinsics.Vector256 left, T right) { throw null; } public static System.Runtime.Intrinsics.Vector256 Multiply(T left, System.Runtime.Intrinsics.Vector256 right) { throw null; } @@ -570,6 +622,12 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) { throw null; } public static System.Runtime.Intrinsics.Vector256 Negate(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 OnesComplement(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 RadiansToDegrees(System.Runtime.Intrinsics.Vector256 radians) { throw null; } + public static System.Runtime.Intrinsics.Vector256 RadiansToDegrees(System.Runtime.Intrinsics.Vector256 radians) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Round(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Round(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Round(System.Runtime.Intrinsics.Vector256 vector, System.MidpointRounding mode) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Round(System.Runtime.Intrinsics.Vector256 vector, System.MidpointRounding mode) { throw null; } public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) { throw null; } public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) { throw null; } public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) { throw null; } @@ -637,6 +695,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static T ToScalar(this System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ToVector512Unsafe(this System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ToVector512(this System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Truncate(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 Truncate(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static bool TryCopyTo(this System.Runtime.Intrinsics.Vector256 vector, System.Span destination) { throw null; } [System.CLSCompliantAttribute(false)] public static (System.Runtime.Intrinsics.Vector256 Lower, System.Runtime.Intrinsics.Vector256 Upper) Widen(System.Runtime.Intrinsics.Vector256 source) { throw null; } @@ -739,6 +799,8 @@ public static partial class Vector512 public static System.Runtime.Intrinsics.Vector512 BitwiseOr(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 Ceiling(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Ceiling(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Clamp(System.Runtime.Intrinsics.Vector512 value, System.Runtime.Intrinsics.Vector512 min, System.Runtime.Intrinsics.Vector512 max) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ClampNative(System.Runtime.Intrinsics.Vector512 value, System.Runtime.Intrinsics.Vector512 min, System.Runtime.Intrinsics.Vector512 max) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConditionalSelect(System.Runtime.Intrinsics.Vector512 condition, System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToDouble(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] @@ -758,6 +820,7 @@ public static partial class Vector512 public static System.Runtime.Intrinsics.Vector512 ConvertToUInt64(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 CopySign(System.Runtime.Intrinsics.Vector512 value, System.Runtime.Intrinsics.Vector512 sign) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, T[] destination, int startIndex) { } @@ -854,6 +917,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static System.Runtime.Intrinsics.Vector512 Create(T value) { throw null; } public static System.Runtime.Intrinsics.Vector512 Create(T[] values) { throw null; } public static System.Runtime.Intrinsics.Vector512 Create(T[] values, int index) { throw null; } + public static System.Runtime.Intrinsics.Vector512 DegreesToRadians(System.Runtime.Intrinsics.Vector512 degrees) { throw null; } + public static System.Runtime.Intrinsics.Vector512 DegreesToRadians(System.Runtime.Intrinsics.Vector512 degrees) { throw null; } public static System.Runtime.Intrinsics.Vector512 Divide(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 Divide(System.Runtime.Intrinsics.Vector512 left, T right) { throw null; } public static T Dot(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } @@ -877,6 +942,15 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static bool GreaterThanOrEqualAny(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 GreaterThanOrEqual(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 GreaterThan(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Hypot(System.Runtime.Intrinsics.Vector512 x, System.Runtime.Intrinsics.Vector512 y) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Hypot(System.Runtime.Intrinsics.Vector512 x, System.Runtime.Intrinsics.Vector512 y) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsNaN(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsNegative(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsPositive(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsPositiveInfinity(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsZero(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Lerp(System.Runtime.Intrinsics.Vector512 x, System.Runtime.Intrinsics.Vector512 y, System.Runtime.Intrinsics.Vector512 amount) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Lerp(System.Runtime.Intrinsics.Vector512 x, System.Runtime.Intrinsics.Vector512 y, System.Runtime.Intrinsics.Vector512 amount) { throw null; } public static bool LessThanAll(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static bool LessThanAny(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static bool LessThanOrEqualAll(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } @@ -899,7 +973,15 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static System.Runtime.Intrinsics.Vector512 Log2(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Log2(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Max(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MaxMagnitude(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MaxMagnitudeNumber(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MaxNative(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MaxNumber(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 Min(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MinMagnitude(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MinMagnitudeNumber(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MinNative(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MinNumber(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 Multiply(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 Multiply(System.Runtime.Intrinsics.Vector512 left, T right) { throw null; } public static System.Runtime.Intrinsics.Vector512 Multiply(T left, System.Runtime.Intrinsics.Vector512 right) { throw null; } @@ -918,6 +1000,12 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static System.Runtime.Intrinsics.Vector512 Narrow(System.Runtime.Intrinsics.Vector512 lower, System.Runtime.Intrinsics.Vector512 upper) { throw null; } public static System.Runtime.Intrinsics.Vector512 Negate(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 OnesComplement(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 RadiansToDegrees(System.Runtime.Intrinsics.Vector512 radians) { throw null; } + public static System.Runtime.Intrinsics.Vector512 RadiansToDegrees(System.Runtime.Intrinsics.Vector512 radians) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Round(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Round(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Round(System.Runtime.Intrinsics.Vector512 vector, System.MidpointRounding mode) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Round(System.Runtime.Intrinsics.Vector512 vector, System.MidpointRounding mode) { throw null; } public static System.Runtime.Intrinsics.Vector512 ShiftLeft(System.Runtime.Intrinsics.Vector512 vector, int shiftCount) { throw null; } public static System.Runtime.Intrinsics.Vector512 ShiftLeft(System.Runtime.Intrinsics.Vector512 vector, int shiftCount) { throw null; } public static System.Runtime.Intrinsics.Vector512 ShiftLeft(System.Runtime.Intrinsics.Vector512 vector, int shiftCount) { throw null; } @@ -983,6 +1071,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static System.Runtime.Intrinsics.Vector512 Subtract(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static T Sum(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static T ToScalar(this System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Truncate(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 Truncate(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static bool TryCopyTo(this System.Runtime.Intrinsics.Vector512 vector, System.Span destination) { throw null; } [System.CLSCompliantAttribute(false)] public static (System.Runtime.Intrinsics.Vector512 Lower, System.Runtime.Intrinsics.Vector512 Upper) Widen(System.Runtime.Intrinsics.Vector512 source) { throw null; } @@ -1083,6 +1173,8 @@ public static partial class Vector64 public static System.Runtime.Intrinsics.Vector64 BitwiseOr(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Ceiling(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Ceiling(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Clamp(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 min, System.Runtime.Intrinsics.Vector64 max) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ClampNative(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 min, System.Runtime.Intrinsics.Vector64 max) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConditionalSelect(System.Runtime.Intrinsics.Vector64 condition, System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToDouble(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] @@ -1102,6 +1194,7 @@ public static partial class Vector64 public static System.Runtime.Intrinsics.Vector64 ConvertToUInt64(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 CopySign(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 sign) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination, int startIndex) { } @@ -1173,6 +1266,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, public static System.Runtime.Intrinsics.Vector64 Create(T value) { throw null; } public static System.Runtime.Intrinsics.Vector64 Create(T[] values) { throw null; } public static System.Runtime.Intrinsics.Vector64 Create(T[] values, int index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DegreesToRadians(System.Runtime.Intrinsics.Vector64 degrees) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DegreesToRadians(System.Runtime.Intrinsics.Vector64 degrees) { throw null; } public static System.Runtime.Intrinsics.Vector64 Divide(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Divide(System.Runtime.Intrinsics.Vector64 left, T right) { throw null; } public static T Dot(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } @@ -1194,6 +1289,15 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, public static bool GreaterThanOrEqualAny(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 GreaterThanOrEqual(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 GreaterThan(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Hypot(System.Runtime.Intrinsics.Vector64 x, System.Runtime.Intrinsics.Vector64 y) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Hypot(System.Runtime.Intrinsics.Vector64 x, System.Runtime.Intrinsics.Vector64 y) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsNaN(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsNegative(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsPositive(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsPositiveInfinity(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsZero(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Lerp(System.Runtime.Intrinsics.Vector64 x, System.Runtime.Intrinsics.Vector64 y, System.Runtime.Intrinsics.Vector64 amount) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Lerp(System.Runtime.Intrinsics.Vector64 x, System.Runtime.Intrinsics.Vector64 y, System.Runtime.Intrinsics.Vector64 amount) { throw null; } public static bool LessThanAll(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static bool LessThanAny(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static bool LessThanOrEqualAll(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } @@ -1216,7 +1320,15 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, public static System.Runtime.Intrinsics.Vector64 Log2(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Log2(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Max(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MaxMagnitude(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MaxMagnitudeNumber(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MaxNative(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MaxNumber(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Min(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MinMagnitude(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MinMagnitudeNumber(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MinNative(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MinNumber(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Multiply(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Multiply(System.Runtime.Intrinsics.Vector64 left, T right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Multiply(T left, System.Runtime.Intrinsics.Vector64 right) { throw null; } @@ -1235,6 +1347,12 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) { throw null; } public static System.Runtime.Intrinsics.Vector64 Negate(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 OnesComplement(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 RadiansToDegrees(System.Runtime.Intrinsics.Vector64 radians) { throw null; } + public static System.Runtime.Intrinsics.Vector64 RadiansToDegrees(System.Runtime.Intrinsics.Vector64 radians) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Round(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Round(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Round(System.Runtime.Intrinsics.Vector64 vector, System.MidpointRounding mode) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Round(System.Runtime.Intrinsics.Vector64 vector, System.MidpointRounding mode) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) { throw null; } @@ -1298,6 +1416,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, public static T ToScalar(this System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ToVector128Unsafe(this System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ToVector128(this System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Truncate(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 Truncate(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static bool TryCopyTo(this System.Runtime.Intrinsics.Vector64 vector, System.Span destination) { throw null; } [System.CLSCompliantAttribute(false)] public static (System.Runtime.Intrinsics.Vector64 Lower, System.Runtime.Intrinsics.Vector64 Upper) Widen(System.Runtime.Intrinsics.Vector64 source) { throw null; } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj index b8fc0641259d4..e956491c0a63b 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj +++ b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs index 0ae183839c611..5c32e8b991e7e 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs @@ -5,7 +5,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.X86; +using System.Tests; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -4825,7 +4825,7 @@ private static void TestCreateSequence(T start, T step) } [Theory] - [MemberData(nameof(VectorTestMemberData.ExpDouble), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.ExpDouble), MemberType = typeof(GenericMathTestMemberData))] public void ExpDoubleTest(double value, double expectedResult, double variance) { Vector128 actualResult = Vector128.Exp(Vector128.Create(value)); @@ -4833,7 +4833,7 @@ public void ExpDoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.ExpSingle), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.ExpSingle), MemberType = typeof(GenericMathTestMemberData))] public void ExpSingleTest(float value, float expectedResult, float variance) { Vector128 actualResult = Vector128.Exp(Vector128.Create(value)); @@ -4841,7 +4841,7 @@ public void ExpSingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.LogDouble), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.LogDouble), MemberType = typeof(GenericMathTestMemberData))] public void LogDoubleTest(double value, double expectedResult, double variance) { Vector128 actualResult = Vector128.Log(Vector128.Create(value)); @@ -4849,7 +4849,7 @@ public void LogDoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.LogSingle), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.LogSingle), MemberType = typeof(GenericMathTestMemberData))] public void LogSingleTest(float value, float expectedResult, float variance) { Vector128 actualResult = Vector128.Log(Vector128.Create(value)); @@ -4857,7 +4857,7 @@ public void LogSingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.Log2Double), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.Log2Double), MemberType = typeof(GenericMathTestMemberData))] public void Log2DoubleTest(double value, double expectedResult, double variance) { Vector128 actualResult = Vector128.Log2(Vector128.Create(value)); @@ -4865,7 +4865,7 @@ public void Log2DoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.Log2Single), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] public void Log2SingleTest(float value, float expectedResult, float variance) { Vector128 actualResult = Vector128.Log2(Vector128.Create(value)); @@ -4873,35 +4873,19 @@ public void Log2SingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddDouble), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend, double expectedResult) { - Vector128 actualResult = Vector128.FusedMultiplyAdd(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)); - AssertEqual(Vector128.Create(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector128.Zero); + AssertEqual(Vector128.Create(expectedResult), Vector128.FusedMultiplyAdd(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)), Vector128.Zero); + AssertEqual(Vector128.Create(double.MultiplyAddEstimate(left, right, addend)), Vector128.MultiplyAddEstimate(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)), Vector128.Zero); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddSingle), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend, float expectedResult) { - Vector128 actualResult = Vector128.FusedMultiplyAdd(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)); - AssertEqual(Vector128.Create(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector128.Zero); - } - - [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) - { - Vector128 actualResult = Vector128.MultiplyAddEstimate(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)); - AssertEqual(Vector128.Create(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector128.Zero); - } - - [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateSingleTest(float left, float right, float addend) - { - Vector128 actualResult = Vector128.MultiplyAddEstimate(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)); - AssertEqual(Vector128.Create(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector128.Zero); + AssertEqual(Vector128.Create(expectedResult), Vector128.FusedMultiplyAdd(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)), Vector128.Zero); + AssertEqual(Vector128.Create(float.MultiplyAddEstimate(left, right, addend)), Vector128.MultiplyAddEstimate(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)), Vector128.Zero); } [Fact] @@ -4985,5 +4969,380 @@ public void ConvertToUInt64NativeTest() Assert.Equal(Vector128.Create(double.ConvertToIntegerNative(2.6)), Vector128.ConvertToUInt64Native(Vector128.Create(2.6))); Assert.Equal(Vector128.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector128.ConvertToUInt64Native(Vector128.Create(double.MaxValue))); } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampDouble), MemberType = typeof(GenericMathTestMemberData))] + public void ClampDoubleTest(double x, double min, double max, double expectedResult) + { + Vector128 actualResult = Vector128.Clamp(Vector128.Create(x), Vector128.Create(min), Vector128.Create(max)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ClampSingleTest(float x, float min, float max, float expectedResult) + { + Vector128 actualResult = Vector128.Clamp(Vector128.Create(x), Vector128.Create(min), Vector128.Create(max)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignDouble), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignDoubleTest(double x, double y, double expectedResult) + { + Vector128 actualResult = Vector128.CopySign(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignSingle), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignSingleTest(float x, float y, float expectedResult) + { + Vector128 actualResult = Vector128.CopySign(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansDouble), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansDoubleTest(double value, double expectedResult, double variance) + { + Vector128 actualResult1 = Vector128.DegreesToRadians(Vector128.Create(-value)); + AssertEqual(Vector128.Create(-expectedResult), actualResult1, Vector128.Create(variance)); + + Vector128 actualResult2 = Vector128.DegreesToRadians(Vector128.Create(+value)); + AssertEqual(Vector128.Create(+expectedResult), actualResult2, Vector128.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansSingle), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector128.Create(-expectedResult), Vector128.DegreesToRadians(Vector128.Create(-value)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(+expectedResult), Vector128.DegreesToRadians(Vector128.Create(+value)), Vector128.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotDouble), MemberType = typeof(GenericMathTestMemberData))] + public void HypotDoubleTest(double x, double y, double expectedResult, double variance) + { + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(-x), Vector128.Create(-y)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(-x), Vector128.Create(+y)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(+x), Vector128.Create(-y)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(+x), Vector128.Create(+y)), Vector128.Create(variance)); + + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(-y), Vector128.Create(-x)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(-y), Vector128.Create(+x)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(+y), Vector128.Create(-x)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(+y), Vector128.Create(+x)), Vector128.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotSingle), MemberType = typeof(GenericMathTestMemberData))] + public void HypotSingleTest(float x, float y, float expectedResult, float variance) + { + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(-x), Vector128.Create(-y)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(-x), Vector128.Create(+y)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(+x), Vector128.Create(-y)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(+x), Vector128.Create(+y)), Vector128.Create(variance)); + + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(-y), Vector128.Create(-x)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(-y), Vector128.Create(+x)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(+y), Vector128.Create(-x)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(+y), Vector128.Create(+x)), Vector128.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNaN(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNaN(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNegative(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNegative(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositive(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositive(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositiveInfinity(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositiveInfinity(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsZero(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsZero(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] + public void LerpDoubleTest(double x, double y, double amount, double expectedResult) + { + AssertEqual(Vector128.Create(+expectedResult), Vector128.Lerp(Vector128.Create(+x), Vector128.Create(+y), Vector128.Create(amount)), Vector128.Zero); + AssertEqual(Vector128.Create((expectedResult == 0.0) ? expectedResult : -expectedResult), Vector128.Lerp(Vector128.Create(-x), Vector128.Create(-y), Vector128.Create(amount)), Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LerpSingleTest(float x, float y, float amount, float expectedResult) + { + AssertEqual(Vector128.Create(+expectedResult), Vector128.Lerp(Vector128.Create(+x), Vector128.Create(+y), Vector128.Create(amount)), Vector128.Zero); + AssertEqual(Vector128.Create((expectedResult == 0.0f) ? expectedResult : -expectedResult), Vector128.Lerp(Vector128.Create(-x), Vector128.Create(-y), Vector128.Create(amount)), Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxDoubleTest(double x, double y, double expectedResult) + { + Vector128 actualResult = Vector128.Max(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxSingleTest(float x, float y, float expectedResult) + { + Vector128 actualResult = Vector128.Max(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector128 actualResult = Vector128.MaxMagnitude(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector128 actualResult = Vector128.MaxMagnitude(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector128 actualResult = Vector128.MaxMagnitudeNumber(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector128 actualResult = Vector128.MaxMagnitudeNumber(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberDoubleTest(double x, double y, double expectedResult) + { + Vector128 actualResult = Vector128.MaxNumber(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberSingleTest(float x, float y, float expectedResult) + { + Vector128 actualResult = Vector128.MaxNumber(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinDoubleTest(double x, double y, double expectedResult) + { + Vector128 actualResult = Vector128.Min(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinSingleTest(float x, float y, float expectedResult) + { + Vector128 actualResult = Vector128.Min(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector128 actualResult = Vector128.MinMagnitude(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector128 actualResult = Vector128.MinMagnitude(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector128 actualResult = Vector128.MinMagnitudeNumber(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector128 actualResult = Vector128.MinMagnitudeNumber(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberDoubleTest(double x, double y, double expectedResult) + { + Vector128 actualResult = Vector128.MinNumber(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberSingleTest(float x, float y, float expectedResult) + { + Vector128 actualResult = Vector128.MinNumber(Vector128.Create(x), Vector128.Create(y)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesDoubleTest(double value, double expectedResult, double variance) + { + AssertEqual(Vector128.Create(-expectedResult), Vector128.RadiansToDegrees(Vector128.Create(-value)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(+expectedResult), Vector128.RadiansToDegrees(Vector128.Create(+value)), Vector128.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector128.Create(-expectedResult), Vector128.RadiansToDegrees(Vector128.Create(-value)), Vector128.Create(variance)); + AssertEqual(Vector128.Create(+expectedResult), Vector128.RadiansToDegrees(Vector128.Create(+value)), Vector128.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundDoubleTest(double value, double expectedResult) + { + Vector128 actualResult = Vector128.Round(Vector128.Create(value)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundSingleTest(float value, float expectedResult) + { + Vector128 actualResult = Vector128.Round(Vector128.Create(value)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroDoubleTest(double value, double expectedResult) + { + Vector128 actualResult = Vector128.Round(Vector128.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroSingleTest(float value, float expectedResult) + { + Vector128 actualResult = Vector128.Round(Vector128.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenDoubleTest(double value, double expectedResult) + { + Vector128 actualResult = Vector128.Round(Vector128.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenSingleTest(float value, float expectedResult) + { + Vector128 actualResult = Vector128.Round(Vector128.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateDouble), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateDoubleTest(double value, double expectedResult) + { + Vector128 actualResult = Vector128.Truncate(Vector128.Create(value)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateSingle), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateSingleTest(float value, float expectedResult) + { + Vector128 actualResult = Vector128.Truncate(Vector128.Create(value)); + AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs index 8fc41fc97f631..0c5cd3bdb2e82 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.Intrinsics.X86; +using System.Tests; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -5840,7 +5841,7 @@ private static void TestCreateSequence(T start, T step) } [Theory] - [MemberData(nameof(VectorTestMemberData.ExpDouble), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.ExpDouble), MemberType = typeof(GenericMathTestMemberData))] public void ExpDoubleTest(double value, double expectedResult, double variance) { Vector256 actualResult = Vector256.Exp(Vector256.Create(value)); @@ -5848,7 +5849,7 @@ public void ExpDoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.ExpSingle), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.ExpSingle), MemberType = typeof(GenericMathTestMemberData))] public void ExpSingleTest(float value, float expectedResult, float variance) { Vector256 actualResult = Vector256.Exp(Vector256.Create(value)); @@ -5856,7 +5857,7 @@ public void ExpSingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.LogDouble), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.LogDouble), MemberType = typeof(GenericMathTestMemberData))] public void LogDoubleTest(double value, double expectedResult, double variance) { Vector256 actualResult = Vector256.Log(Vector256.Create(value)); @@ -5864,7 +5865,7 @@ public void LogDoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.LogSingle), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.LogSingle), MemberType = typeof(GenericMathTestMemberData))] public void LogSingleTest(float value, float expectedResult, float variance) { Vector256 actualResult = Vector256.Log(Vector256.Create(value)); @@ -5872,7 +5873,7 @@ public void LogSingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.Log2Double), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.Log2Double), MemberType = typeof(GenericMathTestMemberData))] public void Log2DoubleTest(double value, double expectedResult, double variance) { Vector256 actualResult = Vector256.Log2(Vector256.Create(value)); @@ -5880,7 +5881,7 @@ public void Log2DoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.Log2Single), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] public void Log2SingleTest(float value, float expectedResult, float variance) { Vector256 actualResult = Vector256.Log2(Vector256.Create(value)); @@ -5888,35 +5889,19 @@ public void Log2SingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddDouble), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend, double expectedResult) { - Vector256 actualResult = Vector256.FusedMultiplyAdd(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)); - AssertEqual(Vector256.Create(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector256.Zero); + AssertEqual(Vector256.Create(expectedResult), Vector256.FusedMultiplyAdd(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)), Vector256.Zero); + AssertEqual(Vector256.Create(double.MultiplyAddEstimate(left, right, addend)), Vector256.MultiplyAddEstimate(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)), Vector256.Zero); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddSingle), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend, float expectedResult) { - Vector256 actualResult = Vector256.FusedMultiplyAdd(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)); - AssertEqual(Vector256.Create(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector256.Zero); - } - - [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) - { - Vector256 actualResult = Vector256.MultiplyAddEstimate(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)); - AssertEqual(Vector256.Create(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector256.Zero); - } - - [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateSingleTest(float left, float right, float addend) - { - Vector256 actualResult = Vector256.MultiplyAddEstimate(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)); - AssertEqual(Vector256.Create(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector256.Zero); + AssertEqual(Vector256.Create(expectedResult), Vector256.FusedMultiplyAdd(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)), Vector256.Zero); + AssertEqual(Vector256.Create(float.MultiplyAddEstimate(left, right, addend)), Vector256.MultiplyAddEstimate(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)), Vector256.Zero); } [Fact] @@ -6000,5 +5985,380 @@ public void ConvertToUInt64NativeTest() Assert.Equal(Vector256.Create(double.ConvertToIntegerNative(2.6)), Vector256.ConvertToUInt64Native(Vector256.Create(2.6))); Assert.Equal(Vector256.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector256.ConvertToUInt64Native(Vector256.Create(double.MaxValue))); } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampDouble), MemberType = typeof(GenericMathTestMemberData))] + public void ClampDoubleTest(double x, double min, double max, double expectedResult) + { + Vector256 actualResult = Vector256.Clamp(Vector256.Create(x), Vector256.Create(min), Vector256.Create(max)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ClampSingleTest(float x, float min, float max, float expectedResult) + { + Vector256 actualResult = Vector256.Clamp(Vector256.Create(x), Vector256.Create(min), Vector256.Create(max)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignDouble), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignDoubleTest(double x, double y, double expectedResult) + { + Vector256 actualResult = Vector256.CopySign(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignSingle), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignSingleTest(float x, float y, float expectedResult) + { + Vector256 actualResult = Vector256.CopySign(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansDouble), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansDoubleTest(double value, double expectedResult, double variance) + { + Vector256 actualResult1 = Vector256.DegreesToRadians(Vector256.Create(-value)); + AssertEqual(Vector256.Create(-expectedResult), actualResult1, Vector256.Create(variance)); + + Vector256 actualResult2 = Vector256.DegreesToRadians(Vector256.Create(+value)); + AssertEqual(Vector256.Create(+expectedResult), actualResult2, Vector256.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansSingle), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector256.Create(-expectedResult), Vector256.DegreesToRadians(Vector256.Create(-value)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(+expectedResult), Vector256.DegreesToRadians(Vector256.Create(+value)), Vector256.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotDouble), MemberType = typeof(GenericMathTestMemberData))] + public void HypotDoubleTest(double x, double y, double expectedResult, double variance) + { + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(-x), Vector256.Create(-y)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(-x), Vector256.Create(+y)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(+x), Vector256.Create(-y)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(+x), Vector256.Create(+y)), Vector256.Create(variance)); + + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(-y), Vector256.Create(-x)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(-y), Vector256.Create(+x)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(+y), Vector256.Create(-x)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(+y), Vector256.Create(+x)), Vector256.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotSingle), MemberType = typeof(GenericMathTestMemberData))] + public void HypotSingleTest(float x, float y, float expectedResult, float variance) + { + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(-x), Vector256.Create(-y)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(-x), Vector256.Create(+y)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(+x), Vector256.Create(-y)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(+x), Vector256.Create(+y)), Vector256.Create(variance)); + + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(-y), Vector256.Create(-x)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(-y), Vector256.Create(+x)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(+y), Vector256.Create(-x)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(+y), Vector256.Create(+x)), Vector256.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNaN(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNaN(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNegative(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNegative(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositive(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositive(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositiveInfinity(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositiveInfinity(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsZero(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsZero(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] + public void LerpDoubleTest(double x, double y, double amount, double expectedResult) + { + AssertEqual(Vector256.Create(+expectedResult), Vector256.Lerp(Vector256.Create(+x), Vector256.Create(+y), Vector256.Create(amount)), Vector256.Zero); + AssertEqual(Vector256.Create((expectedResult == 0.0) ? expectedResult : -expectedResult), Vector256.Lerp(Vector256.Create(-x), Vector256.Create(-y), Vector256.Create(amount)), Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LerpSingleTest(float x, float y, float amount, float expectedResult) + { + AssertEqual(Vector256.Create(+expectedResult), Vector256.Lerp(Vector256.Create(+x), Vector256.Create(+y), Vector256.Create(amount)), Vector256.Zero); + AssertEqual(Vector256.Create((expectedResult == 0.0f) ? expectedResult : -expectedResult), Vector256.Lerp(Vector256.Create(-x), Vector256.Create(-y), Vector256.Create(amount)), Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxDoubleTest(double x, double y, double expectedResult) + { + Vector256 actualResult = Vector256.Max(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxSingleTest(float x, float y, float expectedResult) + { + Vector256 actualResult = Vector256.Max(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector256 actualResult = Vector256.MaxMagnitude(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector256 actualResult = Vector256.MaxMagnitude(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector256 actualResult = Vector256.MaxMagnitudeNumber(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector256 actualResult = Vector256.MaxMagnitudeNumber(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberDoubleTest(double x, double y, double expectedResult) + { + Vector256 actualResult = Vector256.MaxNumber(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberSingleTest(float x, float y, float expectedResult) + { + Vector256 actualResult = Vector256.MaxNumber(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinDoubleTest(double x, double y, double expectedResult) + { + Vector256 actualResult = Vector256.Min(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinSingleTest(float x, float y, float expectedResult) + { + Vector256 actualResult = Vector256.Min(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector256 actualResult = Vector256.MinMagnitude(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector256 actualResult = Vector256.MinMagnitude(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector256 actualResult = Vector256.MinMagnitudeNumber(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector256 actualResult = Vector256.MinMagnitudeNumber(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberDoubleTest(double x, double y, double expectedResult) + { + Vector256 actualResult = Vector256.MinNumber(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberSingleTest(float x, float y, float expectedResult) + { + Vector256 actualResult = Vector256.MinNumber(Vector256.Create(x), Vector256.Create(y)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesDoubleTest(double value, double expectedResult, double variance) + { + AssertEqual(Vector256.Create(-expectedResult), Vector256.RadiansToDegrees(Vector256.Create(-value)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(+expectedResult), Vector256.RadiansToDegrees(Vector256.Create(+value)), Vector256.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector256.Create(-expectedResult), Vector256.RadiansToDegrees(Vector256.Create(-value)), Vector256.Create(variance)); + AssertEqual(Vector256.Create(+expectedResult), Vector256.RadiansToDegrees(Vector256.Create(+value)), Vector256.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundDoubleTest(double value, double expectedResult) + { + Vector256 actualResult = Vector256.Round(Vector256.Create(value)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundSingleTest(float value, float expectedResult) + { + Vector256 actualResult = Vector256.Round(Vector256.Create(value)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroDoubleTest(double value, double expectedResult) + { + Vector256 actualResult = Vector256.Round(Vector256.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroSingleTest(float value, float expectedResult) + { + Vector256 actualResult = Vector256.Round(Vector256.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenDoubleTest(double value, double expectedResult) + { + Vector256 actualResult = Vector256.Round(Vector256.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenSingleTest(float value, float expectedResult) + { + Vector256 actualResult = Vector256.Round(Vector256.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateDouble), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateDoubleTest(double value, double expectedResult) + { + Vector256 actualResult = Vector256.Truncate(Vector256.Create(value)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateSingle), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateSingleTest(float value, float expectedResult) + { + Vector256 actualResult = Vector256.Truncate(Vector256.Create(value)); + AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs index ac18da95a6623..450abc7f32b86 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.Intrinsics.X86; +using System.Tests; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -5273,7 +5274,7 @@ private static void TestCreateSequence(T start, T step) } [Theory] - [MemberData(nameof(VectorTestMemberData.ExpDouble), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.ExpDouble), MemberType = typeof(GenericMathTestMemberData))] public void ExpDoubleTest(double value, double expectedResult, double variance) { Vector512 actualResult = Vector512.Exp(Vector512.Create(value)); @@ -5281,7 +5282,7 @@ public void ExpDoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.ExpSingle), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.ExpSingle), MemberType = typeof(GenericMathTestMemberData))] public void ExpSingleTest(float value, float expectedResult, float variance) { Vector512 actualResult = Vector512.Exp(Vector512.Create(value)); @@ -5289,7 +5290,7 @@ public void ExpSingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.LogDouble), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.LogDouble), MemberType = typeof(GenericMathTestMemberData))] public void LogDoubleTest(double value, double expectedResult, double variance) { Vector512 actualResult = Vector512.Log(Vector512.Create(value)); @@ -5297,7 +5298,7 @@ public void LogDoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.LogSingle), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.LogSingle), MemberType = typeof(GenericMathTestMemberData))] public void LogSingleTest(float value, float expectedResult, float variance) { Vector512 actualResult = Vector512.Log(Vector512.Create(value)); @@ -5305,7 +5306,7 @@ public void LogSingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.Log2Double), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.Log2Double), MemberType = typeof(GenericMathTestMemberData))] public void Log2DoubleTest(double value, double expectedResult, double variance) { Vector512 actualResult = Vector512.Log2(Vector512.Create(value)); @@ -5313,7 +5314,7 @@ public void Log2DoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.Log2Single), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] public void Log2SingleTest(float value, float expectedResult, float variance) { Vector512 actualResult = Vector512.Log2(Vector512.Create(value)); @@ -5321,35 +5322,19 @@ public void Log2SingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddDouble), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend, double expectedResult) { - Vector512 actualResult = Vector512.FusedMultiplyAdd(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)); - AssertEqual(Vector512.Create(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector512.Zero); + AssertEqual(Vector512.Create(expectedResult), Vector512.FusedMultiplyAdd(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)), Vector512.Zero); + AssertEqual(Vector512.Create(double.MultiplyAddEstimate(left, right, addend)), Vector512.MultiplyAddEstimate(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)), Vector512.Zero); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddSingle), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend, float expectedResult) { - Vector512 actualResult = Vector512.FusedMultiplyAdd(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)); - AssertEqual(Vector512.Create(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector512.Zero); - } - - [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) - { - Vector512 actualResult = Vector512.MultiplyAddEstimate(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)); - AssertEqual(Vector512.Create(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector512.Zero); - } - - [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateSingleTest(float left, float right, float addend) - { - Vector512 actualResult = Vector512.MultiplyAddEstimate(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)); - AssertEqual(Vector512.Create(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector512.Zero); + AssertEqual(Vector512.Create(expectedResult), Vector512.FusedMultiplyAdd(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)), Vector512.Zero); + AssertEqual(Vector512.Create(float.MultiplyAddEstimate(left, right, addend)), Vector512.MultiplyAddEstimate(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)), Vector512.Zero); } [Fact] @@ -5433,5 +5418,380 @@ public void ConvertToUInt64NativeTest() Assert.Equal(Vector512.Create(double.ConvertToIntegerNative(2.6)), Vector512.ConvertToUInt64Native(Vector512.Create(2.6))); Assert.Equal(Vector512.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector512.ConvertToUInt64Native(Vector512.Create(double.MaxValue))); } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampDouble), MemberType = typeof(GenericMathTestMemberData))] + public void ClampDoubleTest(double x, double min, double max, double expectedResult) + { + Vector512 actualResult = Vector512.Clamp(Vector512.Create(x), Vector512.Create(min), Vector512.Create(max)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ClampSingleTest(float x, float min, float max, float expectedResult) + { + Vector512 actualResult = Vector512.Clamp(Vector512.Create(x), Vector512.Create(min), Vector512.Create(max)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignDouble), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignDoubleTest(double x, double y, double expectedResult) + { + Vector512 actualResult = Vector512.CopySign(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignSingle), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignSingleTest(float x, float y, float expectedResult) + { + Vector512 actualResult = Vector512.CopySign(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansDouble), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansDoubleTest(double value, double expectedResult, double variance) + { + Vector512 actualResult1 = Vector512.DegreesToRadians(Vector512.Create(-value)); + AssertEqual(Vector512.Create(-expectedResult), actualResult1, Vector512.Create(variance)); + + Vector512 actualResult2 = Vector512.DegreesToRadians(Vector512.Create(+value)); + AssertEqual(Vector512.Create(+expectedResult), actualResult2, Vector512.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansSingle), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector512.Create(-expectedResult), Vector512.DegreesToRadians(Vector512.Create(-value)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(+expectedResult), Vector512.DegreesToRadians(Vector512.Create(+value)), Vector512.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotDouble), MemberType = typeof(GenericMathTestMemberData))] + public void HypotDoubleTest(double x, double y, double expectedResult, double variance) + { + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(-x), Vector512.Create(-y)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(-x), Vector512.Create(+y)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(+x), Vector512.Create(-y)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(+x), Vector512.Create(+y)), Vector512.Create(variance)); + + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(-y), Vector512.Create(-x)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(-y), Vector512.Create(+x)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(+y), Vector512.Create(-x)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(+y), Vector512.Create(+x)), Vector512.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotSingle), MemberType = typeof(GenericMathTestMemberData))] + public void HypotSingleTest(float x, float y, float expectedResult, float variance) + { + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(-x), Vector512.Create(-y)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(-x), Vector512.Create(+y)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(+x), Vector512.Create(-y)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(+x), Vector512.Create(+y)), Vector512.Create(variance)); + + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(-y), Vector512.Create(-x)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(-y), Vector512.Create(+x)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(+y), Vector512.Create(-x)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(+y), Vector512.Create(+x)), Vector512.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNaN(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNaN(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNegative(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNegative(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositive(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositive(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositiveInfinity(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositiveInfinity(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsZero(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsZero(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] + public void LerpDoubleTest(double x, double y, double amount, double expectedResult) + { + AssertEqual(Vector512.Create(+expectedResult), Vector512.Lerp(Vector512.Create(+x), Vector512.Create(+y), Vector512.Create(amount)), Vector512.Zero); + AssertEqual(Vector512.Create((expectedResult == 0.0) ? expectedResult : -expectedResult), Vector512.Lerp(Vector512.Create(-x), Vector512.Create(-y), Vector512.Create(amount)), Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LerpSingleTest(float x, float y, float amount, float expectedResult) + { + AssertEqual(Vector512.Create(+expectedResult), Vector512.Lerp(Vector512.Create(+x), Vector512.Create(+y), Vector512.Create(amount)), Vector512.Zero); + AssertEqual(Vector512.Create((expectedResult == 0.0f) ? expectedResult : -expectedResult), Vector512.Lerp(Vector512.Create(-x), Vector512.Create(-y), Vector512.Create(amount)), Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxDoubleTest(double x, double y, double expectedResult) + { + Vector512 actualResult = Vector512.Max(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxSingleTest(float x, float y, float expectedResult) + { + Vector512 actualResult = Vector512.Max(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector512 actualResult = Vector512.MaxMagnitude(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector512 actualResult = Vector512.MaxMagnitude(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector512 actualResult = Vector512.MaxMagnitudeNumber(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector512 actualResult = Vector512.MaxMagnitudeNumber(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberDoubleTest(double x, double y, double expectedResult) + { + Vector512 actualResult = Vector512.MaxNumber(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberSingleTest(float x, float y, float expectedResult) + { + Vector512 actualResult = Vector512.MaxNumber(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinDoubleTest(double x, double y, double expectedResult) + { + Vector512 actualResult = Vector512.Min(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinSingleTest(float x, float y, float expectedResult) + { + Vector512 actualResult = Vector512.Min(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector512 actualResult = Vector512.MinMagnitude(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector512 actualResult = Vector512.MinMagnitude(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector512 actualResult = Vector512.MinMagnitudeNumber(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector512 actualResult = Vector512.MinMagnitudeNumber(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberDoubleTest(double x, double y, double expectedResult) + { + Vector512 actualResult = Vector512.MinNumber(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberSingleTest(float x, float y, float expectedResult) + { + Vector512 actualResult = Vector512.MinNumber(Vector512.Create(x), Vector512.Create(y)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesDoubleTest(double value, double expectedResult, double variance) + { + AssertEqual(Vector512.Create(-expectedResult), Vector512.RadiansToDegrees(Vector512.Create(-value)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(+expectedResult), Vector512.RadiansToDegrees(Vector512.Create(+value)), Vector512.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector512.Create(-expectedResult), Vector512.RadiansToDegrees(Vector512.Create(-value)), Vector512.Create(variance)); + AssertEqual(Vector512.Create(+expectedResult), Vector512.RadiansToDegrees(Vector512.Create(+value)), Vector512.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundDoubleTest(double value, double expectedResult) + { + Vector512 actualResult = Vector512.Round(Vector512.Create(value)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundSingleTest(float value, float expectedResult) + { + Vector512 actualResult = Vector512.Round(Vector512.Create(value)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroDoubleTest(double value, double expectedResult) + { + Vector512 actualResult = Vector512.Round(Vector512.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroSingleTest(float value, float expectedResult) + { + Vector512 actualResult = Vector512.Round(Vector512.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenDoubleTest(double value, double expectedResult) + { + Vector512 actualResult = Vector512.Round(Vector512.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenSingleTest(float value, float expectedResult) + { + Vector512 actualResult = Vector512.Round(Vector512.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateDouble), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateDoubleTest(double value, double expectedResult) + { + Vector512 actualResult = Vector512.Truncate(Vector512.Create(value)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateSingle), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateSingleTest(float value, float expectedResult) + { + Vector512 actualResult = Vector512.Truncate(Vector512.Create(value)); + AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs index c42580263a038..ba7ee7c891787 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs @@ -4,7 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.X86; +using System.Tests; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -4242,7 +4242,7 @@ private static void TestCreateSequence(T start, T step) } [Theory] - [MemberData(nameof(VectorTestMemberData.ExpDouble), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.ExpDouble), MemberType = typeof(GenericMathTestMemberData))] public void ExpDoubleTest(double value, double expectedResult, double variance) { Vector64 actualResult = Vector64.Exp(Vector64.Create(value)); @@ -4250,7 +4250,7 @@ public void ExpDoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.ExpSingle), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.ExpSingle), MemberType = typeof(GenericMathTestMemberData))] public void ExpSingleTest(float value, float expectedResult, float variance) { Vector64 actualResult = Vector64.Exp(Vector64.Create(value)); @@ -4258,7 +4258,7 @@ public void ExpSingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.LogDouble), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.LogDouble), MemberType = typeof(GenericMathTestMemberData))] public void LogDoubleTest(double value, double expectedResult, double variance) { Vector64 actualResult = Vector64.Log(Vector64.Create(value)); @@ -4266,7 +4266,7 @@ public void LogDoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.LogSingle), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.LogSingle), MemberType = typeof(GenericMathTestMemberData))] public void LogSingleTest(float value, float expectedResult, float variance) { Vector64 actualResult = Vector64.Log(Vector64.Create(value)); @@ -4274,7 +4274,7 @@ public void LogSingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.Log2Double), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.Log2Double), MemberType = typeof(GenericMathTestMemberData))] public void Log2DoubleTest(double value, double expectedResult, double variance) { Vector64 actualResult = Vector64.Log2(Vector64.Create(value)); @@ -4282,7 +4282,7 @@ public void Log2DoubleTest(double value, double expectedResult, double variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.Log2Single), MemberType = typeof(VectorTestMemberData))] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] public void Log2SingleTest(float value, float expectedResult, float variance) { Vector64 actualResult = Vector64.Log2(Vector64.Create(value)); @@ -4290,35 +4290,19 @@ public void Log2SingleTest(float value, float expectedResult, float variance) } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddDouble), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend, double expectedResult) { - Vector64 actualResult = Vector64.FusedMultiplyAdd(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)); - AssertEqual(Vector64.Create(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector64.Zero); + AssertEqual(Vector64.Create(expectedResult), Vector64.FusedMultiplyAdd(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)), Vector64.Zero); + AssertEqual(Vector64.Create(double.MultiplyAddEstimate(left, right, addend)), Vector64.MultiplyAddEstimate(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)), Vector64.Zero); } [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void FusedMultiplyAddSingleTest(float left, float right, float addend) + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddSingle), MemberType = typeof(GenericMathTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend, float expectedResult) { - Vector64 actualResult = Vector64.FusedMultiplyAdd(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)); - AssertEqual(Vector64.Create(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector64.Zero); - } - - [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) - { - Vector64 actualResult = Vector64.MultiplyAddEstimate(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)); - AssertEqual(Vector64.Create(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector64.Zero); - } - - [Theory] - [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] - public void MultiplyAddEstimateSingleTest(float left, float right, float addend) - { - Vector64 actualResult = Vector64.MultiplyAddEstimate(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)); - AssertEqual(Vector64.Create(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector64.Zero); + AssertEqual(Vector64.Create(expectedResult), Vector64.FusedMultiplyAdd(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)), Vector64.Zero); + AssertEqual(Vector64.Create(float.MultiplyAddEstimate(left, right, addend)), Vector64.MultiplyAddEstimate(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)), Vector64.Zero); } [Fact] @@ -4392,5 +4376,380 @@ public void ConvertToUInt64NativeTest() Assert.Equal(Vector64.Create(double.ConvertToIntegerNative(2.6)), Vector64.ConvertToUInt64Native(Vector64.Create(2.6))); Assert.Equal(Vector64.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector64.ConvertToUInt64Native(Vector64.Create(double.MaxValue))); } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampDouble), MemberType = typeof(GenericMathTestMemberData))] + public void ClampDoubleTest(double x, double min, double max, double expectedResult) + { + Vector64 actualResult = Vector64.Clamp(Vector64.Create(x), Vector64.Create(min), Vector64.Create(max)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] + public void ClampSingleTest(float x, float min, float max, float expectedResult) + { + Vector64 actualResult = Vector64.Clamp(Vector64.Create(x), Vector64.Create(min), Vector64.Create(max)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignDouble), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignDoubleTest(double x, double y, double expectedResult) + { + Vector64 actualResult = Vector64.CopySign(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.CopySignSingle), MemberType = typeof(GenericMathTestMemberData))] + public void CopySignSingleTest(float x, float y, float expectedResult) + { + Vector64 actualResult = Vector64.CopySign(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansDouble), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansDoubleTest(double value, double expectedResult, double variance) + { + Vector64 actualResult1 = Vector64.DegreesToRadians(Vector64.Create(-value)); + AssertEqual(Vector64.Create(-expectedResult), actualResult1, Vector64.Create(variance)); + + Vector64 actualResult2 = Vector64.DegreesToRadians(Vector64.Create(+value)); + AssertEqual(Vector64.Create(+expectedResult), actualResult2, Vector64.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansSingle), MemberType = typeof(GenericMathTestMemberData))] + public void DegreesToRadiansSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector64.Create(-expectedResult), Vector64.DegreesToRadians(Vector64.Create(-value)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(+expectedResult), Vector64.DegreesToRadians(Vector64.Create(+value)), Vector64.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotDouble), MemberType = typeof(GenericMathTestMemberData))] + public void HypotDoubleTest(double x, double y, double expectedResult, double variance) + { + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(-x), Vector64.Create(-y)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(-x), Vector64.Create(+y)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(+x), Vector64.Create(-y)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(+x), Vector64.Create(+y)), Vector64.Create(variance)); + + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(-y), Vector64.Create(-x)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(-y), Vector64.Create(+x)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(+y), Vector64.Create(-x)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(+y), Vector64.Create(+x)), Vector64.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.HypotSingle), MemberType = typeof(GenericMathTestMemberData))] + public void HypotSingleTest(float x, float y, float expectedResult, float variance) + { + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(-x), Vector64.Create(-y)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(-x), Vector64.Create(+y)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(+x), Vector64.Create(-y)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(+x), Vector64.Create(+y)), Vector64.Create(variance)); + + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(-y), Vector64.Create(-x)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(-y), Vector64.Create(+x)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(+y), Vector64.Create(-x)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(+y), Vector64.Create(+x)), Vector64.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNaN(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNaN(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNegative(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNegative(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositive(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositive(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositiveInfinity(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositiveInfinity(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsZero(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsZero(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] + public void LerpDoubleTest(double x, double y, double amount, double expectedResult) + { + AssertEqual(Vector64.Create(+expectedResult), Vector64.Lerp(Vector64.Create(+x), Vector64.Create(+y), Vector64.Create(amount)), Vector64.Zero); + AssertEqual(Vector64.Create((expectedResult == 0.0) ? expectedResult : -expectedResult), Vector64.Lerp(Vector64.Create(-x), Vector64.Create(-y), Vector64.Create(amount)), Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.LerpSingle), MemberType = typeof(GenericMathTestMemberData))] + public void LerpSingleTest(float x, float y, float amount, float expectedResult) + { + AssertEqual(Vector64.Create(+expectedResult), Vector64.Lerp(Vector64.Create(+x), Vector64.Create(+y), Vector64.Create(amount)), Vector64.Zero); + AssertEqual(Vector64.Create((expectedResult == 0.0f) ? expectedResult : -expectedResult), Vector64.Lerp(Vector64.Create(-x), Vector64.Create(-y), Vector64.Create(amount)), Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxDoubleTest(double x, double y, double expectedResult) + { + Vector64 actualResult = Vector64.Max(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxSingleTest(float x, float y, float expectedResult) + { + Vector64 actualResult = Vector64.Max(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector64 actualResult = Vector64.MaxMagnitude(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector64 actualResult = Vector64.MaxMagnitude(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector64 actualResult = Vector64.MaxMagnitudeNumber(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector64 actualResult = Vector64.MaxMagnitudeNumber(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberDoubleTest(double x, double y, double expectedResult) + { + Vector64 actualResult = Vector64.MaxNumber(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MaxNumberSingleTest(float x, float y, float expectedResult) + { + Vector64 actualResult = Vector64.MaxNumber(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinDoubleTest(double x, double y, double expectedResult) + { + Vector64 actualResult = Vector64.Min(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinSingleTest(float x, float y, float expectedResult) + { + Vector64 actualResult = Vector64.Min(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeDoubleTest(double x, double y, double expectedResult) + { + Vector64 actualResult = Vector64.MinMagnitude(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeSingleTest(float x, float y, float expectedResult) + { + Vector64 actualResult = Vector64.MinMagnitude(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberDoubleTest(double x, double y, double expectedResult) + { + Vector64 actualResult = Vector64.MinMagnitudeNumber(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinMagnitudeNumberSingleTest(float x, float y, float expectedResult) + { + Vector64 actualResult = Vector64.MinMagnitudeNumber(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberDoubleTest(double x, double y, double expectedResult) + { + Vector64 actualResult = Vector64.MinNumber(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public void MinNumberSingleTest(float x, float y, float expectedResult) + { + Vector64 actualResult = Vector64.MinNumber(Vector64.Create(x), Vector64.Create(y)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesDoubleTest(double value, double expectedResult, double variance) + { + AssertEqual(Vector64.Create(-expectedResult), Vector64.RadiansToDegrees(Vector64.Create(-value)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(+expectedResult), Vector64.RadiansToDegrees(Vector64.Create(+value)), Vector64.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RadiansToDegreesSingleTest(float value, float expectedResult, float variance) + { + AssertEqual(Vector64.Create(-expectedResult), Vector64.RadiansToDegrees(Vector64.Create(-value)), Vector64.Create(variance)); + AssertEqual(Vector64.Create(+expectedResult), Vector64.RadiansToDegrees(Vector64.Create(+value)), Vector64.Create(variance)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundDoubleTest(double value, double expectedResult) + { + Vector64 actualResult = Vector64.Round(Vector64.Create(value)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundSingleTest(float value, float expectedResult) + { + Vector64 actualResult = Vector64.Round(Vector64.Create(value)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroDoubleTest(double value, double expectedResult) + { + Vector64 actualResult = Vector64.Round(Vector64.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundAwayFromZeroSingleTest(float value, float expectedResult) + { + Vector64 actualResult = Vector64.Round(Vector64.Create(value), MidpointRounding.AwayFromZero); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenDouble), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenDoubleTest(double value, double expectedResult) + { + Vector64 actualResult = Vector64.Round(Vector64.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenSingle), MemberType = typeof(GenericMathTestMemberData))] + public void RoundToEvenSingleTest(float value, float expectedResult) + { + Vector64 actualResult = Vector64.Round(Vector64.Create(value), MidpointRounding.ToEven); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateDouble), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateDoubleTest(double value, double expectedResult) + { + Vector64 actualResult = Vector64.Truncate(Vector64.Create(value)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateSingle), MemberType = typeof(GenericMathTestMemberData))] + public void TruncateSingleTest(float value, float expectedResult) + { + Vector64 actualResult = Vector64.Truncate(Vector64.Create(value)); + AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); + } } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System.Runtime.Extensions.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System.Runtime.Extensions.Tests.csproj index bf090364567c5..6efe773b447f8 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System.Runtime.Extensions.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System.Runtime.Extensions.Tests.csproj @@ -1,4 +1,4 @@ - + true true @@ -86,6 +86,7 @@ + diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Math.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Math.cs index 7d8606b799d64..136e4acf1d373 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Math.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Math.cs @@ -658,46 +658,7 @@ public static void IEEERemainder() } [Theory] - [InlineData( double.NegativeInfinity, double.NaN, 0.0)] - [InlineData(-3.1415926535897932, double.NaN, 0.0)] // value: -(pi) - [InlineData(-2.7182818284590452, double.NaN, 0.0)] // value: -(e) - [InlineData(-1.4142135623730950, double.NaN, 0.0)] // value: -(sqrt(2)) - [InlineData(-1.0, double.NaN, 0.0)] - [InlineData(-0.69314718055994531, double.NaN, 0.0)] // value: -(ln(2)) - [InlineData(-0.43429448190325183, double.NaN, 0.0)] // value: -(log10(e)) - [InlineData(-0.0, double.NegativeInfinity, 0.0)] - [InlineData( double.NaN, double.NaN, 0.0)] - [InlineData( 0.0, double.NegativeInfinity, 0.0)] - [InlineData( 0.043213918263772250, -3.1415926535897932, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) - [InlineData( 0.065988035845312537, -2.7182818284590452, CrossPlatformMachineEpsilon * 10)] // expected: -(e) - [InlineData( 0.1, -2.3025850929940457, CrossPlatformMachineEpsilon * 10)] // expected: -(ln(10)) - [InlineData( 0.20787957635076191, -1.5707963267948966, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) - [InlineData( 0.23629008834452270, -1.4426950408889634, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) - [InlineData( 0.24311673443421421, -1.4142135623730950, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) - [InlineData( 0.32355726390307110, -1.1283791670955126, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) - [InlineData( 0.36787944117144232, -1.0, CrossPlatformMachineEpsilon * 10)] - [InlineData( 0.45593812776599624, -0.78539816339744831, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) - [InlineData( 0.49306869139523979, -0.70710678118654752, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) - [InlineData( 0.5, -0.69314718055994531, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) - [InlineData( 0.52907780826773535, -0.63661977236758134, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) - [InlineData( 0.64772148514180065, -0.43429448190325183, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) - [InlineData( 0.72737734929521647, -0.31830988618379067, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) - [InlineData( 1.0, 0.0, 0.0)] - [InlineData( 1.3748022274393586, 0.31830988618379067, CrossPlatformMachineEpsilon)] // expected: (1 / pi) - [InlineData( 1.5438734439711811, 0.43429448190325183, CrossPlatformMachineEpsilon)] // expected: (log10(e)) - [InlineData( 1.8900811645722220, 0.63661977236758134, CrossPlatformMachineEpsilon)] // expected: (2 / pi) - [InlineData( 2.0, 0.69314718055994531, CrossPlatformMachineEpsilon)] // expected: (ln(2)) - [InlineData( 2.0281149816474725, 0.70710678118654752, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) - [InlineData( 2.1932800507380155, 0.78539816339744831, CrossPlatformMachineEpsilon)] // expected: (pi / 4) - [InlineData( 2.7182818284590452, 1.0, CrossPlatformMachineEpsilon * 10)] // value: (e) - [InlineData( 3.0906430223107976, 1.1283791670955126, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) - [InlineData( 4.1132503787829275, 1.4142135623730950, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) - [InlineData( 4.2320861065570819, 1.4426950408889634, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) - [InlineData( 4.8104773809653517, 1.5707963267948966, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) - [InlineData( 10.0, 2.3025850929940457, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) - [InlineData( 15.154262241479264, 2.7182818284590452, CrossPlatformMachineEpsilon * 10)] // expected: (e) - [InlineData( 23.140692632779269, 3.1415926535897932, CrossPlatformMachineEpsilon * 10)] // expected: (pi) - [InlineData( double.PositiveInfinity, double.PositiveInfinity, 0.0)] + [MemberData(nameof(GenericMathTestMemberData.LogDouble), MemberType = typeof(GenericMathTestMemberData))] public static void Log(double value, double expectedResult, double allowedVariance) { AssertExtensions.Equal(expectedResult, Math.Log(value), allowedVariance); @@ -776,23 +737,7 @@ public static void Max_Decimal() } [Theory] - [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity)] - [InlineData(double.MinValue, double.MaxValue, double.MaxValue)] - [InlineData(double.MaxValue, double.MinValue, double.MaxValue)] - [InlineData(double.NaN, double.NaN, double.NaN)] - [InlineData(double.NaN, 1.0, double.NaN)] - [InlineData(1.0, double.NaN, double.NaN)] - [InlineData(double.PositiveInfinity, double.NaN, double.NaN)] - [InlineData(double.NegativeInfinity, double.NaN, double.NaN)] - [InlineData(double.NaN, double.PositiveInfinity, double.NaN)] - [InlineData(double.NaN, double.NegativeInfinity, double.NaN)] - [InlineData(-0.0, 0.0, 0.0)] - [InlineData( 0.0, -0.0, 0.0)] - [InlineData( 2.0, -3.0, 2.0)] - [InlineData(-3.0, 2.0, 2.0)] - [InlineData( 3.0, -2.0, 3.0)] - [InlineData(-2.0, 3.0, 3.0)] + [MemberData(nameof(GenericMathTestMemberData.MaxDouble), MemberType = typeof(GenericMathTestMemberData))] public static void Max_Double_NotNetFramework(double x, double y, double expectedResult) { AssertExtensions.Equal(expectedResult, Math.Max(x, y), 0.0); @@ -857,23 +802,7 @@ public static void Max_SByte() } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MaxValue)] - [InlineData(float.MaxValue, float.MinValue, float.MaxValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0, float.NaN)] - [InlineData(1.0, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] - [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0, 0.0, 0.0)] - [InlineData( 0.0, -0.0, 0.0)] - [InlineData( 2.0, -3.0, 2.0)] - [InlineData(-3.0, 2.0, 2.0)] - [InlineData( 3.0, -2.0, 3.0)] - [InlineData(-2.0, 3.0, 3.0)] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Max_Single_NotNetFramework(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, Math.Max(x, y), 0.0f); @@ -945,23 +874,7 @@ public static void Min_Decimal() } [Theory] - [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData(double.MinValue, double.MaxValue, double.MinValue)] - [InlineData(double.MaxValue, double.MinValue, double.MinValue)] - [InlineData(double.NaN, double.NaN, double.NaN)] - [InlineData(double.NaN, 1.0, double.NaN)] - [InlineData(1.0, double.NaN, double.NaN)] - [InlineData(double.PositiveInfinity, double.NaN, double.NaN)] - [InlineData(double.NegativeInfinity, double.NaN, double.NaN)] - [InlineData(double.NaN, double.PositiveInfinity, double.NaN)] - [InlineData(double.NaN, double.NegativeInfinity, double.NaN)] - [InlineData(-0.0, 0.0, -0.0)] - [InlineData( 0.0, -0.0, -0.0)] - [InlineData( 2.0, -3.0, -3.0)] - [InlineData(-3.0, 2.0, -3.0)] - [InlineData( 3.0, -2.0, -2.0)] - [InlineData(-2.0, 3.0, -2.0)] + [MemberData(nameof(GenericMathTestMemberData.MinDouble), MemberType = typeof(GenericMathTestMemberData))] public static void Min_Double_NotNetFramework(double x, double y, double expectedResult) { AssertExtensions.Equal(expectedResult, Math.Min(x, y), 0.0); @@ -1026,23 +939,7 @@ public static void Min_SByte() } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MinValue)] - [InlineData(float.MaxValue, float.MinValue, float.MinValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0, float.NaN)] - [InlineData(1.0, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] - [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0, 0.0, -0.0)] - [InlineData( 0.0, -0.0, -0.0)] - [InlineData( 2.0, -3.0, -3.0)] - [InlineData(-3.0, 2.0, -3.0)] - [InlineData( 3.0, -2.0, -2.0)] - [InlineData(-2.0, 3.0, -2.0)] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Min_Single_NotNetFramework(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, Math.Min(x, y), 0.0f); @@ -1708,12 +1605,11 @@ public static void Truncate_Decimal() Assert.Equal(-3.0m, Math.Truncate(-3.14159m)); } - [Fact] - public static void Truncate_Double() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void Truncate_Double(double value, double expectedResult) { - Assert.Equal(0.0, Math.Truncate(0.12345)); - Assert.Equal(3.0, Math.Truncate(3.14159)); - Assert.Equal(-3.0, Math.Truncate(-3.14159)); + AssertExtensions.Equal(expectedResult, Math.Truncate(value)); } [Theory] @@ -2378,7 +2274,6 @@ public static void Clamp_ULong(ulong value, ulong min, ulong max, ulong expected Assert.Equal(expected, Math.Clamp(value, min, max)); } - [Theory] [MemberData(nameof(Clamp_SignedInt_TestData))] public static void Clamp_NInt(int value, int min, int max, int expected) @@ -2394,38 +2289,14 @@ public static void Clamp_NUInt(uint value, uint min, uint max, uint expected) } [Theory] - [MemberData(nameof(Clamp_SignedInt_TestData))] - [InlineData(double.NegativeInfinity, double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)] - [InlineData(1, double.NegativeInfinity, double.PositiveInfinity, 1)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(1, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(1, double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData(double.NaN, double.NaN, double.NaN, double.NaN)] - [InlineData(double.NaN, double.NaN, 1, double.NaN)] - [InlineData(double.NaN, 1, double.NaN, double.NaN)] - [InlineData(double.NaN, 1, 1, double.NaN)] - [InlineData(1, double.NaN, double.NaN, 1)] - [InlineData(1, double.NaN, 1, 1)] - [InlineData(1, 1, double.NaN, 1)] + [MemberData(nameof(GenericMathTestMemberData.ClampDouble), MemberType = typeof(GenericMathTestMemberData))] public static void Clamp_Double(double value, double min, double max, double expected) { Assert.Equal(expected, Math.Clamp(value, min, max)); } [Theory] - [MemberData(nameof(Clamp_SignedInt_TestData))] - [InlineData(float.NegativeInfinity, float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] - [InlineData(1, float.NegativeInfinity, float.PositiveInfinity, 1)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(1, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(1, float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.NaN, float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, float.NaN, 1, float.NaN)] - [InlineData(float.NaN, 1, float.NaN, float.NaN)] - [InlineData(float.NaN, 1, 1, float.NaN)] - [InlineData(1, float.NaN, float.NaN, 1)] - [InlineData(1, float.NaN, 1, 1)] - [InlineData(1, 1, float.NaN, 1)] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Clamp_Float(float value, float min, float max, float expected) { Assert.Equal(expected, Math.Clamp(value, min, max)); @@ -2456,127 +2327,14 @@ public static void Clamp_MinGreaterThanMax_ThrowsArgumentException() } [Theory] - [InlineData( double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData( double.NegativeInfinity, -3.1415926535897932, double.NegativeInfinity)] - [InlineData( double.NegativeInfinity, -0.0, double.NegativeInfinity)] - [InlineData( double.NegativeInfinity, double.NaN, double.NegativeInfinity)] - [InlineData( double.NegativeInfinity, 0.0, double.PositiveInfinity)] - [InlineData( double.NegativeInfinity, 3.1415926535897932, double.PositiveInfinity)] - [InlineData( double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(-3.1415926535897932, double.NegativeInfinity, -3.1415926535897932)] - [InlineData(-3.1415926535897932, -3.1415926535897932, -3.1415926535897932)] - [InlineData(-3.1415926535897932, -0.0, -3.1415926535897932)] - [InlineData(-3.1415926535897932, double.NaN, -3.1415926535897932)] - [InlineData(-3.1415926535897932, 0.0, 3.1415926535897932)] - [InlineData(-3.1415926535897932, 3.1415926535897932, 3.1415926535897932)] - [InlineData(-3.1415926535897932, double.PositiveInfinity, 3.1415926535897932)] - [InlineData(-0.0, double.NegativeInfinity, -0.0)] - [InlineData(-0.0, -3.1415926535897932, -0.0)] - [InlineData(-0.0, -0.0, -0.0)] - [InlineData(-0.0, double.NaN, -0.0)] - [InlineData(-0.0, 0.0, 0.0)] - [InlineData(-0.0, 3.1415926535897932, 0.0)] - [InlineData(-0.0, double.PositiveInfinity, 0.0)] - [InlineData( double.NaN, double.NegativeInfinity, double.NaN)] - [InlineData( double.NaN, -3.1415926535897932, double.NaN)] - [InlineData( double.NaN, -0.0, double.NaN)] - [InlineData( double.NaN, double.NaN, double.NaN)] - [InlineData( double.NaN, 0.0, double.NaN)] - [InlineData( double.NaN, 3.1415926535897932, double.NaN)] - [InlineData( double.NaN, double.PositiveInfinity, double.NaN)] - [InlineData( 0.0, double.NegativeInfinity, -0.0)] - [InlineData( 0.0, -3.1415926535897932, -0.0)] - [InlineData( 0.0, -0.0, -0.0)] - [InlineData( 0.0, double.NaN, -0.0)] - [InlineData( 0.0, 0.0, 0.0)] - [InlineData( 0.0, 3.1415926535897932, 0.0)] - [InlineData( 0.0, double.PositiveInfinity, 0.0)] - [InlineData( 3.1415926535897932, double.NegativeInfinity, -3.1415926535897932)] - [InlineData( 3.1415926535897932, -3.1415926535897932, -3.1415926535897932)] - [InlineData( 3.1415926535897932, -0.0, -3.1415926535897932)] - [InlineData( 3.1415926535897932, double.NaN, -3.1415926535897932)] - [InlineData( 3.1415926535897932, 0.0, 3.1415926535897932)] - [InlineData( 3.1415926535897932, 3.1415926535897932, 3.1415926535897932)] - [InlineData( 3.1415926535897932, double.PositiveInfinity, 3.1415926535897932)] - [InlineData( double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData( double.PositiveInfinity, -3.1415926535897932, double.NegativeInfinity)] - [InlineData( double.PositiveInfinity, -0.0, double.NegativeInfinity)] - [InlineData( double.PositiveInfinity, double.NaN, double.NegativeInfinity)] - [InlineData( double.PositiveInfinity, 0.0, double.PositiveInfinity)] - [InlineData( double.PositiveInfinity, 3.1415926535897932, double.PositiveInfinity)] - [InlineData( double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity)] + [MemberData(nameof(GenericMathTestMemberData.CopySignDouble), MemberType = typeof(GenericMathTestMemberData))] public static void CopySign(double x, double y, double expectedResult) { AssertExtensions.Equal(expectedResult, Math.CopySign(x, y), 0.0); } [Theory] - [InlineData( double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity, double.NaN)] - [InlineData( double.NegativeInfinity, -0.0, double.NegativeInfinity, double.NaN)] - [InlineData( double.NegativeInfinity, -0.0, -3.1415926535897932, double.NaN)] - [InlineData( double.NegativeInfinity, -0.0, -0.0, double.NaN)] - [InlineData( double.NegativeInfinity, -0.0, double.NaN, double.NaN)] - [InlineData( double.NegativeInfinity, -0.0, 0.0, double.NaN)] - [InlineData( double.NegativeInfinity, -0.0, 3.1415926535897932, double.NaN)] - [InlineData( double.NegativeInfinity, -0.0, double.PositiveInfinity, double.NaN)] - [InlineData( double.NegativeInfinity, 0.0, double.NegativeInfinity, double.NaN)] - [InlineData( double.NegativeInfinity, 0.0, -3.1415926535897932, double.NaN)] - [InlineData( double.NegativeInfinity, 0.0, -0.0, double.NaN)] - [InlineData( double.NegativeInfinity, 0.0, double.NaN, double.NaN)] - [InlineData( double.NegativeInfinity, 0.0, 0.0, double.NaN)] - [InlineData( double.NegativeInfinity, 0.0, 3.1415926535897932, double.NaN)] - [InlineData( double.NegativeInfinity, 0.0, double.PositiveInfinity, double.NaN)] - [InlineData( double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity, double.NaN)] - [InlineData(-1e308, 2.0, 1e308, -1e308)] - [InlineData(-1e308, 2.0, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(-5, 4, -3, -23)] - [InlineData(-0.0, double.NegativeInfinity, double.NegativeInfinity, double.NaN)] - [InlineData(-0.0, double.NegativeInfinity, -3.1415926535897932, double.NaN)] - [InlineData(-0.0, double.NegativeInfinity, -0.0, double.NaN)] - [InlineData(-0.0, double.NegativeInfinity, double.NaN, double.NaN)] - [InlineData(-0.0, double.NegativeInfinity, 0.0, double.NaN)] - [InlineData(-0.0, double.NegativeInfinity, 3.1415926535897932, double.NaN)] - [InlineData(-0.0, double.NegativeInfinity, double.PositiveInfinity, double.NaN)] - [InlineData(-0.0, double.PositiveInfinity, double.NegativeInfinity, double.NaN)] - [InlineData(-0.0, double.PositiveInfinity, -3.1415926535897932, double.NaN)] - [InlineData(-0.0, double.PositiveInfinity, -0.0, double.NaN)] - [InlineData(-0.0, double.PositiveInfinity, double.NaN, double.NaN)] - [InlineData(-0.0, double.PositiveInfinity, 0.0, double.NaN)] - [InlineData(-0.0, double.PositiveInfinity, 3.1415926535897932, double.NaN)] - [InlineData(-0.0, double.PositiveInfinity, double.PositiveInfinity, double.NaN)] - [InlineData( 0.0, double.NegativeInfinity, double.NegativeInfinity, double.NaN)] - [InlineData( 0.0, double.NegativeInfinity, -3.1415926535897932, double.NaN)] - [InlineData( 0.0, double.NegativeInfinity, -0.0, double.NaN)] - [InlineData( 0.0, double.NegativeInfinity, double.NaN, double.NaN)] - [InlineData( 0.0, double.NegativeInfinity, 0.0, double.NaN)] - [InlineData( 0.0, double.NegativeInfinity, 3.1415926535897932, double.NaN)] - [InlineData( 0.0, double.NegativeInfinity, double.PositiveInfinity, double.NaN)] - [InlineData( 0.0, double.PositiveInfinity, double.NegativeInfinity, double.NaN)] - [InlineData( 0.0, double.PositiveInfinity, -3.1415926535897932, double.NaN)] - [InlineData( 0.0, double.PositiveInfinity, -0.0, double.NaN)] - [InlineData( 0.0, double.PositiveInfinity, double.NaN, double.NaN)] - [InlineData( 0.0, double.PositiveInfinity, 0.0, double.NaN)] - [InlineData( 0.0, double.PositiveInfinity, 3.1415926535897932, double.NaN)] - [InlineData( 0.0, double.PositiveInfinity, double.PositiveInfinity, double.NaN)] - [InlineData( 5, 4, 3, 23)] - [InlineData( 1e308, 2.0, -1e308, 1e308)] - [InlineData( 1e308, 2.0, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData( double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity, double.NaN)] - [InlineData( double.PositiveInfinity, -0.0, double.NegativeInfinity, double.NaN)] - [InlineData( double.PositiveInfinity, -0.0, -3.1415926535897932, double.NaN)] - [InlineData( double.PositiveInfinity, -0.0, -0.0, double.NaN)] - [InlineData( double.PositiveInfinity, -0.0, double.NaN, double.NaN)] - [InlineData( double.PositiveInfinity, -0.0, 0.0, double.NaN)] - [InlineData( double.PositiveInfinity, -0.0, 3.1415926535897932, double.NaN)] - [InlineData( double.PositiveInfinity, -0.0, double.PositiveInfinity, double.NaN)] - [InlineData( double.PositiveInfinity, 0.0, double.NegativeInfinity, double.NaN)] - [InlineData( double.PositiveInfinity, 0.0, -3.1415926535897932, double.NaN)] - [InlineData( double.PositiveInfinity, 0.0, -0.0, double.NaN)] - [InlineData( double.PositiveInfinity, 0.0, double.NaN, double.NaN)] - [InlineData( double.PositiveInfinity, 0.0, 0.0, double.NaN)] - [InlineData( double.PositiveInfinity, 0.0, 3.1415926535897932, double.NaN)] - [InlineData( double.PositiveInfinity, 0.0, double.PositiveInfinity, double.NaN)] - [InlineData( double.PositiveInfinity, double.PositiveInfinity, double.NegativeInfinity, double.NaN)] + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddDouble), MemberType = typeof(GenericMathTestMemberData))] public static void FusedMultiplyAdd(double x, double y, double z, double expectedResult) { AssertExtensions.Equal(expectedResult, Math.FusedMultiplyAdd(x, y, z), 0.0); @@ -2633,64 +2391,14 @@ public static void ILogB(double value, int expectedResult) } [Theory] - [InlineData( double.NegativeInfinity, double.NaN, 0.0)] - [InlineData(-0.11331473229676087, double.NaN, 0.0)] - [InlineData(-0.0, double.NegativeInfinity, 0.0)] - [InlineData( double.NaN, double.NaN, 0.0)] - [InlineData( 0.0, double.NegativeInfinity, 0.0)] - [InlineData( 0.11331473229676087, -3.1415926535897932, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) - [InlineData( 0.15195522325791297, -2.7182818284590452, CrossPlatformMachineEpsilon * 10)] // expected: -(e) - [InlineData( 0.20269956628651730, -2.3025850929940457, CrossPlatformMachineEpsilon * 10)] // expected: -(ln(10)) - [InlineData( 0.33662253682241906, -1.5707963267948966, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) - [InlineData( 0.36787944117144232, -1.4426950408889634, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) - [InlineData( 0.37521422724648177, -1.4142135623730950, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) - [InlineData( 0.45742934732229695, -1.1283791670955126, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) - [InlineData( 0.5, -1.0, CrossPlatformMachineEpsilon * 10)] - [InlineData( 0.58019181037172444, -0.78539816339744831, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) - [InlineData( 0.61254732653606592, -0.70710678118654752, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) - [InlineData( 0.61850313780157598, -0.69314718055994531, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) - [InlineData( 0.64321824193300488, -0.63661977236758134, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) - [InlineData( 0.74005557395545179, -0.43429448190325183, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) - [InlineData( 0.80200887896145195, -0.31830988618379067, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) - [InlineData( 1, 0.0, 0.0)] - [InlineData( 1.2468689889006383, 0.31830988618379067, CrossPlatformMachineEpsilon)] // expected: (1 / pi) - [InlineData( 1.3512498725672678, 0.43429448190325183, CrossPlatformMachineEpsilon)] // expected: (log10(e)) - [InlineData( 1.5546822754821001, 0.63661977236758134, CrossPlatformMachineEpsilon)] // expected: (2 / pi) - [InlineData( 1.6168066722416747, 0.69314718055994531, CrossPlatformMachineEpsilon)] // expected: (ln(2)) - [InlineData( 1.6325269194381528, 0.70710678118654752, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) - [InlineData( 1.7235679341273495, 0.78539816339744831, CrossPlatformMachineEpsilon)] // expected: (pi / 4) - [InlineData( 2, 1.0, CrossPlatformMachineEpsilon * 10)] // value: (e) - [InlineData( 2.1861299583286618, 1.1283791670955126, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) - [InlineData( 2.6651441426902252, 1.4142135623730950, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) - [InlineData( 2.7182818284590452, 1.4426950408889634, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) - [InlineData( 2.9706864235520193, 1.5707963267948966, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) - [InlineData( 4.9334096679145963, 2.3025850929940457, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) - [InlineData( 6.5808859910179210, 2.7182818284590452, CrossPlatformMachineEpsilon * 10)] // expected: (e) - [InlineData( 8.8249778270762876, 3.1415926535897932, CrossPlatformMachineEpsilon * 10)] // expected: (pi) - [InlineData( double.PositiveInfinity, double.PositiveInfinity, 0.0)] + [MemberData(nameof(GenericMathTestMemberData.Log2Double), MemberType = typeof(GenericMathTestMemberData))] public static void Log2(double value, double expectedResult, double allowedVariance) { AssertExtensions.Equal(expectedResult, Math.Log2(value), allowedVariance); } [Theory] - [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity)] - [InlineData(double.MinValue, double.MaxValue, double.MaxValue)] - [InlineData(double.MaxValue, double.MinValue, double.MaxValue)] - [InlineData(double.NaN, double.NaN, double.NaN)] - [InlineData(double.NaN, 1.0, double.NaN)] - [InlineData(1.0, double.NaN, double.NaN)] - [InlineData(double.PositiveInfinity, double.NaN, double.NaN)] - [InlineData(double.NegativeInfinity, double.NaN, double.NaN)] - [InlineData(double.NaN, double.PositiveInfinity, double.NaN)] - [InlineData(double.NaN, double.NegativeInfinity, double.NaN)] - [InlineData(-0.0, 0.0, 0.0)] - [InlineData(0.0, -0.0, 0.0)] - [InlineData(2.0, -3.0, -3.0)] - [InlineData(-3.0, 2.0, -3.0)] - [InlineData(3.0, -2.0, 3.0)] - [InlineData(-2.0, 3.0, 3.0)] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] public static void MaxMagnitude(double x, double y, double expectedResult) { AssertExtensions.Equal(expectedResult, Math.MaxMagnitude(x, y), 0.0); @@ -2720,23 +2428,7 @@ public static void MaxMagnitude(double x, double y, double expectedResult) } [Theory] - [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData(double.MinValue, double.MaxValue, double.MinValue)] - [InlineData(double.MaxValue, double.MinValue, double.MinValue)] - [InlineData(double.NaN, double.NaN, double.NaN)] - [InlineData(double.NaN, 1.0, double.NaN)] - [InlineData(1.0, double.NaN, double.NaN)] - [InlineData(double.PositiveInfinity, double.NaN, double.NaN)] - [InlineData(double.NegativeInfinity, double.NaN, double.NaN)] - [InlineData(double.NaN, double.PositiveInfinity, double.NaN)] - [InlineData(double.NaN, double.NegativeInfinity, double.NaN)] - [InlineData(-0.0, 0.0, -0.0)] - [InlineData(0.0, -0.0, -0.0)] - [InlineData(2.0, -3.0, 2.0)] - [InlineData(-3.0, 2.0, 2.0)] - [InlineData(3.0, -2.0, -2.0)] - [InlineData(-2.0, 3.0, -2.0)] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] public static void MinMagnitude(double x, double y, double expectedResult) { AssertExtensions.Equal(expectedResult, Math.MinMagnitude(x, y), 0.0); @@ -3074,45 +2766,8 @@ public static void Round_Float_Constant_Arg() Assert.Equal(-4, MathF.Round(-3.5f, MidpointRounding.AwayFromZero)); } - public static IEnumerable Round_ToEven_TestData() - { - yield return new object[] { 1, 1 }; - yield return new object[] { 0.5, 0 }; - yield return new object[] { 1.5, 2 }; - yield return new object[] { 2.5, 2 }; - yield return new object[] { 3.5, 4 }; - - // Math.Round(var = 0.49999999999999994) returns 1 on ARM32 - if (!PlatformDetection.IsArmProcess) - yield return new object[] { 0.49999999999999994, 0 }; - - yield return new object[] { 1.5, 2 }; - yield return new object[] { 2.5, 2 }; - yield return new object[] { 3.5, 4 }; - yield return new object[] { 4.5, 4 }; - yield return new object[] { 3.141592653589793, 3 }; - yield return new object[] { 2.718281828459045, 3 }; - yield return new object[] { 1385.4557313670111, 1385 }; - yield return new object[] { 3423423.43432, 3423423 }; - yield return new object[] { 535345.5, 535346 }; - yield return new object[] { 535345.50001, 535346 }; - yield return new object[] { 535345.5, 535346 }; - yield return new object[] { 535345.4, 535345 }; - yield return new object[] { 535345.6, 535346 }; - yield return new object[] { -2.718281828459045, -3 }; - yield return new object[] { 10, 10 }; - yield return new object[] { -10, -10 }; - yield return new object[] { -0, -0 }; - yield return new object[] { 0, 0 }; - yield return new object[] { double.NaN, double.NaN }; - yield return new object[] { double.PositiveInfinity, double.PositiveInfinity }; - yield return new object[] { double.NegativeInfinity, double.NegativeInfinity }; - yield return new object[] { 1.7976931348623157E+308, 1.7976931348623157E+308 }; - yield return new object[] { -1.7976931348623157E+308, -1.7976931348623157E+308 }; - } - - [Theory] - [MemberData(nameof(Round_ToEven_TestData))] + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenDouble), MemberType = typeof(GenericMathTestMemberData))] public static void Round_ToEven_0(double value, double expected) { // Math.Round has special fast paths when MidpointRounding is a const @@ -3121,41 +2776,8 @@ public static void Round_ToEven_0(double value, double expected) Assert.Equal(expected, Math.Round(value, 0, MidpointRounding.ToEven)); } - public static IEnumerable Round_AwayFromZero_TestData() - { - yield return new object[] { 1, 1 }; - yield return new object[] { 0.5, 1 }; - yield return new object[] { 1.5, 2 }; - yield return new object[] { 2.5, 3 }; - yield return new object[] { 3.5, 4 }; - yield return new object[] { 0.49999999999999994, 0 }; - yield return new object[] { 1.5, 2 }; - yield return new object[] { 2.5, 3 }; - yield return new object[] { 3.5, 4 }; - yield return new object[] { 4.5, 5 }; - yield return new object[] { 3.141592653589793, 3 }; - yield return new object[] { 2.718281828459045, 3 }; - yield return new object[] { 1385.4557313670111, 1385 }; - yield return new object[] { 3423423.43432, 3423423 }; - yield return new object[] { 535345.5, 535346 }; - yield return new object[] { 535345.50001, 535346 }; - yield return new object[] { 535345.5, 535346 }; - yield return new object[] { 535345.4, 535345 }; - yield return new object[] { 535345.6, 535346 }; - yield return new object[] { -2.718281828459045, -3 }; - yield return new object[] { 10, 10 }; - yield return new object[] { -10, -10 }; - yield return new object[] { -0, -0 }; - yield return new object[] { 0, 0 }; - yield return new object[] { double.NaN, double.NaN }; - yield return new object[] { double.PositiveInfinity, double.PositiveInfinity }; - yield return new object[] { double.NegativeInfinity, double.NegativeInfinity }; - yield return new object[] { 1.7976931348623157E+308, 1.7976931348623157E+308 }; - yield return new object[] { -1.7976931348623157E+308, -1.7976931348623157E+308 }; - } - - [Theory] - [MemberData(nameof(Round_AwayFromZero_TestData))] + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroDouble), MemberType = typeof(GenericMathTestMemberData))] public static void Round_AwayFromZero_0(double value, double expected) { // Math.Round has special fast paths when MidpointRounding is a const diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/MathF.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/MathF.cs index 59040cd799c47..565c00a986b29 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/MathF.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/MathF.cs @@ -577,55 +577,7 @@ public static void Ceiling(float value, float expectedResult, float allowedVaria } [Theory] - [InlineData(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.NegativeInfinity, -3.14159265f, float.NegativeInfinity)] - [InlineData(float.NegativeInfinity, -0.0f, float.NegativeInfinity)] - [InlineData(float.NegativeInfinity, float.NaN, float.NegativeInfinity)] - [InlineData(float.NegativeInfinity, 0.0f, float.PositiveInfinity)] - [InlineData(float.NegativeInfinity, 3.14159265f, float.PositiveInfinity)] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(-3.14159265f, float.NegativeInfinity, -3.14159265f)] - [InlineData(-3.14159265f, -3.14159265f, -3.14159265f)] - [InlineData(-3.14159265f, -0.0f, -3.14159265f)] - [InlineData(-3.14159265f, float.NaN, -3.14159265f)] - [InlineData(-3.14159265f, 0.0f, 3.14159265f)] - [InlineData(-3.14159265f, 3.14159265f, 3.14159265f)] - [InlineData(-3.14159265f, float.PositiveInfinity, 3.14159265f)] - [InlineData(-0.0f, float.NegativeInfinity, -0.0f)] - [InlineData(-0.0f, -3.14159265f, -0.0f)] - [InlineData(-0.0f, -0.0f, -0.0f)] - [InlineData(-0.0f, float.NaN, -0.0f)] - [InlineData(-0.0f, 0.0f, 0.0f)] - [InlineData(-0.0f, 3.14159265f, 0.0f)] - [InlineData(-0.0f, float.PositiveInfinity, 0.0f)] - [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(float.NaN, -3.14159265f, float.NaN)] - [InlineData(float.NaN, -0.0f, float.NaN)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 0.0f, float.NaN)] - [InlineData(float.NaN, 3.14159265f, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] - [InlineData(0.0f, float.NegativeInfinity, -0.0f)] - [InlineData(0.0f, -3.14159265f, -0.0f)] - [InlineData(0.0f, -0.0f, -0.0f)] - [InlineData(0.0f, float.NaN, -0.0f)] - [InlineData(0.0f, 0.0f, 0.0f)] - [InlineData(0.0f, 3.14159265f, 0.0f)] - [InlineData(0.0f, float.PositiveInfinity, 0.0f)] - [InlineData(3.14159265f, float.NegativeInfinity, -3.14159265f)] - [InlineData(3.14159265f, -3.14159265f, -3.14159265f)] - [InlineData(3.14159265f, -0.0f, -3.14159265f)] - [InlineData(3.14159265f, float.NaN, -3.14159265f)] - [InlineData(3.14159265f, 0.0f, 3.14159265f)] - [InlineData(3.14159265f, 3.14159265f, 3.14159265f)] - [InlineData(3.14159265f, float.PositiveInfinity, 3.14159265f)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, -3.14159265f, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, -0.0f, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, float.NaN, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, 0.0f, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, 3.14159265f, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity)] + [MemberData(nameof(GenericMathTestMemberData.CopySignSingle), MemberType = typeof(GenericMathTestMemberData))] public static void CopySign(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, MathF.CopySign(x, y), 0.0f); @@ -710,39 +662,7 @@ public static void Cosh(float value, float expectedResult, float allowedVariance } [Theory] - [InlineData(float.NegativeInfinity, 0.0f, CrossPlatformMachineEpsilon)] - [InlineData(-3.14159265f, 0.0432139183f, CrossPlatformMachineEpsilon / 10)] // value: -(pi) - [InlineData(-2.71828183f, 0.0659880358f, CrossPlatformMachineEpsilon / 10)] // value: -(e) - [InlineData(-2.30258509f, 0.1f, CrossPlatformMachineEpsilon)] // value: -(ln(10)) - [InlineData(-1.57079633f, 0.207879576f, CrossPlatformMachineEpsilon)] // value: -(pi / 2) - [InlineData(-1.44269504f, 0.236290088f, CrossPlatformMachineEpsilon)] // value: -(log2(e)) - [InlineData(-1.41421356f, 0.243116734f, CrossPlatformMachineEpsilon)] // value: -(sqrt(2)) - [InlineData(-1.12837917f, 0.323557264f, CrossPlatformMachineEpsilon)] // value: -(2 / sqrt(pi)) - [InlineData(-1.0f, 0.367879441f, CrossPlatformMachineEpsilon)] - [InlineData(-0.785398163f, 0.455938128f, CrossPlatformMachineEpsilon)] // value: -(pi / 4) - [InlineData(-0.707106781f, 0.493068691f, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) - [InlineData(-0.693147181f, 0.5f, CrossPlatformMachineEpsilon)] // value: -(ln(2)) - [InlineData(-0.636619772f, 0.529077808f, CrossPlatformMachineEpsilon)] // value: -(2 / pi) - [InlineData(-0.434294482f, 0.647721485f, CrossPlatformMachineEpsilon)] // value: -(log10(e)) - [InlineData(-0.318309886f, 0.727377349f, CrossPlatformMachineEpsilon)] // value: -(1 / pi) - [InlineData(-0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(float.NaN, float.NaN, 0.0f)] - [InlineData(0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(0.318309886f, 1.37480223f, CrossPlatformMachineEpsilon * 10)] // value: (1 / pi) - [InlineData(0.434294482f, 1.54387344f, CrossPlatformMachineEpsilon * 10)] // value: (log10(e)) - [InlineData(0.636619772f, 1.89008116f, CrossPlatformMachineEpsilon * 10)] // value: (2 / pi) - [InlineData(0.693147181f, 2.0f, CrossPlatformMachineEpsilon * 10)] // value: (ln(2)) - [InlineData(0.707106781f, 2.02811498f, CrossPlatformMachineEpsilon * 10)] // value: (1 / sqrt(2)) - [InlineData(0.785398163f, 2.19328005f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 4) - [InlineData(1.0f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) - [InlineData(1.12837917f, 3.09064302f, CrossPlatformMachineEpsilon * 10)] // value: (2 / sqrt(pi)) - [InlineData(1.41421356f, 4.11325038f, CrossPlatformMachineEpsilon * 10)] // value: (sqrt(2)) - [InlineData(1.44269504f, 4.23208611f, CrossPlatformMachineEpsilon * 10)] // value: (log2(e)) - [InlineData(1.57079633f, 4.81047738f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 2) - [InlineData(2.30258509f, 10.0f, CrossPlatformMachineEpsilon * 100)] // value: (ln(10)) - [InlineData(2.71828183f, 15.1542622f, CrossPlatformMachineEpsilon * 100)] // value: (e) - [InlineData(3.14159265f, 23.1406926f, CrossPlatformMachineEpsilon * 100)] // value: (pi) - [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + [MemberData(nameof(GenericMathTestMemberData.ExpSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Exp(float value, float expectedResult, float allowedVariance) { AssertExtensions.Equal(expectedResult, MathF.Exp(value), allowedVariance); @@ -788,72 +708,7 @@ public static void Floor(float value, float expectedResult, float allowedVarianc } [Theory] - [InlineData(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity, float.NaN)] - [InlineData(float.NegativeInfinity, -0.0f, float.NegativeInfinity, float.NaN)] - [InlineData(float.NegativeInfinity, -0.0f, -3.14159265f, float.NaN)] - [InlineData(float.NegativeInfinity, -0.0f, -0.0f, float.NaN)] - [InlineData(float.NegativeInfinity, -0.0f, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, -0.0f, 0.0f, float.NaN)] - [InlineData(float.NegativeInfinity, -0.0f, 3.14159265f, float.NaN)] - [InlineData(float.NegativeInfinity, -0.0f, float.PositiveInfinity, float.NaN)] - [InlineData(float.NegativeInfinity, 0.0f, float.NegativeInfinity, float.NaN)] - [InlineData(float.NegativeInfinity, 0.0f, -3.14159265f, float.NaN)] - [InlineData(float.NegativeInfinity, 0.0f, -0.0f, float.NaN)] - [InlineData(float.NegativeInfinity, 0.0f, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, 0.0f, 0.0f, float.NaN)] - [InlineData(float.NegativeInfinity, 0.0f, 3.14159265f, float.NaN)] - [InlineData(float.NegativeInfinity, 0.0f, float.PositiveInfinity, float.NaN)] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity, float.NaN)] - [InlineData(-1e38f, 2.0f, 1e38f, -1e38f)] - [InlineData(-1e38f, 2.0f, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(-5, 4, -3, -23)] - [InlineData(-0.0f, float.NegativeInfinity, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0f, float.NegativeInfinity, -3.14159265f, float.NaN)] - [InlineData(-0.0f, float.NegativeInfinity, -0.0f, float.NaN)] - [InlineData(-0.0f, float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(-0.0f, float.NegativeInfinity, 0.0f, float.NaN)] - [InlineData(-0.0f, float.NegativeInfinity, 3.14159265f, float.NaN)] - [InlineData(-0.0f, float.NegativeInfinity, float.PositiveInfinity, float.NaN)] - [InlineData(-0.0f, float.PositiveInfinity, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0f, float.PositiveInfinity, -3.14159265f, float.NaN)] - [InlineData(-0.0f, float.PositiveInfinity, -0.0f, float.NaN)] - [InlineData(-0.0f, float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(-0.0f, float.PositiveInfinity, 0.0f, float.NaN)] - [InlineData(-0.0f, float.PositiveInfinity, 3.14159265f, float.NaN)] - [InlineData(-0.0f, float.PositiveInfinity, float.PositiveInfinity, float.NaN)] - [InlineData(0.0f, float.NegativeInfinity, float.NegativeInfinity, float.NaN)] - [InlineData(0.0f, float.NegativeInfinity, -3.14159265f, float.NaN)] - [InlineData(0.0f, float.NegativeInfinity, -0.0f, float.NaN)] - [InlineData(0.0f, float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(0.0f, float.NegativeInfinity, 0.0f, float.NaN)] - [InlineData(0.0f, float.NegativeInfinity, 3.14159265f, float.NaN)] - [InlineData(0.0f, float.NegativeInfinity, float.PositiveInfinity, float.NaN)] - [InlineData(0.0f, float.PositiveInfinity, float.NegativeInfinity, float.NaN)] - [InlineData(0.0f, float.PositiveInfinity, -3.14159265f, float.NaN)] - [InlineData(0.0f, float.PositiveInfinity, -0.0f, float.NaN)] - [InlineData(0.0f, float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(0.0f, float.PositiveInfinity, 0.0f, float.NaN)] - [InlineData(0.0f, float.PositiveInfinity, 3.14159265f, float.NaN)] - [InlineData(0.0f, float.PositiveInfinity, float.PositiveInfinity, float.NaN)] - [InlineData(5, 4, 3, 23)] - [InlineData(1e38f, 2.0f, -1e38f, 1e38f)] - [InlineData(1e38f, 2.0f, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity, float.NaN)] - [InlineData(float.PositiveInfinity, -0.0f, float.NegativeInfinity, float.NaN)] - [InlineData(float.PositiveInfinity, -0.0f, -3.14159265f, float.NaN)] - [InlineData(float.PositiveInfinity, -0.0f, -0.0f, float.NaN)] - [InlineData(float.PositiveInfinity, -0.0f, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, -0.0f, 0.0f, float.NaN)] - [InlineData(float.PositiveInfinity, -0.0f, 3.14159265f, float.NaN)] - [InlineData(float.PositiveInfinity, -0.0f, float.PositiveInfinity, float.NaN)] - [InlineData(float.PositiveInfinity, 0.0f, float.NegativeInfinity, float.NaN)] - [InlineData(float.PositiveInfinity, 0.0f, -3.14159265f, float.NaN)] - [InlineData(float.PositiveInfinity, 0.0f, -0.0f, float.NaN)] - [InlineData(float.PositiveInfinity, 0.0f, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, 0.0f, 0.0f, float.NaN)] - [InlineData(float.PositiveInfinity, 0.0f, 3.14159265f, float.NaN)] - [InlineData(float.PositiveInfinity, 0.0f, float.PositiveInfinity, float.NaN)] - [InlineData(float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NaN)] + [MemberData(nameof(GenericMathTestMemberData.FusedMultiplyAddSingle), MemberType = typeof(GenericMathTestMemberData))] public static void FusedMultiplyAdd(float x, float y, float z, float expectedResult) { AssertExtensions.Equal(expectedResult, MathF.FusedMultiplyAdd(x, y, z), 0.0f); @@ -925,46 +780,7 @@ public static void ILogB(float value, int expectedResult) } [Theory] - [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] - [InlineData(-3.14159265f, float.NaN, 0.0f)] // value: -(pi) - [InlineData(-2.71828183f, float.NaN, 0.0f)] // value: -(e) - [InlineData(-1.41421356f, float.NaN, 0.0f)] // value: -(sqrt(2)) - [InlineData(-1.0f, float.NaN, 0.0f)] - [InlineData(-0.693147181f, float.NaN, 0.0f)] // value: -(ln(2)) - [InlineData(-0.434294482f, float.NaN, 0.0f)] // value: -(log10(e)) - [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] - [InlineData(float.NaN, float.NaN, 0.0f)] - [InlineData(0.0f, float.NegativeInfinity, 0.0f)] - [InlineData(0.0432139183f, -3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) - [InlineData(0.0659880358f, -2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: -(e) - [InlineData(0.1f, -2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: -(ln(10)) - [InlineData(0.207879576f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) - [InlineData(0.236290088f, -1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) - [InlineData(0.243116734f, -1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) - [InlineData(0.323557264f, -1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) - [InlineData(0.367879441f, -1.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(0.455938128f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) - [InlineData(0.493068691f, -0.707106781f, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) - [InlineData(0.5f, -0.693147181f, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) - [InlineData(0.529077808f, -0.636619772f, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) - [InlineData(0.647721485f, -0.434294482f, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) - [InlineData(0.727377349f, -0.318309886f, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) - [InlineData(1.0f, 0.0f, 0.0f)] - [InlineData(1.37480223f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) - [InlineData(1.54387344f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) - [InlineData(1.89008116f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) - [InlineData(2.0f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) - [InlineData(2.02811498f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) - [InlineData(2.19328005f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) - [InlineData(2.71828183f, 1.0f, CrossPlatformMachineEpsilon * 10)] // value: (e) - [InlineData(3.09064302f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) - [InlineData(4.11325038f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) - [InlineData(4.23208611f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) - [InlineData(4.81047738f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) - [InlineData(10.0f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) - [InlineData(15.1542622f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) - [InlineData(23.1406926f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) - [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + [MemberData(nameof(GenericMathTestMemberData.LogSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Log(float value, float expectedResult, float allowedVariance) { AssertExtensions.Equal(expectedResult, MathF.Log(value), allowedVariance); @@ -983,41 +799,7 @@ public static void LogWithBase() } [Theory] - [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] - [InlineData(-0.113314732f, float.NaN, 0.0f)] - [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] - [InlineData(float.NaN, float.NaN, 0.0f)] - [InlineData(0.0f, float.NegativeInfinity, 0.0f)] - [InlineData(0.113314732f, -3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) - [InlineData(0.151955223f, -2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: -(e) - [InlineData(0.202699566f, -2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: -(ln(10)) - [InlineData(0.336622537f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) - [InlineData(0.367879441f, -1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) - [InlineData(0.375214227f, -1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) - [InlineData(0.457429347f, -1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) - [InlineData(0.5f, -1.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(0.580191810f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) - [InlineData(0.612547327f, -0.707106781f, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) - [InlineData(0.618503138f, -0.693147181f, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) - [InlineData(0.643218242f, -0.636619772f, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) - [InlineData(0.740055574f, -0.434294482f, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) - [InlineData(0.802008879f, -0.318309886f, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) - [InlineData(1, 0.0f, 0.0f)] - [InlineData(1.24686899f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) - [InlineData(1.35124987f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) - [InlineData(1.55468228f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) - [InlineData(1.61680667f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) - [InlineData(1.63252692f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) - [InlineData(1.72356793f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) - [InlineData(2, 1.0f, CrossPlatformMachineEpsilon * 10)] // value: (e) - [InlineData(2.18612996f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) - [InlineData(2.66514414f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) - [InlineData(2.71828183f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) - [InlineData(2.97068642f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) - [InlineData(4.93340967f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) - [InlineData(6.58088599f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) - [InlineData(8.82497783f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) - [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] public static void Log2(float value, float expectedResult, float allowedVariance) { AssertExtensions.Equal(expectedResult, MathF.Log2(value), allowedVariance); @@ -1070,23 +852,7 @@ public static void Log10(float value, float expectedResult, float allowedVarianc } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MaxValue)] - [InlineData(float.MaxValue, float.MinValue, float.MaxValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, float.NaN)] - [InlineData(1.0f, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] - [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0f, 0.0f, 0.0f)] - [InlineData(0.0f, -0.0f, 0.0f)] - [InlineData(2.0f, -3.0f, 2.0f)] - [InlineData(-3.0f, 2.0f, 2.0f)] - [InlineData(3.0f, -2.0f, 3.0f)] - [InlineData(-2.0f, 3.0f, 3.0f)] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Max(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, MathF.Max(x, y), 0.0f); @@ -1116,23 +882,7 @@ public static void Max(float x, float y, float expectedResult) } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MaxValue)] - [InlineData(float.MaxValue, float.MinValue, float.MaxValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, float.NaN)] - [InlineData(1.0f, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] - [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0f, 0.0f, 0.0f)] - [InlineData(0.0f, -0.0f, 0.0f)] - [InlineData(2.0f, -3.0f, -3.0f)] - [InlineData(-3.0f, 2.0f, -3.0f)] - [InlineData(3.0f, -2.0f, 3.0f)] - [InlineData(-2.0f, 3.0f, 3.0f)] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] public static void MaxMagnitude(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, MathF.MaxMagnitude(x, y), 0.0f); @@ -1162,23 +912,7 @@ public static void MaxMagnitude(float x, float y, float expectedResult) } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MinValue)] - [InlineData(float.MaxValue, float.MinValue, float.MinValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, float.NaN)] - [InlineData(1.0f, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] - [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0f, 0.0f, -0.0f)] - [InlineData(0.0f, -0.0f, -0.0f)] - [InlineData(2.0f, -3.0f, -3.0f)] - [InlineData(-3.0f, 2.0f, -3.0f)] - [InlineData(3.0f, -2.0f, -2.0f)] - [InlineData(-2.0f, 3.0f, -2.0f)] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Min(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, MathF.Min(x, y), 0.0f); @@ -1203,23 +937,7 @@ public static void Min(float x, float y, float expectedResult) } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MinValue)] - [InlineData(float.MaxValue, float.MinValue, float.MinValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, float.NaN)] - [InlineData(1.0f, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] - [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0f, 0.0f, -0.0f)] - [InlineData(0.0f, -0.0f, -0.0f)] - [InlineData(2.0f, -3.0f, 2.0f)] - [InlineData(-3.0f, 2.0f, 2.0f)] - [InlineData(3.0f, -2.0f, -2.0f)] - [InlineData(-2.0f, 3.0f, -2.0f)] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] public static void MinMagnitude(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, MathF.MinMagnitude(x, y), 0.0f); @@ -1523,17 +1241,11 @@ public static IEnumerable Round_Digits_TestData } } - [Fact] - public static void Round() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.RoundSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void Round(float value, float expectedResult) { - Assert.Equal(0.0f, MathF.Round(0.0f)); - Assert.Equal(1.0f, MathF.Round(1.4f)); - Assert.Equal(2.0f, MathF.Round(1.5f)); - Assert.Equal(2e7f, MathF.Round(2e7f)); - Assert.Equal(0.0f, MathF.Round(-0.0f)); - Assert.Equal(-1.0f, MathF.Round(-1.4f)); - Assert.Equal(-2.0f, MathF.Round(-1.5f)); - Assert.Equal(-2e7f, MathF.Round(-2e7f)); + AssertExtensions.Equal(expectedResult, MathF.Round(value), 0.0f); } [Theory] @@ -1874,49 +1586,15 @@ public static void Tanh(float value, float expectedResult, float allowedVariance AssertExtensions.Equal(expectedResult, MathF.Tanh(value), allowedVariance); } - [Fact] - public static void Truncate() - { - Assert.Equal(0.0f, MathF.Truncate(0.12345f)); - Assert.Equal(3.0f, MathF.Truncate(3.14159f)); - Assert.Equal(-3.0f, MathF.Truncate(-3.14159f)); - } - - public static IEnumerable Round_ToEven_TestData() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.TruncateSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void Truncate(float value, float expectedResult) { - yield return new object[] { 1f, 1f }; - yield return new object[] { 0.5f, 0f }; - yield return new object[] { 1.5f, 2f }; - yield return new object[] { 2.5f, 2f }; - yield return new object[] { 3.5f, 4f }; - yield return new object[] { 0.49999997f, 0f }; - yield return new object[] { 1.5f, 2f }; - yield return new object[] { 2.5f, 2f }; - yield return new object[] { 3.5f, 4f }; - yield return new object[] { 4.5f, 4f }; - yield return new object[] { 3.1415927f, 3f }; - yield return new object[] { 2.7182817f, 3f }; - yield return new object[] { 1385.4557f, 1385f }; - yield return new object[] { 3423.4343f, 3423f }; - yield return new object[] { 535345.5f, 535346f }; - yield return new object[] { 535345.5f, 535346f }; - yield return new object[] { 535345.5f, 535346f }; - yield return new object[] { 535345.4f, 535345f }; - yield return new object[] { 535345.6f, 535346f }; - yield return new object[] { -2.7182817f, -3f }; - yield return new object[] { 10f, 10f }; - yield return new object[] { -10f, -10f }; - yield return new object[] { -0f, -0f }; - yield return new object[] { 0f, 0f }; - yield return new object[] { float.NaN, float.NaN }; - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity }; - yield return new object[] { float.NegativeInfinity, float.NegativeInfinity }; - yield return new object[] { 3.4028235E+38f, 3.4028235E+38f }; - yield return new object[] { -3.4028235E+38f, -3.4028235E+38f }; + AssertExtensions.Equal(expectedResult, MathF.Truncate(value), 0.0f); } [Theory] - [MemberData(nameof(Round_ToEven_TestData))] + [MemberData(nameof(GenericMathTestMemberData.RoundToEvenSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Round_ToEven_0(float value, float expected) { // Math.Round has special fast paths when MidpointRounding is a const @@ -1925,41 +1603,8 @@ public static void Round_ToEven_0(float value, float expected) Assert.Equal(expected, MathF.Round(value, 0, MidpointRounding.ToEven)); } - public static IEnumerable Round_AwayFromZero_TestData() - { - yield return new object[] { 1f, 1f }; - yield return new object[] { 0.5f, 1f }; - yield return new object[] { 1.5f, 2f }; - yield return new object[] { 2.5f, 3f }; - yield return new object[] { 3.5f, 4f }; - yield return new object[] { 0.49999997f, 0f }; - yield return new object[] { 1.5f, 2f }; - yield return new object[] { 2.5f, 3f }; - yield return new object[] { 3.5f, 4f }; - yield return new object[] { 4.5f, 5f }; - yield return new object[] { 3.1415927f, 3f }; - yield return new object[] { 2.7182817f, 3f }; - yield return new object[] { 1385.4557f, 1385f }; - yield return new object[] { 3423.4343f, 3423f }; - yield return new object[] { 535345.5f, 535346f }; - yield return new object[] { 535345.5f, 535346f }; - yield return new object[] { 535345.5f, 535346f }; - yield return new object[] { 535345.4f, 535345f }; - yield return new object[] { 535345.6f, 535346f }; - yield return new object[] { -2.7182817f, -3f }; - yield return new object[] { 10f, 10f }; - yield return new object[] { -10f, -10f }; - yield return new object[] { -0f, -0f }; - yield return new object[] { 0f, 0f }; - yield return new object[] { float.NaN, float.NaN }; - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity }; - yield return new object[] { float.NegativeInfinity, float.NegativeInfinity }; - yield return new object[] { 3.4028235E+38f, 3.4028235E+38f }; - yield return new object[] { -3.4028235E+38f, -3.4028235E+38f }; - } - [Theory] - [MemberData(nameof(Round_AwayFromZero_TestData))] + [MemberData(nameof(GenericMathTestMemberData.RoundAwayFromZeroSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Round_AwayFromZero_0(float value, float expected) { // Math.Round has special fast paths when MidpointRounding is a const diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj index 1c9fa97e35c6d..92bc092999191 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj @@ -43,6 +43,7 @@ + diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs index d829eb1199d4d..3402e419b3617 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs @@ -117,24 +117,11 @@ public static void IsPow2Test() Assert.False(BinaryNumberHelper.IsPow2(double.PositiveInfinity)); } - [Fact] - public static void Log2Test() - { - AssertBitwiseEqual(double.NaN, BinaryNumberHelper.Log2(double.NegativeInfinity)); - AssertBitwiseEqual(double.NaN, BinaryNumberHelper.Log2(double.MinValue)); - AssertBitwiseEqual(double.NaN, BinaryNumberHelper.Log2(-1.0)); - AssertBitwiseEqual(double.NaN, BinaryNumberHelper.Log2(-MinNormal)); - AssertBitwiseEqual(double.NaN, BinaryNumberHelper.Log2(-MaxSubnormal)); - AssertBitwiseEqual(double.NaN, BinaryNumberHelper.Log2(-double.Epsilon)); - AssertBitwiseEqual(double.NegativeInfinity, BinaryNumberHelper.Log2(-0.0)); - AssertBitwiseEqual(double.NaN, BinaryNumberHelper.Log2(double.NaN)); - AssertBitwiseEqual(double.NegativeInfinity, BinaryNumberHelper.Log2(0.0)); - AssertBitwiseEqual(-1074.0, BinaryNumberHelper.Log2(double.Epsilon)); - AssertBitwiseEqual(-1022.0, BinaryNumberHelper.Log2(MaxSubnormal)); - AssertBitwiseEqual(-1022.0, BinaryNumberHelper.Log2(MinNormal)); - AssertBitwiseEqual(0.0, BinaryNumberHelper.Log2(1.0)); - AssertBitwiseEqual(1024.0, BinaryNumberHelper.Log2(double.MaxValue)); - AssertBitwiseEqual(double.PositiveInfinity, BinaryNumberHelper.Log2(double.PositiveInfinity)); + [Theory] + [MemberData(nameof(GenericMathTestMemberData.Log2Double), MemberType = typeof(GenericMathTestMemberData))] + public static void Log2Test(double value, double expectedResult, double allowedVariance) + { + AssertExtensions.Equal(expectedResult, BinaryNumberHelper.Log2(value), allowedVariance); } // @@ -1029,104 +1016,39 @@ public static void op_CheckedMultiplyTest() // INumber // - [Fact] - public static void ClampTest() - { - AssertBitwiseEqual(1.0, NumberHelper.Clamp(double.NegativeInfinity, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(double.MinValue, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(-1.0, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(-MinNormal, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(-MaxSubnormal, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(-double.Epsilon, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(-0.0, 1.0, 63.0)); - AssertBitwiseEqual(double.NaN, NumberHelper.Clamp(double.NaN, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(0.0, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(double.Epsilon, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(MaxSubnormal, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(MinNormal, 1.0, 63.0)); - AssertBitwiseEqual(1.0, NumberHelper.Clamp(1.0, 1.0, 63.0)); - AssertBitwiseEqual(63.0, NumberHelper.Clamp(double.MaxValue, 1.0, 63.0)); - AssertBitwiseEqual(63.0, NumberHelper.Clamp(double.PositiveInfinity, 1.0, 63.0)); - } - - [Fact] - public static void MaxTest() - { - AssertBitwiseEqual(1.0, NumberHelper.Max(double.NegativeInfinity, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(double.MinValue, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(-1.0, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(-MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(-MaxSubnormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(-double.Epsilon, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(-0.0, 1.0)); - AssertBitwiseEqual(double.NaN, NumberHelper.Max(double.NaN, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(0.0, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(double.Epsilon, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(MaxSubnormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Max(1.0, 1.0)); - AssertBitwiseEqual(double.MaxValue, NumberHelper.Max(double.MaxValue, 1.0)); - AssertBitwiseEqual(double.PositiveInfinity, NumberHelper.Max(double.PositiveInfinity, 1.0)); - } - - [Fact] - public static void MaxNumberTest() - { - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(double.NegativeInfinity, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(double.MinValue, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(-1.0, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(-MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(-MaxSubnormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(-double.Epsilon, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(-0.0, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(double.NaN, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(0.0, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(double.Epsilon, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(MaxSubnormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MaxNumber(1.0, 1.0)); - AssertBitwiseEqual(double.MaxValue, NumberHelper.MaxNumber(double.MaxValue, 1.0)); - AssertBitwiseEqual(double.PositiveInfinity, NumberHelper.MaxNumber(double.PositiveInfinity, 1.0)); - } - - [Fact] - public static void MinTest() - { - AssertBitwiseEqual(double.NegativeInfinity, NumberHelper.Min(double.NegativeInfinity, 1.0)); - AssertBitwiseEqual(double.MinValue, NumberHelper.Min(double.MinValue, 1.0)); - AssertBitwiseEqual(-1.0, NumberHelper.Min(-1.0, 1.0)); - AssertBitwiseEqual(-MinNormal, NumberHelper.Min(-MinNormal, 1.0)); - AssertBitwiseEqual(-MaxSubnormal, NumberHelper.Min(-MaxSubnormal, 1.0)); - AssertBitwiseEqual(-double.Epsilon, NumberHelper.Min(-double.Epsilon, 1.0)); - AssertBitwiseEqual(-0.0, NumberHelper.Min(-0.0, 1.0)); - AssertBitwiseEqual(double.NaN, NumberHelper.Min(double.NaN, 1.0)); - AssertBitwiseEqual(0.0, NumberHelper.Min(0.0, 1.0)); - AssertBitwiseEqual(double.Epsilon, NumberHelper.Min(double.Epsilon, 1.0)); - AssertBitwiseEqual(MaxSubnormal, NumberHelper.Min(MaxSubnormal, 1.0)); - AssertBitwiseEqual(MinNormal, NumberHelper.Min(MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Min(1.0, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Min(double.MaxValue, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.Min(double.PositiveInfinity, 1.0)); - } - - [Fact] - public static void MinNumberTest() - { - AssertBitwiseEqual(double.NegativeInfinity, NumberHelper.MinNumber(double.NegativeInfinity, 1.0)); - AssertBitwiseEqual(double.MinValue, NumberHelper.MinNumber(double.MinValue, 1.0)); - AssertBitwiseEqual(-1.0, NumberHelper.MinNumber(-1.0, 1.0)); - AssertBitwiseEqual(-MinNormal, NumberHelper.MinNumber(-MinNormal, 1.0)); - AssertBitwiseEqual(-MaxSubnormal, NumberHelper.MinNumber(-MaxSubnormal, 1.0)); - AssertBitwiseEqual(-double.Epsilon, NumberHelper.MinNumber(-double.Epsilon, 1.0)); - AssertBitwiseEqual(-0.0, NumberHelper.MinNumber(-0.0, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MinNumber(double.NaN, 1.0)); - AssertBitwiseEqual(0.0, NumberHelper.MinNumber(0.0, 1.0)); - AssertBitwiseEqual(double.Epsilon, NumberHelper.MinNumber(double.Epsilon, 1.0)); - AssertBitwiseEqual(MaxSubnormal, NumberHelper.MinNumber(MaxSubnormal, 1.0)); - AssertBitwiseEqual(MinNormal, NumberHelper.MinNumber(MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MinNumber(1.0, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MinNumber(double.MaxValue, 1.0)); - AssertBitwiseEqual(1.0, NumberHelper.MinNumber(double.PositiveInfinity, 1.0)); + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void ClampTest(double value, double min, double max, double expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberHelper.Clamp(value, min, max)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void MaxTest(double x, double y, double expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberHelper.Max(x, y)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void MaxNumberTest(double x, double y, double expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberHelper.MaxNumber(x, y)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void MinTest(double x, double y, double expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberHelper.Min(x, y)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void MinNumberTest(double x, double y, double expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberHelper.MinNumber(x, y)); } [Fact] @@ -2198,44 +2120,18 @@ public static void IsIntegerTest() Assert.False(NumberBaseHelper.IsInteger(double.PositiveInfinity)); } - [Fact] - public static void IsNaNTest() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void IsNaNTest(double value, bool expectedResult) { - Assert.False(NumberBaseHelper.IsNaN(double.NegativeInfinity)); - Assert.False(NumberBaseHelper.IsNaN(double.MinValue)); - Assert.False(NumberBaseHelper.IsNaN(-1.0)); - Assert.False(NumberBaseHelper.IsNaN(-MinNormal)); - Assert.False(NumberBaseHelper.IsNaN(-MaxSubnormal)); - Assert.False(NumberBaseHelper.IsNaN(-double.Epsilon)); - Assert.False(NumberBaseHelper.IsNaN(-0.0)); - Assert.True(NumberBaseHelper.IsNaN(double.NaN)); - Assert.False(NumberBaseHelper.IsNaN(0.0)); - Assert.False(NumberBaseHelper.IsNaN(double.Epsilon)); - Assert.False(NumberBaseHelper.IsNaN(MaxSubnormal)); - Assert.False(NumberBaseHelper.IsNaN(MinNormal)); - Assert.False(NumberBaseHelper.IsNaN(1.0)); - Assert.False(NumberBaseHelper.IsNaN(double.MaxValue)); - Assert.False(NumberBaseHelper.IsNaN(double.PositiveInfinity)); + Assert.Equal(expectedResult, NumberBaseHelper.IsNaN(value)); } - [Fact] - public static void IsNegativeTest() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void IsNegativeTest(double value, bool expectedResult) { - Assert.True(NumberBaseHelper.IsNegative(double.NegativeInfinity)); - Assert.True(NumberBaseHelper.IsNegative(double.MinValue)); - Assert.True(NumberBaseHelper.IsNegative(-1.0)); - Assert.True(NumberBaseHelper.IsNegative(-MinNormal)); - Assert.True(NumberBaseHelper.IsNegative(-MaxSubnormal)); - Assert.True(NumberBaseHelper.IsNegative(-double.Epsilon)); - Assert.True(NumberBaseHelper.IsNegative(-0.0)); - Assert.True(NumberBaseHelper.IsNegative(double.NaN)); - Assert.False(NumberBaseHelper.IsNegative(0.0)); - Assert.False(NumberBaseHelper.IsNegative(double.Epsilon)); - Assert.False(NumberBaseHelper.IsNegative(MaxSubnormal)); - Assert.False(NumberBaseHelper.IsNegative(MinNormal)); - Assert.False(NumberBaseHelper.IsNegative(1.0)); - Assert.False(NumberBaseHelper.IsNegative(double.MaxValue)); - Assert.False(NumberBaseHelper.IsNegative(double.PositiveInfinity)); + Assert.Equal(expectedResult, NumberBaseHelper.IsNegative(value)); } [Fact] @@ -2298,44 +2194,18 @@ public static void IsOddIntegerTest() Assert.False(NumberBaseHelper.IsOddInteger(double.PositiveInfinity)); } - [Fact] - public static void IsPositiveTest() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void IsPositiveTest(double value, bool expectedResult) { - Assert.False(NumberBaseHelper.IsPositive(double.NegativeInfinity)); - Assert.False(NumberBaseHelper.IsPositive(double.MinValue)); - Assert.False(NumberBaseHelper.IsPositive(-1.0)); - Assert.False(NumberBaseHelper.IsPositive(-MinNormal)); - Assert.False(NumberBaseHelper.IsPositive(-MaxSubnormal)); - Assert.False(NumberBaseHelper.IsPositive(-double.Epsilon)); - Assert.False(NumberBaseHelper.IsPositive(-0.0)); - Assert.False(NumberBaseHelper.IsPositive(double.NaN)); - Assert.True(NumberBaseHelper.IsPositive(0.0)); - Assert.True(NumberBaseHelper.IsPositive(double.Epsilon)); - Assert.True(NumberBaseHelper.IsPositive(MaxSubnormal)); - Assert.True(NumberBaseHelper.IsPositive(MinNormal)); - Assert.True(NumberBaseHelper.IsPositive(1.0)); - Assert.True(NumberBaseHelper.IsPositive(double.MaxValue)); - Assert.True(NumberBaseHelper.IsPositive(double.PositiveInfinity)); + Assert.Equal(expectedResult, NumberBaseHelper.IsPositive(value)); } - [Fact] - public static void IsPositiveInfinityTest() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void IsPositiveInfinityTest(double value, bool expectedResult) { - Assert.False(NumberBaseHelper.IsPositiveInfinity(double.NegativeInfinity)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(double.MinValue)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-1.0)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-MinNormal)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-MaxSubnormal)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-double.Epsilon)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-0.0)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(double.NaN)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(0.0)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(double.Epsilon)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(MaxSubnormal)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(MinNormal)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(1.0)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(double.MaxValue)); - Assert.True(NumberBaseHelper.IsPositiveInfinity(double.PositiveInfinity)); + Assert.Equal(expectedResult, NumberBaseHelper.IsPositiveInfinity(value)); } [Fact] @@ -2378,104 +2248,39 @@ public static void IsSubnormalTest() Assert.False(NumberBaseHelper.IsSubnormal(double.PositiveInfinity)); } - [Fact] - public static void IsZeroTest() - { - Assert.False(NumberBaseHelper.IsZero(double.NegativeInfinity)); - Assert.False(NumberBaseHelper.IsZero(double.MinValue)); - Assert.False(NumberBaseHelper.IsZero(-1.0)); - Assert.False(NumberBaseHelper.IsZero(-MinNormal)); - Assert.False(NumberBaseHelper.IsZero(-MaxSubnormal)); - Assert.False(NumberBaseHelper.IsZero(-double.Epsilon)); - Assert.True(NumberBaseHelper.IsZero(-0.0)); - Assert.False(NumberBaseHelper.IsZero(double.NaN)); - Assert.True(NumberBaseHelper.IsZero(0.0)); - Assert.False(NumberBaseHelper.IsZero(double.Epsilon)); - Assert.False(NumberBaseHelper.IsZero(MaxSubnormal)); - Assert.False(NumberBaseHelper.IsZero(MinNormal)); - Assert.False(NumberBaseHelper.IsZero(1.0)); - Assert.False(NumberBaseHelper.IsZero(double.MaxValue)); - Assert.False(NumberBaseHelper.IsZero(double.PositiveInfinity)); - } - - [Fact] - public static void MaxMagnitudeTest() - { - AssertBitwiseEqual(double.NegativeInfinity, NumberBaseHelper.MaxMagnitude(double.NegativeInfinity, 1.0)); - AssertBitwiseEqual(double.MinValue, NumberBaseHelper.MaxMagnitude(double.MinValue, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(-1.0, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(-MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(-MaxSubnormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(-double.Epsilon, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(-0.0, 1.0)); - AssertBitwiseEqual(double.NaN, NumberBaseHelper.MaxMagnitude(double.NaN, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(0.0, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(double.Epsilon, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(MaxSubnormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitude(1.0, 1.0)); - AssertBitwiseEqual(double.MaxValue, NumberBaseHelper.MaxMagnitude(double.MaxValue, 1.0)); - AssertBitwiseEqual(double.PositiveInfinity, NumberBaseHelper.MaxMagnitude(double.PositiveInfinity, 1.0)); - } - - [Fact] - public static void MaxMagnitudeNumberTest() - { - AssertBitwiseEqual(double.NegativeInfinity, NumberBaseHelper.MaxMagnitudeNumber(double.NegativeInfinity, 1.0)); - AssertBitwiseEqual(double.MinValue, NumberBaseHelper.MaxMagnitudeNumber(double.MinValue, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(-1.0, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(-MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(-MaxSubnormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(-double.Epsilon, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(-0.0, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(double.NaN, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(0.0, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(double.Epsilon, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(MaxSubnormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MaxMagnitudeNumber(1.0, 1.0)); - AssertBitwiseEqual(double.MaxValue, NumberBaseHelper.MaxMagnitudeNumber(double.MaxValue, 1.0)); - AssertBitwiseEqual(double.PositiveInfinity, NumberBaseHelper.MaxMagnitudeNumber(double.PositiveInfinity, 1.0)); - } - - [Fact] - public static void MinMagnitudeTest() - { - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitude(double.NegativeInfinity, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitude(double.MinValue, 1.0)); - AssertBitwiseEqual(-1.0, NumberBaseHelper.MinMagnitude(-1.0, 1.0)); - AssertBitwiseEqual(-MinNormal, NumberBaseHelper.MinMagnitude(-MinNormal, 1.0)); - AssertBitwiseEqual(-MaxSubnormal, NumberBaseHelper.MinMagnitude(-MaxSubnormal, 1.0)); - AssertBitwiseEqual(-double.Epsilon, NumberBaseHelper.MinMagnitude(-double.Epsilon, 1.0)); - AssertBitwiseEqual(-0.0, NumberBaseHelper.MinMagnitude(-0.0, 1.0)); - AssertBitwiseEqual(double.NaN, NumberBaseHelper.MinMagnitude(double.NaN, 1.0)); - AssertBitwiseEqual(0.0, NumberBaseHelper.MinMagnitude(0.0, 1.0)); - AssertBitwiseEqual(double.Epsilon, NumberBaseHelper.MinMagnitude(double.Epsilon, 1.0)); - AssertBitwiseEqual(MaxSubnormal, NumberBaseHelper.MinMagnitude(MaxSubnormal, 1.0)); - AssertBitwiseEqual(MinNormal, NumberBaseHelper.MinMagnitude(MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitude(1.0, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitude(double.MaxValue, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitude(double.PositiveInfinity, 1.0)); - } - - [Fact] - public static void MinMagnitudeNumberTest() - { - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitudeNumber(double.NegativeInfinity, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitudeNumber(double.MinValue, 1.0)); - AssertBitwiseEqual(-1.0, NumberBaseHelper.MinMagnitudeNumber(-1.0, 1.0)); - AssertBitwiseEqual(-MinNormal, NumberBaseHelper.MinMagnitudeNumber(-MinNormal, 1.0)); - AssertBitwiseEqual(-MaxSubnormal, NumberBaseHelper.MinMagnitudeNumber(-MaxSubnormal, 1.0)); - AssertBitwiseEqual(-double.Epsilon, NumberBaseHelper.MinMagnitudeNumber(-double.Epsilon, 1.0)); - AssertBitwiseEqual(-0.0, NumberBaseHelper.MinMagnitudeNumber(-0.0, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitudeNumber(double.NaN, 1.0)); - AssertBitwiseEqual(0.0, NumberBaseHelper.MinMagnitudeNumber(0.0, 1.0)); - AssertBitwiseEqual(double.Epsilon, NumberBaseHelper.MinMagnitudeNumber(double.Epsilon, 1.0)); - AssertBitwiseEqual(MaxSubnormal, NumberBaseHelper.MinMagnitudeNumber(MaxSubnormal, 1.0)); - AssertBitwiseEqual(MinNormal, NumberBaseHelper.MinMagnitudeNumber(MinNormal, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitudeNumber(1.0, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitudeNumber(double.MaxValue, 1.0)); - AssertBitwiseEqual(1.0, NumberBaseHelper.MinMagnitudeNumber(double.PositiveInfinity, 1.0)); + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void IsZeroTest(double value, bool expectedResult) + { + Assert.Equal(expectedResult, NumberBaseHelper.IsZero(value)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void MaxMagnitudeTest(double x, double y, double expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberBaseHelper.MaxMagnitude(x, y)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void MaxMagnitudeNumberTest(double x, double y, double expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberBaseHelper.MaxMagnitudeNumber(x, y)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void MinMagnitudeTest(double x, double y, double expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberBaseHelper.MinMagnitude(x, y)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] + public static void MinMagnitudeNumberTest(double x, double y, double expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberBaseHelper.MinMagnitudeNumber(x, y)); } // diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs index bf5e2261995ee..a236858cff20d 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs @@ -159,55 +159,7 @@ public static void GetTypeCode_Invoke_ReturnsDouble() } [Theory] - [InlineData(double.NaN, double.NaN, double.NaN, 0.0)] - [InlineData(double.NaN, 0.0f, double.NaN, 0.0)] - [InlineData(double.NaN, 1.0f, double.NaN, 0.0)] - [InlineData(double.NaN, 2.7182818284590452, double.NaN, 0.0)] - [InlineData(double.NaN, 10.0, double.NaN, 0.0)] - [InlineData(0.0, 0.0, 0.0, 0.0)] - [InlineData(0.0, 1.0, 1.0, 0.0)] - [InlineData(0.0, 1.5707963267948966, 1.5707963267948966, 0.0)] - [InlineData(0.0, 2.0, 2.0, 0.0)] - [InlineData(0.0, 2.7182818284590452, 2.7182818284590452, 0.0)] - [InlineData(0.0, 3.0, 3.0, 0.0)] - [InlineData(0.0, 10.0, 10.0, 0.0)] - [InlineData(1.0, 1.0, 1.4142135623730950, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.0, 1e+10, 1e+10, 0.0)] // dotnet/runtime#75651 - [InlineData(1.0, 1e+20, 1e+20, 0.0)] // dotnet/runtime#75651 - [InlineData(2.7182818284590452, 0.31830988618379067, 2.7368553638387594, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (1 / pi) - [InlineData(2.7182818284590452, 0.43429448190325183, 2.7527563996732919, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (log10(e)) - [InlineData(2.7182818284590452, 0.63661977236758134, 2.7918346715914253, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (2 / pi) - [InlineData(2.7182818284590452, 0.69314718055994531, 2.8052645352709344, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (ln(2)) - [InlineData(2.7182818284590452, 0.70710678118654752, 2.8087463571726533, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (1 / sqrt(2)) - [InlineData(2.7182818284590452, 0.78539816339744831, 2.8294710413783590, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (pi / 4) - [InlineData(2.7182818284590452, 1.0, 2.8963867315900082, CrossPlatformMachineEpsilon * 10)] // x: (e) - [InlineData(2.7182818284590452, 1.1283791670955126, 2.9431778138036127, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (2 / sqrt(pi)) - [InlineData(2.7182818284590452, 1.4142135623730950, 3.0641566701020120, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (sqrt(2)) - [InlineData(2.7182818284590452, 1.4426950408889634, 3.0774055761202907, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (log2(e)) - [InlineData(2.7182818284590452, 1.5707963267948966, 3.1394995141268918, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (pi / 2) - [InlineData(2.7182818284590452, 2.3025850929940457, 3.5624365551415857, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (ln(10)) - [InlineData(2.7182818284590452, 2.7182818284590452, 3.8442310281591168, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (e) - [InlineData(2.7182818284590452, 3.1415926535897932, 4.1543544023133136, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (pi) - [InlineData(10.0, 0.31830988618379067, 10.005064776584025, CrossPlatformMachineEpsilon * 100)] // y: (1 / pi) - [InlineData(10.0, 0.43429448190325183, 10.009426142242702, CrossPlatformMachineEpsilon * 100)] // y: (log10(e)) - [InlineData(10.0, 0.63661977236758134, 10.020243746265325, CrossPlatformMachineEpsilon * 100)] // y: (2 / pi) - [InlineData(10.0, 0.69314718055994531, 10.023993865417028, CrossPlatformMachineEpsilon * 100)] // y: (ln(2)) - [InlineData(10.0, 0.70710678118654752, 10.024968827881711, CrossPlatformMachineEpsilon * 100)] // y: (1 / sqrt(2)) - [InlineData(10.0, 0.78539816339744831, 10.030795096853892, CrossPlatformMachineEpsilon * 100)] // y: (pi / 4) - [InlineData(10.0, 1.0, 10.049875621120890, CrossPlatformMachineEpsilon * 100)] // - [InlineData(10.0, 1.1283791670955126, 10.063460614755501, CrossPlatformMachineEpsilon * 100)] // y: (2 / sqrt(pi)) - [InlineData(10.0, 1.4142135623730950, 10.099504938362078, CrossPlatformMachineEpsilon * 100)] // y: (sqrt(2)) - [InlineData(10.0, 1.4426950408889634, 10.103532500121213, CrossPlatformMachineEpsilon * 100)] // y: (log2(e)) - [InlineData(10.0, 1.5707963267948966, 10.122618292728040, CrossPlatformMachineEpsilon * 100)] // y: (pi / 2) - [InlineData(10.0, 2.3025850929940457, 10.261671311754163, CrossPlatformMachineEpsilon * 100)] // y: (ln(10)) - [InlineData(10.0, 2.7182818284590452, 10.362869105558106, CrossPlatformMachineEpsilon * 100)] // y: (e) - [InlineData(10.0, 3.1415926535897932, 10.481870272097884, CrossPlatformMachineEpsilon * 100)] // y: (pi) - [InlineData(double.PositiveInfinity, double.NaN, double.PositiveInfinity, 0.0)] - [InlineData(double.PositiveInfinity, 0.0, double.PositiveInfinity, 0.0)] - [InlineData(double.PositiveInfinity, 1.0, double.PositiveInfinity, 0.0)] - [InlineData(double.PositiveInfinity, 2.7182818284590452, double.PositiveInfinity, 0.0)] - [InlineData(double.PositiveInfinity, 10.0, double.PositiveInfinity, 0.0)] - [InlineData(double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, 0.0)] + [MemberData(nameof(GenericMathTestMemberData.HypotDouble), MemberType = typeof(GenericMathTestMemberData))] public static void Hypot(double x, double y, double expectedResult, double allowedVariance) { AssertExtensions.Equal(expectedResult, double.Hypot(-x, -y), allowedVariance); @@ -241,19 +193,7 @@ public static void IsInfinity(double d, bool expected) } [Theory] - [InlineData(double.NegativeInfinity, false)] // Negative Infinity - [InlineData(double.MinValue, false)] // Min Negative Normal - [InlineData(-2.2250738585072014E-308, false)] // Max Negative Normal - [InlineData(-2.2250738585072009E-308, false)] // Min Negative Subnormal - [InlineData(-double.Epsilon, false)] // Max Negative Subnormal (Negative Epsilon) - [InlineData(-0.0, false)] // Negative Zero - [InlineData(double.NaN, true)] // NaN - [InlineData(0.0, false)] // Positive Zero - [InlineData(double.Epsilon, false)] // Min Positive Subnormal (Positive Epsilon) - [InlineData(2.2250738585072009E-308, false)] // Max Positive Subnormal - [InlineData(2.2250738585072014E-308, false)] // Min Positive Normal - [InlineData(double.MaxValue, false)] // Max Positive Normal - [InlineData(double.PositiveInfinity, false)] // Positive Infinity + [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] public static void IsNaN(double d, bool expected) { Assert.Equal(expected, double.IsNaN(d)); @@ -279,19 +219,7 @@ public static void IsNegativeInfinity(double d, bool expected) } [Theory] - [InlineData(double.NegativeInfinity, false)] // Negative Infinity - [InlineData(double.MinValue, false)] // Min Negative Normal - [InlineData(-2.2250738585072014E-308, false)] // Max Negative Normal - [InlineData(-2.2250738585072009E-308, false)] // Min Negative Subnormal - [InlineData(-double.Epsilon, false)] // Max Negative Subnormal (Negative Epsilon) - [InlineData(-0.0, false)] // Negative Zero - [InlineData(double.NaN, false)] // NaN - [InlineData(0.0, false)] // Positive Zero - [InlineData(double.Epsilon, false)] // Min Positive Subnormal (Positive Epsilon) - [InlineData(2.2250738585072009E-308, false)] // Max Positive Subnormal - [InlineData(2.2250738585072014E-308, false)] // Min Positive Normal - [InlineData(double.MaxValue, false)] // Max Positive Normal - [InlineData(double.PositiveInfinity, true)] // Positive Infinity + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] public static void IsPositiveInfinity(double d, bool expected) { Assert.Equal(expected, double.IsPositiveInfinity(d)); @@ -935,19 +863,7 @@ public static void IsFinite(double d, bool expected) } [Theory] - [InlineData(double.NegativeInfinity, true)] // Negative Infinity - [InlineData(double.MinValue, true)] // Min Negative Normal - [InlineData(-2.2250738585072014E-308, true)] // Max Negative Normal - [InlineData(-2.2250738585072009E-308, true)] // Min Negative Subnormal - [InlineData(-4.94065645841247E-324, true)] // Max Negative Subnormal - [InlineData(-0.0, true)] // Negative Zero - [InlineData(double.NaN, true)] // NaN - [InlineData(0.0, false)] // Positive Zero - [InlineData(4.94065645841247E-324, false)] // Min Positive Subnormal - [InlineData(2.2250738585072009E-308, false)] // Max Positive Subnormal - [InlineData(2.2250738585072014E-308, false)] // Min Positive Normal - [InlineData(double.MaxValue, false)] // Max Positive Normal - [InlineData(double.PositiveInfinity, false)] // Positive Infinity + [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] public static void IsNegative(double d, bool expected) { Assert.Equal(expected, double.IsNegative(d)); @@ -1060,92 +976,28 @@ public static void TestNegativeNumberParsingWithHyphen() } [Theory] - [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity)] - [InlineData(double.MinValue, double.MaxValue, double.MaxValue)] - [InlineData(double.MaxValue, double.MinValue, double.MaxValue)] - [InlineData(double.NaN, double.NaN, double.NaN)] - [InlineData(double.NaN, 1.0, 1.0)] - [InlineData(1.0, double.NaN, 1.0)] - [InlineData(double.PositiveInfinity, double.NaN, double.PositiveInfinity)] - [InlineData(double.NegativeInfinity, double.NaN, double.NegativeInfinity)] - [InlineData(double.NaN, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(double.NaN, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData(-0.0, 0.0, 0.0)] - [InlineData(0.0, -0.0, 0.0)] - [InlineData(2.0, -3.0, -3.0)] - [InlineData(-3.0, 2.0, -3.0)] - [InlineData(3.0, -2.0, 3.0)] - [InlineData(-2.0, 3.0, 3.0)] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] public static void MaxMagnitudeNumberTest(double x, double y, double expectedResult) { AssertExtensions.Equal(expectedResult, double.MaxMagnitudeNumber(x, y), 0.0); } [Theory] - [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity)] - [InlineData(double.MinValue, double.MaxValue, double.MaxValue)] - [InlineData(double.MaxValue, double.MinValue, double.MaxValue)] - [InlineData(double.NaN, double.NaN, double.NaN)] - [InlineData(double.NaN, 1.0, 1.0)] - [InlineData(1.0, double.NaN, 1.0)] - [InlineData(double.PositiveInfinity, double.NaN, double.PositiveInfinity)] - [InlineData(double.NegativeInfinity, double.NaN, double.NegativeInfinity)] - [InlineData(double.NaN, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(double.NaN, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData(-0.0, 0.0, 0.0)] - [InlineData(0.0, -0.0, 0.0)] - [InlineData(2.0, -3.0, 2.0)] - [InlineData(-3.0, 2.0, 2.0)] - [InlineData(3.0, -2.0, 3.0)] - [InlineData(-2.0, 3.0, 3.0)] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberDouble), MemberType = typeof(GenericMathTestMemberData))] public static void MaxNumberTest(double x, double y, double expectedResult) { AssertExtensions.Equal(expectedResult, double.MaxNumber(x, y), 0.0); } [Theory] - [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData(double.MinValue, double.MaxValue, double.MinValue)] - [InlineData(double.MaxValue, double.MinValue, double.MinValue)] - [InlineData(double.NaN, double.NaN, double.NaN)] - [InlineData(double.NaN, 1.0, 1.0)] - [InlineData(1.0, double.NaN, 1.0)] - [InlineData(double.PositiveInfinity, double.NaN, double.PositiveInfinity)] - [InlineData(double.NegativeInfinity, double.NaN, double.NegativeInfinity)] - [InlineData(double.NaN, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(double.NaN, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData(-0.0, 0.0, -0.0)] - [InlineData(0.0, -0.0, -0.0)] - [InlineData(2.0, -3.0, 2.0)] - [InlineData(-3.0, 2.0, 2.0)] - [InlineData(3.0, -2.0, -2.0)] - [InlineData(-2.0, 3.0, -2.0)] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberDouble), MemberType = typeof(GenericMathTestMemberData))] public static void MinMagnitudeNumberTest(double x, double y, double expectedResult) { AssertExtensions.Equal(expectedResult, double.MinMagnitudeNumber(x, y), 0.0); } [Theory] - [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData(double.MinValue, double.MaxValue, double.MinValue)] - [InlineData(double.MaxValue, double.MinValue, double.MinValue)] - [InlineData(double.NaN, double.NaN, double.NaN)] - [InlineData(double.NaN, 1.0, 1.0)] - [InlineData(1.0, double.NaN, 1.0)] - [InlineData(double.PositiveInfinity, double.NaN, double.PositiveInfinity)] - [InlineData(double.NegativeInfinity, double.NaN, double.NegativeInfinity)] - [InlineData(double.NaN, double.PositiveInfinity, double.PositiveInfinity)] - [InlineData(double.NaN, double.NegativeInfinity, double.NegativeInfinity)] - [InlineData(-0.0, 0.0, -0.0)] - [InlineData(0.0, -0.0, -0.0)] - [InlineData(2.0, -3.0, -3.0)] - [InlineData(-3.0, 2.0, -3.0)] - [InlineData(3.0, -2.0, -2.0)] - [InlineData(-2.0, 3.0, -2.0)] + [MemberData(nameof(GenericMathTestMemberData.MinNumberDouble), MemberType = typeof(GenericMathTestMemberData))] public static void MinNumberTest(double x, double y, double expectedResult) { AssertExtensions.Equal(expectedResult, double.MinNumber(x, y), 0.0); @@ -1662,37 +1514,7 @@ public static void TanPiTest(double value, double expectedResult, double allowed } [Theory] - [InlineData(double.NegativeInfinity, double.NegativeInfinity, 0.5, double.NegativeInfinity)] - [InlineData(double.NegativeInfinity, double.NaN, 0.5, double.NaN)] - [InlineData(double.NegativeInfinity, double.PositiveInfinity, 0.5, double.NaN)] - [InlineData(double.NegativeInfinity, 0.0, 0.5, double.NegativeInfinity)] - [InlineData(double.NegativeInfinity, 1.0, 0.5, double.NegativeInfinity)] - [InlineData(double.NaN, double.NegativeInfinity, 0.5, double.NaN)] - [InlineData(double.NaN, double.NaN, 0.5, double.NaN)] - [InlineData(double.NaN, double.PositiveInfinity, 0.5, double.NaN)] - [InlineData(double.NaN, 0.0, 0.5, double.NaN)] - [InlineData(double.NaN, 1.0, 0.5, double.NaN)] - [InlineData(double.PositiveInfinity, double.NegativeInfinity, 0.5, double.NaN)] - [InlineData(double.PositiveInfinity, double.NaN, 0.5, double.NaN)] - [InlineData(double.PositiveInfinity, double.PositiveInfinity, 0.5, double.PositiveInfinity)] - [InlineData(double.PositiveInfinity, 0.0, 0.5, double.PositiveInfinity)] - [InlineData(double.PositiveInfinity, 1.0, 0.5, double.PositiveInfinity)] - [InlineData(1.0, 3.0, 0.0, 1.0)] - [InlineData(1.0, 3.0, 0.5, 2.0)] - [InlineData(1.0, 3.0, 1.0, 3.0)] - [InlineData(1.0, 3.0, 2.0, 5.0)] - [InlineData(2.0, 4.0, 0.0, 2.0)] - [InlineData(2.0, 4.0, 0.5, 3.0)] - [InlineData(2.0, 4.0, 1.0, 4.0)] - [InlineData(2.0, 4.0, 2.0, 6.0)] - [InlineData(3.0, 1.0, 0.0, 3.0)] - [InlineData(3.0, 1.0, 0.5, 2.0)] - [InlineData(3.0, 1.0, 1.0, 1.0)] - [InlineData(3.0, 1.0, 2.0, -1.0)] - [InlineData(4.0, 2.0, 0.0, 4.0)] - [InlineData(4.0, 2.0, 0.5, 3.0)] - [InlineData(4.0, 2.0, 1.0, 2.0)] - [InlineData(4.0, 2.0, 2.0, 0.0)] + [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] public static void LerpTest(double value1, double value2, double amount, double expectedResult) { AssertExtensions.Equal(+expectedResult, double.Lerp(+value1, +value2, amount), 0); @@ -1700,29 +1522,7 @@ public static void LerpTest(double value1, double value2, double amount, double } [Theory] - [InlineData(double.NaN, double.NaN, 0.0)] - [InlineData(0.0, 0.0, 0.0)] - [InlineData(0.31830988618379067, 0.005555555555555556, CrossPlatformMachineEpsilon)] // value: (1 / pi) - [InlineData(0.43429448190325183, 0.007579868632454674, CrossPlatformMachineEpsilon)] // value: (log10(e)) - [InlineData(0.5, 0.008726646259971648, CrossPlatformMachineEpsilon)] - [InlineData(0.63661977236758134, 0.011111111111111112, CrossPlatformMachineEpsilon)] // value: (2 / pi) - [InlineData(0.69314718055994531, 0.01209770050168668, CrossPlatformMachineEpsilon)] // value: (ln(2)) - [InlineData(0.70710678118654752, 0.012341341494884351, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) - [InlineData(0.78539816339744831, 0.013707783890401885, CrossPlatformMachineEpsilon)] // value: (pi / 4) - [InlineData(1.0, 0.017453292519943295, CrossPlatformMachineEpsilon)] - [InlineData(1.1283791670955126, 0.019693931676727953, CrossPlatformMachineEpsilon)] // value: (2 / sqrt(pi)) - [InlineData(1.4142135623730950, 0.024682682989768702, CrossPlatformMachineEpsilon)] // value: (sqrt(2)) - [InlineData(1.4426950408889634, 0.02517977856570663, CrossPlatformMachineEpsilon)] // value: (log2(e)) - [InlineData(1.5, 0.02617993877991494, CrossPlatformMachineEpsilon)] - [InlineData(1.5707963267948966, 0.02741556778080377, CrossPlatformMachineEpsilon)] // value: (pi / 2) - [InlineData(2.0, 0.03490658503988659, CrossPlatformMachineEpsilon)] - [InlineData(2.3025850929940457, 0.040187691180085916, CrossPlatformMachineEpsilon)] // value: (ln(10)) - [InlineData(2.5, 0.04363323129985824, CrossPlatformMachineEpsilon)] - [InlineData(2.7182818284590452, 0.047442967903742035, CrossPlatformMachineEpsilon)] // value: (e) - [InlineData(3.0, 0.05235987755982988, CrossPlatformMachineEpsilon)] - [InlineData(3.1415926535897932, 0.05483113556160754, CrossPlatformMachineEpsilon)] // value: (pi) - [InlineData(3.5, 0.061086523819801536, CrossPlatformMachineEpsilon)] - [InlineData(double.PositiveInfinity, double.PositiveInfinity, 0.0)] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansDouble), MemberType = typeof(GenericMathTestMemberData))] public static void DegreesToRadiansTest(double value, double expectedResult, double allowedVariance) { AssertExtensions.Equal(-expectedResult, double.DegreesToRadians(-value), allowedVariance); @@ -1730,29 +1530,7 @@ public static void DegreesToRadiansTest(double value, double expectedResult, dou } [Theory] - [InlineData(double.NaN, double.NaN, 0.0)] - [InlineData(0.0, 0.0, 0.0)] - [InlineData(0.0055555555555555567, 0.3183098861837906, CrossPlatformMachineEpsilon)] // expected: (1 / pi) - [InlineData(0.0075798686324546743, 0.4342944819032518, CrossPlatformMachineEpsilon)] // expected: (log10(e)) - [InlineData(0.008726646259971648, 0.5, CrossPlatformMachineEpsilon)] - [InlineData(0.0111111111111111124, 0.6366197723675813, CrossPlatformMachineEpsilon)] // expected: (2 / pi) - [InlineData(0.0120977005016866801, 0.6931471805599453, CrossPlatformMachineEpsilon)] // expected: (ln(2)) - [InlineData(0.0123413414948843512, 0.7071067811865475, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) - [InlineData(0.0137077838904018851, 0.7853981633974483, CrossPlatformMachineEpsilon)] // expected: (pi / 4) - [InlineData(0.017453292519943295, 1.0, CrossPlatformMachineEpsilon)] - [InlineData(0.019693931676727953, 1.1283791670955126, CrossPlatformMachineEpsilon)] // expected: (2 / sqrt(pi)) - [InlineData(0.024682682989768702, 1.4142135623730950, CrossPlatformMachineEpsilon)] // expected: (sqrt(2)) - [InlineData(0.025179778565706630, 1.4426950408889634, CrossPlatformMachineEpsilon)] // expected: (log2(e)) - [InlineData(0.026179938779914940, 1.5, CrossPlatformMachineEpsilon)] - [InlineData(0.027415567780803770, 1.5707963267948966, CrossPlatformMachineEpsilon)] // expected: (pi / 2) - [InlineData(0.034906585039886590, 2.0, CrossPlatformMachineEpsilon)] - [InlineData(0.040187691180085916, 2.3025850929940457, CrossPlatformMachineEpsilon)] // expected: (ln(10)) - [InlineData(0.043633231299858240, 2.5, CrossPlatformMachineEpsilon)] - [InlineData(0.047442967903742035, 2.7182818284590452, CrossPlatformMachineEpsilon)] // expected: (e) - [InlineData(0.052359877559829880, 3.0, CrossPlatformMachineEpsilon)] - [InlineData(0.054831135561607540, 3.1415926535897932, CrossPlatformMachineEpsilon)] // expected: (pi) - [InlineData(0.061086523819801536, 3.5, CrossPlatformMachineEpsilon)] - [InlineData(double.PositiveInfinity, double.PositiveInfinity, 0.0)] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesDouble), MemberType = typeof(GenericMathTestMemberData))] public static void RadiansToDegreesTest(double value, double expectedResult, double allowedVariance) { AssertExtensions.Equal(-expectedResult, double.RadiansToDegrees(-value), allowedVariance); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs index 21a4ba2cd77a1..063ad2d9cfe24 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs @@ -117,24 +117,11 @@ public static void IsPow2Test() Assert.False(BinaryNumberHelper.IsPow2(float.PositiveInfinity)); } - [Fact] - public static void Log2Test() - { - AssertBitwiseEqual(float.NaN, BinaryNumberHelper.Log2(float.NegativeInfinity)); - AssertBitwiseEqual(float.NaN, BinaryNumberHelper.Log2(float.MinValue)); - AssertBitwiseEqual(float.NaN, BinaryNumberHelper.Log2(-1.0f)); - AssertBitwiseEqual(float.NaN, BinaryNumberHelper.Log2(-MinNormal)); - AssertBitwiseEqual(float.NaN, BinaryNumberHelper.Log2(-MaxSubnormal)); - AssertBitwiseEqual(float.NaN, BinaryNumberHelper.Log2(-float.Epsilon)); - AssertBitwiseEqual(float.NegativeInfinity, BinaryNumberHelper.Log2(-0.0f)); - AssertBitwiseEqual(float.NaN, BinaryNumberHelper.Log2(float.NaN)); - AssertBitwiseEqual(float.NegativeInfinity, BinaryNumberHelper.Log2(0.0f)); - AssertBitwiseEqual(-149.0f, BinaryNumberHelper.Log2(float.Epsilon)); - AssertBitwiseEqual(-126.0f, BinaryNumberHelper.Log2(MaxSubnormal)); - AssertBitwiseEqual(-126.0f, BinaryNumberHelper.Log2(MinNormal)); - AssertBitwiseEqual(0.0f, BinaryNumberHelper.Log2(1.0f)); - AssertBitwiseEqual(128.0f, BinaryNumberHelper.Log2(float.MaxValue)); - AssertBitwiseEqual(float.PositiveInfinity, BinaryNumberHelper.Log2(float.PositiveInfinity)); + [Theory] + [MemberData(nameof(GenericMathTestMemberData.Log2Single), MemberType = typeof(GenericMathTestMemberData))] + public static void Log2Test(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, BinaryNumberHelper.Log2(value), allowedVariance); } // @@ -1029,104 +1016,39 @@ public static void op_CheckedMultiplyTest() // INumber // - [Fact] - public static void ClampTest() - { - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(float.NegativeInfinity, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(float.MinValue, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(-1.0f, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(-MinNormal, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(-MaxSubnormal, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(-float.Epsilon, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(-0.0f, 1.0f, 63.0f)); - AssertBitwiseEqual(float.NaN, NumberHelper.Clamp(float.NaN, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(0.0f, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(float.Epsilon, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(MaxSubnormal, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(MinNormal, 1.0f, 63.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Clamp(1.0f, 1.0f, 63.0f)); - AssertBitwiseEqual(63.0f, NumberHelper.Clamp(float.MaxValue, 1.0f, 63.0f)); - AssertBitwiseEqual(63.0f, NumberHelper.Clamp(float.PositiveInfinity, 1.0f, 63.0f)); - } - - [Fact] - public static void MaxTest() - { - AssertBitwiseEqual(1.0f, NumberHelper.Max(float.NegativeInfinity, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(float.MinValue, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(-1.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(-MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(-MaxSubnormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(-float.Epsilon, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(-0.0f, 1.0f)); - AssertBitwiseEqual(float.NaN, NumberHelper.Max(float.NaN, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(0.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(float.Epsilon, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(MaxSubnormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Max(1.0f, 1.0f)); - AssertBitwiseEqual(float.MaxValue, NumberHelper.Max(float.MaxValue, 1.0f)); - AssertBitwiseEqual(float.PositiveInfinity, NumberHelper.Max(float.PositiveInfinity, 1.0f)); - } - - [Fact] - public static void MaxNumberTest() - { - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(float.NegativeInfinity, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(float.MinValue, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(-1.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(-MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(-MaxSubnormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(-float.Epsilon, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(-0.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(float.NaN, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(0.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(float.Epsilon, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(MaxSubnormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MaxNumber(1.0f, 1.0f)); - AssertBitwiseEqual(float.MaxValue, NumberHelper.MaxNumber(float.MaxValue, 1.0f)); - AssertBitwiseEqual(float.PositiveInfinity, NumberHelper.MaxNumber(float.PositiveInfinity, 1.0f)); - } - - [Fact] - public static void MinTest() - { - AssertBitwiseEqual(float.NegativeInfinity, NumberHelper.Min(float.NegativeInfinity, 1.0f)); - AssertBitwiseEqual(float.MinValue, NumberHelper.Min(float.MinValue, 1.0f)); - AssertBitwiseEqual(-1.0f, NumberHelper.Min(-1.0f, 1.0f)); - AssertBitwiseEqual(-MinNormal, NumberHelper.Min(-MinNormal, 1.0f)); - AssertBitwiseEqual(-MaxSubnormal, NumberHelper.Min(-MaxSubnormal, 1.0f)); - AssertBitwiseEqual(-float.Epsilon, NumberHelper.Min(-float.Epsilon, 1.0f)); - AssertBitwiseEqual(-0.0f, NumberHelper.Min(-0.0f, 1.0f)); - AssertBitwiseEqual(float.NaN, NumberHelper.Min(float.NaN, 1.0f)); - AssertBitwiseEqual(0.0f, NumberHelper.Min(0.0f, 1.0f)); - AssertBitwiseEqual(float.Epsilon, NumberHelper.Min(float.Epsilon, 1.0f)); - AssertBitwiseEqual(MaxSubnormal, NumberHelper.Min(MaxSubnormal, 1.0f)); - AssertBitwiseEqual(MinNormal, NumberHelper.Min(MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Min(1.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Min(float.MaxValue, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.Min(float.PositiveInfinity, 1.0f)); - } - - [Fact] - public static void MinNumberTest() - { - AssertBitwiseEqual(float.NegativeInfinity, NumberHelper.MinNumber(float.NegativeInfinity, 1.0f)); - AssertBitwiseEqual(float.MinValue, NumberHelper.MinNumber(float.MinValue, 1.0f)); - AssertBitwiseEqual(-1.0f, NumberHelper.MinNumber(-1.0f, 1.0f)); - AssertBitwiseEqual(-MinNormal, NumberHelper.MinNumber(-MinNormal, 1.0f)); - AssertBitwiseEqual(-MaxSubnormal, NumberHelper.MinNumber(-MaxSubnormal, 1.0f)); - AssertBitwiseEqual(-float.Epsilon, NumberHelper.MinNumber(-float.Epsilon, 1.0f)); - AssertBitwiseEqual(-0.0f, NumberHelper.MinNumber(-0.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MinNumber(float.NaN, 1.0f)); - AssertBitwiseEqual(0.0f, NumberHelper.MinNumber(0.0f, 1.0f)); - AssertBitwiseEqual(float.Epsilon, NumberHelper.MinNumber(float.Epsilon, 1.0f)); - AssertBitwiseEqual(MaxSubnormal, NumberHelper.MinNumber(MaxSubnormal, 1.0f)); - AssertBitwiseEqual(MinNormal, NumberHelper.MinNumber(MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MinNumber(1.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MinNumber(float.MaxValue, 1.0f)); - AssertBitwiseEqual(1.0f, NumberHelper.MinNumber(float.PositiveInfinity, 1.0f)); + [Theory] + [MemberData(nameof(GenericMathTestMemberData.ClampSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void ClampTest(float x, float min, float max, float expectedResult) + { + AssertBitwiseEqual(expectedResult, NumberHelper.Clamp(x, min, max)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void MaxTest(float x, float y, float expectedResult) + { + AssertBitwiseEqual(expectedResult, NumberHelper.Max(x, y)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void MaxNumberTest(float x, float y, float expectedResult) + { + AssertBitwiseEqual(expectedResult, NumberHelper.MaxNumber(x, y)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void MinTest(float x, float y, float expectedResult) + { + AssertBitwiseEqual(expectedResult, NumberHelper.Min(x, y)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void MinNumberTest(float x, float y, float expectedResult) + { + AssertBitwiseEqual(expectedResult, NumberHelper.MinNumber(x, y)); } [Fact] @@ -2204,44 +2126,18 @@ public static void IsIntegerTest() Assert.False(NumberBaseHelper.IsInteger(float.PositiveInfinity)); } - [Fact] - public static void IsNaNTest() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void IsNaNTest(float value, bool expectedResult) { - Assert.False(NumberBaseHelper.IsNaN(float.NegativeInfinity)); - Assert.False(NumberBaseHelper.IsNaN(float.MinValue)); - Assert.False(NumberBaseHelper.IsNaN(-1.0f)); - Assert.False(NumberBaseHelper.IsNaN(-MinNormal)); - Assert.False(NumberBaseHelper.IsNaN(-MaxSubnormal)); - Assert.False(NumberBaseHelper.IsNaN(-float.Epsilon)); - Assert.False(NumberBaseHelper.IsNaN(-0.0f)); - Assert.True(NumberBaseHelper.IsNaN(float.NaN)); - Assert.False(NumberBaseHelper.IsNaN(0.0f)); - Assert.False(NumberBaseHelper.IsNaN(float.Epsilon)); - Assert.False(NumberBaseHelper.IsNaN(MaxSubnormal)); - Assert.False(NumberBaseHelper.IsNaN(MinNormal)); - Assert.False(NumberBaseHelper.IsNaN(1.0f)); - Assert.False(NumberBaseHelper.IsNaN(float.MaxValue)); - Assert.False(NumberBaseHelper.IsNaN(float.PositiveInfinity)); + Assert.Equal(expectedResult, NumberBaseHelper.IsNaN(value)); } - [Fact] - public static void IsNegativeTest() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void IsNegativeTest(float value, bool expectedResult) { - Assert.True(NumberBaseHelper.IsNegative(float.NegativeInfinity)); - Assert.True(NumberBaseHelper.IsNegative(float.MinValue)); - Assert.True(NumberBaseHelper.IsNegative(-1.0f)); - Assert.True(NumberBaseHelper.IsNegative(-MinNormal)); - Assert.True(NumberBaseHelper.IsNegative(-MaxSubnormal)); - Assert.True(NumberBaseHelper.IsNegative(-float.Epsilon)); - Assert.True(NumberBaseHelper.IsNegative(-0.0f)); - Assert.True(NumberBaseHelper.IsNegative(float.NaN)); - Assert.False(NumberBaseHelper.IsNegative(0.0f)); - Assert.False(NumberBaseHelper.IsNegative(float.Epsilon)); - Assert.False(NumberBaseHelper.IsNegative(MaxSubnormal)); - Assert.False(NumberBaseHelper.IsNegative(MinNormal)); - Assert.False(NumberBaseHelper.IsNegative(1.0f)); - Assert.False(NumberBaseHelper.IsNegative(float.MaxValue)); - Assert.False(NumberBaseHelper.IsNegative(float.PositiveInfinity)); + Assert.Equal(expectedResult, NumberBaseHelper.IsNegative(value)); } [Fact] @@ -2304,44 +2200,18 @@ public static void IsOddIntegerTest() Assert.False(NumberBaseHelper.IsOddInteger(float.PositiveInfinity)); } - [Fact] - public static void IsPositiveTest() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void IsPositiveTest(float value, bool expectedResult) { - Assert.False(NumberBaseHelper.IsPositive(float.NegativeInfinity)); - Assert.False(NumberBaseHelper.IsPositive(float.MinValue)); - Assert.False(NumberBaseHelper.IsPositive(-1.0f)); - Assert.False(NumberBaseHelper.IsPositive(-MinNormal)); - Assert.False(NumberBaseHelper.IsPositive(-MaxSubnormal)); - Assert.False(NumberBaseHelper.IsPositive(-float.Epsilon)); - Assert.False(NumberBaseHelper.IsPositive(-0.0f)); - Assert.False(NumberBaseHelper.IsPositive(float.NaN)); - Assert.True(NumberBaseHelper.IsPositive(0.0f)); - Assert.True(NumberBaseHelper.IsPositive(float.Epsilon)); - Assert.True(NumberBaseHelper.IsPositive(MaxSubnormal)); - Assert.True(NumberBaseHelper.IsPositive(MinNormal)); - Assert.True(NumberBaseHelper.IsPositive(1.0f)); - Assert.True(NumberBaseHelper.IsPositive(float.MaxValue)); - Assert.True(NumberBaseHelper.IsPositive(float.PositiveInfinity)); + Assert.Equal(expectedResult, NumberBaseHelper.IsPositive(value)); } - [Fact] - public static void IsPositiveInfinityTest() + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] + public static void IsPositiveInfinityTest(float value, bool expectedResult) { - Assert.False(NumberBaseHelper.IsPositiveInfinity(float.NegativeInfinity)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(float.MinValue)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-1.0f)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-MinNormal)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-MaxSubnormal)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-float.Epsilon)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(-0.0f)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(float.NaN)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(0.0f)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(float.Epsilon)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(MaxSubnormal)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(MinNormal)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(1.0f)); - Assert.False(NumberBaseHelper.IsPositiveInfinity(float.MaxValue)); - Assert.True(NumberBaseHelper.IsPositiveInfinity(float.PositiveInfinity)); + Assert.Equal(expectedResult, NumberBaseHelper.IsPositiveInfinity(value)); } [Fact] @@ -2384,104 +2254,39 @@ public static void IsSubnormalTest() Assert.False(NumberBaseHelper.IsSubnormal(float.PositiveInfinity)); } - [Fact] - public static void IsZeroTest() - { - Assert.False(NumberBaseHelper.IsZero(float.NegativeInfinity)); - Assert.False(NumberBaseHelper.IsZero(float.MinValue)); - Assert.False(NumberBaseHelper.IsZero(-1.0f)); - Assert.False(NumberBaseHelper.IsZero(-MinNormal)); - Assert.False(NumberBaseHelper.IsZero(-MaxSubnormal)); - Assert.False(NumberBaseHelper.IsZero(-float.Epsilon)); - Assert.True(NumberBaseHelper.IsZero(-0.0f)); - Assert.False(NumberBaseHelper.IsZero(float.NaN)); - Assert.True(NumberBaseHelper.IsZero(0.0f)); - Assert.False(NumberBaseHelper.IsZero(float.Epsilon)); - Assert.False(NumberBaseHelper.IsZero(MaxSubnormal)); - Assert.False(NumberBaseHelper.IsZero(MinNormal)); - Assert.False(NumberBaseHelper.IsZero(1.0f)); - Assert.False(NumberBaseHelper.IsZero(float.MaxValue)); - Assert.False(NumberBaseHelper.IsZero(float.PositiveInfinity)); - } - - [Fact] - public static void MaxMagnitudeTest() - { - AssertBitwiseEqual(float.NegativeInfinity, NumberBaseHelper.MaxMagnitude(float.NegativeInfinity, 1.0f)); - AssertBitwiseEqual(float.MinValue, NumberBaseHelper.MaxMagnitude(float.MinValue, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(-1.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(-MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(-MaxSubnormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(-float.Epsilon, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(-0.0f, 1.0f)); - AssertBitwiseEqual(float.NaN, NumberBaseHelper.MaxMagnitude(float.NaN, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(0.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(float.Epsilon, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(MaxSubnormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitude(1.0f, 1.0f)); - AssertBitwiseEqual(float.MaxValue, NumberBaseHelper.MaxMagnitude(float.MaxValue, 1.0f)); - AssertBitwiseEqual(float.PositiveInfinity, NumberBaseHelper.MaxMagnitude(float.PositiveInfinity, 1.0f)); - } - - [Fact] - public static void MaxMagnitudeNumberTest() - { - AssertBitwiseEqual(float.NegativeInfinity, NumberBaseHelper.MaxMagnitudeNumber(float.NegativeInfinity, 1.0f)); - AssertBitwiseEqual(float.MinValue, NumberBaseHelper.MaxMagnitudeNumber(float.MinValue, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(-1.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(-MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(-MaxSubnormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(-float.Epsilon, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(-0.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(float.NaN, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(0.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(float.Epsilon, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(MaxSubnormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MaxMagnitudeNumber(1.0f, 1.0f)); - AssertBitwiseEqual(float.MaxValue, NumberBaseHelper.MaxMagnitudeNumber(float.MaxValue, 1.0f)); - AssertBitwiseEqual(float.PositiveInfinity, NumberBaseHelper.MaxMagnitudeNumber(float.PositiveInfinity, 1.0f)); - } - - [Fact] - public static void MinMagnitudeTest() - { - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitude(float.NegativeInfinity, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitude(float.MinValue, 1.0f)); - AssertBitwiseEqual(-1.0f, NumberBaseHelper.MinMagnitude(-1.0f, 1.0f)); - AssertBitwiseEqual(-MinNormal, NumberBaseHelper.MinMagnitude(-MinNormal, 1.0f)); - AssertBitwiseEqual(-MaxSubnormal, NumberBaseHelper.MinMagnitude(-MaxSubnormal, 1.0f)); - AssertBitwiseEqual(-float.Epsilon, NumberBaseHelper.MinMagnitude(-float.Epsilon, 1.0f)); - AssertBitwiseEqual(-0.0f, NumberBaseHelper.MinMagnitude(-0.0f, 1.0f)); - AssertBitwiseEqual(float.NaN, NumberBaseHelper.MinMagnitude(float.NaN, 1.0f)); - AssertBitwiseEqual(0.0f, NumberBaseHelper.MinMagnitude(0.0f, 1.0f)); - AssertBitwiseEqual(float.Epsilon, NumberBaseHelper.MinMagnitude(float.Epsilon, 1.0f)); - AssertBitwiseEqual(MaxSubnormal, NumberBaseHelper.MinMagnitude(MaxSubnormal, 1.0f)); - AssertBitwiseEqual(MinNormal, NumberBaseHelper.MinMagnitude(MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitude(1.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitude(float.MaxValue, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitude(float.PositiveInfinity, 1.0f)); - } - - [Fact] - public static void MinMagnitudeNumberTest() - { - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitudeNumber(float.NegativeInfinity, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitudeNumber(float.MinValue, 1.0f)); - AssertBitwiseEqual(-1.0f, NumberBaseHelper.MinMagnitudeNumber(-1.0f, 1.0f)); - AssertBitwiseEqual(-MinNormal, NumberBaseHelper.MinMagnitudeNumber(-MinNormal, 1.0f)); - AssertBitwiseEqual(-MaxSubnormal, NumberBaseHelper.MinMagnitudeNumber(-MaxSubnormal, 1.0f)); - AssertBitwiseEqual(-float.Epsilon, NumberBaseHelper.MinMagnitudeNumber(-float.Epsilon, 1.0f)); - AssertBitwiseEqual(-0.0f, NumberBaseHelper.MinMagnitudeNumber(-0.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitudeNumber(float.NaN, 1.0f)); - AssertBitwiseEqual(0.0f, NumberBaseHelper.MinMagnitudeNumber(0.0f, 1.0f)); - AssertBitwiseEqual(float.Epsilon, NumberBaseHelper.MinMagnitudeNumber(float.Epsilon, 1.0f)); - AssertBitwiseEqual(MaxSubnormal, NumberBaseHelper.MinMagnitudeNumber(MaxSubnormal, 1.0f)); - AssertBitwiseEqual(MinNormal, NumberBaseHelper.MinMagnitudeNumber(MinNormal, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitudeNumber(1.0f, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitudeNumber(float.MaxValue, 1.0f)); - AssertBitwiseEqual(1.0f, NumberBaseHelper.MinMagnitudeNumber(float.PositiveInfinity, 1.0f)); + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void IsZeroTest(float value, bool expectedResult) + { + Assert.Equal(expectedResult, NumberBaseHelper.IsZero(value)); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void MaxMagnitudeTest(float x, float y, float expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberBaseHelper.MaxMagnitude(x, y), 0.0f); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void MaxMagnitudeNumberTest(float x, float y, float expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberBaseHelper.MaxMagnitudeNumber(x, y), 0.0f); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void MinMagnitudeTest(float x, float y, float expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberBaseHelper.MinMagnitude(x, y), 0.0f); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] + public static void MinMagnitudeNumberTest(float x, float y, float expectedResult) + { + AssertExtensions.Equal(expectedResult, NumberBaseHelper.MinMagnitudeNumber(x, y), 0.0f); } // diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs index 25f8d230c80c0..a7152e5ab00ef 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs @@ -156,55 +156,7 @@ public static void GetTypeCode_Invoke_ReturnsSingle() } [Theory] - [InlineData(float.NaN, float.NaN, float.NaN, 0.0f)] - [InlineData(float.NaN, 0.0f, float.NaN, 0.0f)] - [InlineData(float.NaN, 1.0f, float.NaN, 0.0f)] - [InlineData(float.NaN, 2.71828183f, float.NaN, 0.0f)] - [InlineData(float.NaN, 10.0f, float.NaN, 0.0f)] - [InlineData(0.0f, 0.0f, 0.0f, 0.0f)] - [InlineData(0.0f, 1.0f, 1.0f, 0.0f)] - [InlineData(0.0f, 1.57079633f, 1.57079633f, 0.0f)] - [InlineData(0.0f, 2.0f, 2.0f, 0.0f)] - [InlineData(0.0f, 2.71828183f, 2.71828183f, 0.0f)] - [InlineData(0.0f, 3.0f, 3.0f, 0.0f)] - [InlineData(0.0f, 10.0f, 10.0f, 0.0f)] - [InlineData(1.0f, 1.0f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.0f, 1e+10f, 1e+10f, 0.0)] // dotnet/runtime#75651 - [InlineData(1.0f, 1e+20f, 1e+20f, 0.0)] // dotnet/runtime#75651 - [InlineData(2.71828183f, 0.318309886f, 2.73685536f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (1 / pi) - [InlineData(2.71828183f, 0.434294482f, 2.75275640f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (log10(e)) - [InlineData(2.71828183f, 0.636619772f, 2.79183467f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (2 / pi) - [InlineData(2.71828183f, 0.693147181f, 2.80526454f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (ln(2)) - [InlineData(2.71828183f, 0.707106781f, 2.80874636f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (1 / sqrt(2)) - [InlineData(2.71828183f, 0.785398163f, 2.82947104f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (pi / 4) - [InlineData(2.71828183f, 1.0f, 2.89638673f, CrossPlatformMachineEpsilon * 10)] // x: (e) - [InlineData(2.71828183f, 1.12837917f, 2.94317781f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (2 / sqrt(pi)) - [InlineData(2.71828183f, 1.41421356f, 3.06415667f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (sqrt(2)) - [InlineData(2.71828183f, 1.44269504f, 3.07740558f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (log2(e)) - [InlineData(2.71828183f, 1.57079633f, 3.13949951f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (pi / 2) - [InlineData(2.71828183f, 2.30258509f, 3.56243656f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (ln(10)) - [InlineData(2.71828183f, 2.71828183f, 3.84423103f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (e) - [InlineData(2.71828183f, 3.14159265f, 4.15435440f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (pi) - [InlineData(10.0f, 0.318309886f, 10.0050648f, CrossPlatformMachineEpsilon * 100)] // y: (1 / pi) - [InlineData(10.0f, 0.434294482f, 10.0094261f, CrossPlatformMachineEpsilon * 100)] // y: (log10(e)) - [InlineData(10.0f, 0.636619772f, 10.0202437f, CrossPlatformMachineEpsilon * 100)] // y: (2 / pi) - [InlineData(10.0f, 0.693147181f, 10.0239939f, CrossPlatformMachineEpsilon * 100)] // y: (ln(2)) - [InlineData(10.0f, 0.707106781f, 10.0249688f, CrossPlatformMachineEpsilon * 100)] // y: (1 / sqrt(2)) - [InlineData(10.0f, 0.785398163f, 10.0307951f, CrossPlatformMachineEpsilon * 100)] // y: (pi / 4) - [InlineData(10.0f, 1.0f, 10.0498756f, CrossPlatformMachineEpsilon * 100)] // - [InlineData(10.0f, 1.12837917f, 10.0634606f, CrossPlatformMachineEpsilon * 100)] // y: (2 / sqrt(pi)) - [InlineData(10.0f, 1.41421356f, 10.0995049f, CrossPlatformMachineEpsilon * 100)] // y: (sqrt(2)) - [InlineData(10.0f, 1.44269504f, 10.1035325f, CrossPlatformMachineEpsilon * 100)] // y: (log2(e)) - [InlineData(10.0f, 1.57079633f, 10.1226183f, CrossPlatformMachineEpsilon * 100)] // y: (pi / 2) - [InlineData(10.0f, 2.30258509f, 10.2616713f, CrossPlatformMachineEpsilon * 100)] // y: (ln(10)) - [InlineData(10.0f, 2.71828183f, 10.3628691f, CrossPlatformMachineEpsilon * 100)] // y: (e) - [InlineData(10.0f, 3.14159265f, 10.4818703f, CrossPlatformMachineEpsilon * 100)] // y: (pi) - [InlineData(float.PositiveInfinity, float.NaN, float.PositiveInfinity, 0.0f)] - [InlineData(float.PositiveInfinity, 0.0f, float.PositiveInfinity, 0.0f)] - [InlineData(float.PositiveInfinity, 1.0f, float.PositiveInfinity, 0.0f)] - [InlineData(float.PositiveInfinity, 2.71828183f, float.PositiveInfinity, 0.0f)] - [InlineData(float.PositiveInfinity, 10.0f, float.PositiveInfinity, 0.0f)] - [InlineData(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + [MemberData(nameof(GenericMathTestMemberData.HypotSingle), MemberType = typeof(GenericMathTestMemberData))] public static void Hypot(float x, float y, float expectedResult, float allowedVariance) { AssertExtensions.Equal(expectedResult, float.Hypot(-x, -y), allowedVariance); @@ -238,19 +190,7 @@ public static void IsInfinity(float d, bool expected) } [Theory] - [InlineData(float.NegativeInfinity, false)] // Negative Infinity - [InlineData(float.MinValue, false)] // Min Negative Normal - [InlineData(-1.17549435E-38f, false)] // Max Negative Normal - [InlineData(-1.17549421E-38f, false)] // Min Negative Subnormal - [InlineData(-float.Epsilon, false)] // Max Negative Subnormal (Negative Epsilon) - [InlineData(-0.0f, false)] // Negative Zero - [InlineData(float.NaN, true)] // NaN - [InlineData(0.0f, false)] // Positive Zero - [InlineData(float.Epsilon, false)] // Min Positive Subnormal (Positive Epsilon) - [InlineData(1.17549421E-38f, false)] // Max Positive Subnormal - [InlineData(1.17549435E-38f, false)] // Min Positive Normal - [InlineData(float.MaxValue, false)] // Max Positive Normal - [InlineData(float.PositiveInfinity, false)] // Positive Infinity + [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] public static void IsNaN(float d, bool expected) { Assert.Equal(expected, float.IsNaN(d)); @@ -276,19 +216,7 @@ public static void IsNegativeInfinity(float d, bool expected) } [Theory] - [InlineData(float.NegativeInfinity, false)] // Negative Infinity - [InlineData(float.MinValue, false)] // Min Negative Normal - [InlineData(-1.17549435E-38f, false)] // Max Negative Normal - [InlineData(-1.17549421E-38f, false)] // Min Negative Subnormal - [InlineData(-float.Epsilon, false)] // Max Negative Subnormal (Negative Epsilon) - [InlineData(-0.0f, false)] // Negative Zero - [InlineData(float.NaN, false)] // NaN - [InlineData(0.0f, false)] // Positive Zero - [InlineData(float.Epsilon, false)] // Min Positive Subnormal (Positive Epsilon) - [InlineData(1.17549421E-38f, false)] // Max Positive Subnormal - [InlineData(1.17549435E-38f, false)] // Min Positive Normal - [InlineData(float.MaxValue, false)] // Max Positive Normal - [InlineData(float.PositiveInfinity, true)] // Positive Infinity + [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] public static void IsPositiveInfinity(float d, bool expected) { Assert.Equal(expected, float.IsPositiveInfinity(d)); @@ -856,19 +784,7 @@ public static void IsFinite(float d, bool expected) } [Theory] - [InlineData(float.NegativeInfinity, true)] // Negative Infinity - [InlineData(float.MinValue, true)] // Min Negative Normal - [InlineData(-1.17549435E-38f, true)] // Max Negative Normal - [InlineData(-1.17549421E-38f, true)] // Min Negative Subnormal - [InlineData(-1.401298E-45, true)] // Max Negative Subnormal - [InlineData(-0.0f, true)] // Negative Zero - [InlineData(float.NaN, true)] // NaN - [InlineData(0.0f, false)] // Positive Zero - [InlineData(1.401298E-45, false)] // Min Positive Subnormal - [InlineData(1.17549421E-38f, false)] // Max Positive Subnormal - [InlineData(1.17549435E-38f, false)] // Min Positive Normal - [InlineData(float.MaxValue, false)] // Max Positive Normal - [InlineData(float.PositiveInfinity, false)] // Positive Infinity + [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] public static void IsNegative(float d, bool expected) { Assert.Equal(expected, float.IsNegative(d)); @@ -972,92 +888,28 @@ public static void ToStringRoundtrip_R(float value) } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MaxValue)] - [InlineData(float.MaxValue, float.MinValue, float.MaxValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, 1.0f)] - [InlineData(1.0f, float.NaN, 1.0f)] - [InlineData(float.PositiveInfinity, float.NaN, float.PositiveInfinity)] - [InlineData(float.NegativeInfinity, float.NaN, float.NegativeInfinity)] - [InlineData(float.NaN, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.NaN, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(-0.0f, 0.0f, 0.0f)] - [InlineData(0.0f, -0.0f, 0.0f)] - [InlineData(2.0f, -3.0f, -3.0f)] - [InlineData(-3.0f, 2.0f, -3.0f)] - [InlineData(3.0f, -2.0f, 3.0f)] - [InlineData(-2.0f, 3.0f, 3.0f)] + [MemberData(nameof(GenericMathTestMemberData.MaxMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] public static void MaxMagnitudeNumberTest(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, float.MaxMagnitudeNumber(x, y), 0.0f); } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MaxValue)] - [InlineData(float.MaxValue, float.MinValue, float.MaxValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, 1.0f)] - [InlineData(1.0f, float.NaN, 1.0f)] - [InlineData(float.PositiveInfinity, float.NaN, float.PositiveInfinity)] - [InlineData(float.NegativeInfinity, float.NaN, float.NegativeInfinity)] - [InlineData(float.NaN, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.NaN, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(-0.0f, 0.0f, 0.0f)] - [InlineData(0.0f, -0.0f, 0.0f)] - [InlineData(2.0f, -3.0f, 2.0f)] - [InlineData(-3.0f, 2.0f, 2.0f)] - [InlineData(3.0f, -2.0f, 3.0f)] - [InlineData(-2.0f, 3.0f, 3.0f)] + [MemberData(nameof(GenericMathTestMemberData.MaxNumberSingle), MemberType = typeof(GenericMathTestMemberData))] public static void MaxNumberTest(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, float.MaxNumber(x, y), 0.0f); } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MinValue)] - [InlineData(float.MaxValue, float.MinValue, float.MinValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, 1.0f)] - [InlineData(1.0f, float.NaN, 1.0f)] - [InlineData(float.PositiveInfinity, float.NaN, float.PositiveInfinity)] - [InlineData(float.NegativeInfinity, float.NaN, float.NegativeInfinity)] - [InlineData(float.NaN, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.NaN, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(-0.0f, 0.0f, -0.0f)] - [InlineData(0.0f, -0.0f, -0.0f)] - [InlineData(2.0f, -3.0f, 2.0f)] - [InlineData(-3.0f, 2.0f, 2.0f)] - [InlineData(3.0f, -2.0f, -2.0f)] - [InlineData(-2.0f, 3.0f, -2.0f)] + [MemberData(nameof(GenericMathTestMemberData.MinMagnitudeNumberSingle), MemberType = typeof(GenericMathTestMemberData))] public static void MinMagnitudeNumberTest(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, float.MinMagnitudeNumber(x, y), 0.0f); } [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MinValue)] - [InlineData(float.MaxValue, float.MinValue, float.MinValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, 1.0f)] - [InlineData(1.0f, float.NaN, 1.0f)] - [InlineData(float.PositiveInfinity, float.NaN, float.PositiveInfinity)] - [InlineData(float.NegativeInfinity, float.NaN, float.NegativeInfinity)] - [InlineData(float.NaN, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.NaN, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(-0.0f, 0.0f, -0.0f)] - [InlineData(0.0f, -0.0f, -0.0f)] - [InlineData(2.0f, -3.0f, -3.0f)] - [InlineData(-3.0f, 2.0f, -3.0f)] - [InlineData(3.0f, -2.0f, -2.0f)] - [InlineData(-2.0f, 3.0f, -2.0f)] + [MemberData(nameof(GenericMathTestMemberData.MinNumberSingle), MemberType = typeof(GenericMathTestMemberData))] public static void MinNumberTest(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, float.MinNumber(x, y), 0.0f); @@ -1574,37 +1426,7 @@ public static void TanPiTest(float value, float expectedResult, float allowedVar } [Theory] - [InlineData(float.NegativeInfinity, float.NegativeInfinity, 0.5f, float.NegativeInfinity)] - [InlineData(float.NegativeInfinity, float.NaN, 0.5f, float.NaN)] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, 0.5f, float.NaN)] - [InlineData(float.NegativeInfinity, 0.0f, 0.5f, float.NegativeInfinity)] - [InlineData(float.NegativeInfinity, 1.0f, 0.5f, float.NegativeInfinity)] - [InlineData(float.NaN, float.NegativeInfinity, 0.5f, float.NaN)] - [InlineData(float.NaN, float.NaN, 0.5f, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, 0.5f, float.NaN)] - [InlineData(float.NaN, 0.0f, 0.5f, float.NaN)] - [InlineData(float.NaN, 1.0f, 0.5f, float.NaN)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, 0.5f, float.NaN)] - [InlineData(float.PositiveInfinity, float.NaN, 0.5f, float.NaN)] - [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.5f, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, 0.0f, 0.5f, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, 1.0f, 0.5f, float.PositiveInfinity)] - [InlineData(1.0f, 3.0f, 0.0f, 1.0f)] - [InlineData(1.0f, 3.0f, 0.5f, 2.0f)] - [InlineData(1.0f, 3.0f, 1.0f, 3.0f)] - [InlineData(1.0f, 3.0f, 2.0f, 5.0f)] - [InlineData(2.0f, 4.0f, 0.0f, 2.0f)] - [InlineData(2.0f, 4.0f, 0.5f, 3.0f)] - [InlineData(2.0f, 4.0f, 1.0f, 4.0f)] - [InlineData(2.0f, 4.0f, 2.0f, 6.0f)] - [InlineData(3.0f, 1.0f, 0.0f, 3.0f)] - [InlineData(3.0f, 1.0f, 0.5f, 2.0f)] - [InlineData(3.0f, 1.0f, 1.0f, 1.0f)] - [InlineData(3.0f, 1.0f, 2.0f, -1.0f)] - [InlineData(4.0f, 2.0f, 0.0f, 4.0f)] - [InlineData(4.0f, 2.0f, 0.5f, 3.0f)] - [InlineData(4.0f, 2.0f, 1.0f, 2.0f)] - [InlineData(4.0f, 2.0f, 2.0f, 0.0f)] + [MemberData(nameof(GenericMathTestMemberData.LerpSingle), MemberType = typeof(GenericMathTestMemberData))] public static void LerpTest(float value1, float value2, float amount, float expectedResult) { AssertExtensions.Equal(+expectedResult, float.Lerp(+value1, +value2, amount), 0); @@ -1612,29 +1434,7 @@ public static void LerpTest(float value1, float value2, float amount, float expe } [Theory] - [InlineData(float.NaN, float.NaN, 0.0f)] - [InlineData(0.0f, 0.0f, 0.0f)] - [InlineData(0.318309886f, 0.0055555557f, CrossPlatformMachineEpsilon)] // value: (1 / pi) - [InlineData(0.434294482f, 0.007579869f, CrossPlatformMachineEpsilon)] // value: (log10(e)) - [InlineData(0.5f, 0.008726646f, CrossPlatformMachineEpsilon)] - [InlineData(0.636619772f, 0.011111111f, CrossPlatformMachineEpsilon)] // value: (2 / pi) - [InlineData(0.693147181f, 0.0120977005f, CrossPlatformMachineEpsilon)] // value: (ln(2)) - [InlineData(0.707106781f, 0.012341342f, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) - [InlineData(0.785398163f, 0.013707785f, CrossPlatformMachineEpsilon)] // value: (pi / 4) - [InlineData(1.0f, 0.017453292f, CrossPlatformMachineEpsilon)] - [InlineData(1.12837917f, 0.019693933f, CrossPlatformMachineEpsilon)] // value: (2 / sqrt(pi)) - [InlineData(1.41421356f, 0.024682684f, CrossPlatformMachineEpsilon)] // value: (sqrt(2)) - [InlineData(1.44269504f, 0.025179777f, CrossPlatformMachineEpsilon)] // value: (log2(e)) - [InlineData(1.5f, 0.02617994f, CrossPlatformMachineEpsilon)] - [InlineData(1.57079633f, 0.02741557f, CrossPlatformMachineEpsilon)] // value: (pi / 2) - [InlineData(2.0f, 0.034906585f, CrossPlatformMachineEpsilon)] - [InlineData(2.30258509f, 0.040187694f, CrossPlatformMachineEpsilon)] // value: (ln(10)) - [InlineData(2.5f, 0.043633234f, CrossPlatformMachineEpsilon)] - [InlineData(2.71828183f, 0.047442965f, CrossPlatformMachineEpsilon)] // value: (e) - [InlineData(3.0f, 0.05235988f, CrossPlatformMachineEpsilon)] - [InlineData(3.14159265f, 0.05483114f, CrossPlatformMachineEpsilon)] // value: (pi) - [InlineData(3.5f, 0.061086528f, CrossPlatformMachineEpsilon)] - [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + [MemberData(nameof(GenericMathTestMemberData.DegreesToRadiansSingle), MemberType = typeof(GenericMathTestMemberData))] public static void DegreesToRadiansTest(float value, float expectedResult, float allowedVariance) { AssertExtensions.Equal(-expectedResult, float.DegreesToRadians(-value), allowedVariance); @@ -1642,29 +1442,7 @@ public static void DegreesToRadiansTest(float value, float expectedResult, float } [Theory] - [InlineData(float.NaN, float.NaN, 0.0)] - [InlineData(0.0f, 0.0f, 0.0)] - [InlineData(0.0055555557f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) - [InlineData(0.007579869f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) - [InlineData(0.008726646f, 0.5f, CrossPlatformMachineEpsilon)] - [InlineData(0.011111111f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) - [InlineData(0.0120977005f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) - [InlineData(0.012341342f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) - [InlineData(0.013707785f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) - [InlineData(0.017453292f, 1.0f, CrossPlatformMachineEpsilon)] - [InlineData(0.019693933f, 1.12837917f, CrossPlatformMachineEpsilon)] // expected: (2 / sqrt(pi)) - [InlineData(0.024682684f, 1.41421356f, CrossPlatformMachineEpsilon)] // expected: (sqrt(2)) - [InlineData(0.025179777f, 1.44269504f, CrossPlatformMachineEpsilon)] // expected: (log2(e)) - [InlineData(0.02617994f, 1.5f, CrossPlatformMachineEpsilon)] - [InlineData(0.02741557f, 1.57079633f, CrossPlatformMachineEpsilon)] // expected: (pi / 2) - [InlineData(0.034906585f, 2.0f, CrossPlatformMachineEpsilon)] - [InlineData(0.040187694f, 2.30258509f, CrossPlatformMachineEpsilon)] // expected: (ln(10)) - [InlineData(0.043633234f, 2.5f, CrossPlatformMachineEpsilon)] - [InlineData(0.047442965f, 2.71828183f, CrossPlatformMachineEpsilon)] // expected: (e) - [InlineData(0.05235988f, 3.0f, CrossPlatformMachineEpsilon)] - [InlineData(0.05483114f, 3.14159265f, CrossPlatformMachineEpsilon)] // expected: (pi) - [InlineData(0.061086528f, 3.5f, CrossPlatformMachineEpsilon)] - [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0)] + [MemberData(nameof(GenericMathTestMemberData.RadiansToDegreesSingle), MemberType = typeof(GenericMathTestMemberData))] public static void RadiansToDegreesTest(float value, float expectedResult, float allowedVariance) { AssertExtensions.Equal(-expectedResult, float.RadiansToDegrees(-value), allowedVariance); diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index bcd4ae0639e92..44fc12ac0a232 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -355,10 +355,16 @@ emit_simd_ins_for_binary_op (MonoCompile *cfg, MonoClass *klass, MonoMethodSigna instc0 = OP_FDIV; break; } +#ifdef TARGET_ARM64 case SN_Max: +#endif + case SN_MaxNative: instc0 = OP_FMAX; break; +#ifdef TARGET_ARM64 case SN_Min: +#endif + case SN_MinNative: instc0 = OP_FMIN; break; case SN_Multiply: @@ -396,6 +402,7 @@ emit_simd_ins_for_binary_op (MonoCompile *cfg, MonoClass *klass, MonoMethodSigna case SN_op_Division: return NULL; case SN_Max: + case SN_MaxNative: instc0 = type_enum_is_unsigned (arg_type) ? OP_IMAX_UN : OP_IMAX; #ifdef TARGET_AMD64 if (!COMPILE_LLVM (cfg) && instc0 == OP_IMAX_UN) @@ -403,6 +410,7 @@ emit_simd_ins_for_binary_op (MonoCompile *cfg, MonoClass *klass, MonoMethodSigna #endif break; case SN_Min: + case SN_MinNative: instc0 = type_enum_is_unsigned (arg_type) ? OP_IMIN_UN : OP_IMIN; #ifdef TARGET_AMD64 if (!COMPILE_LLVM (cfg) && instc0 == OP_IMIN_UN) @@ -1226,6 +1234,11 @@ static guint16 sri_vector_methods [] = { SN_GreaterThanOrEqual, SN_GreaterThanOrEqualAll, SN_GreaterThanOrEqualAny, + SN_IsNaN, + SN_IsNegative, + SN_IsPositive, + SN_IsPositiveInfinity, + SN_IsZero, SN_LessThan, SN_LessThanAll, SN_LessThanAny, @@ -1233,8 +1246,11 @@ static guint16 sri_vector_methods [] = { SN_LessThanOrEqualAll, SN_LessThanOrEqualAny, SN_Max, + SN_MaxNative, SN_Min, + SN_MinNative, SN_Multiply, + SN_MultiplyAddEstimate, SN_Narrow, SN_Negate, SN_OnesComplement, @@ -1595,12 +1611,18 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi case SN_BitwiseOr: case SN_Divide: case SN_Max: + case SN_MaxNative: case SN_Min: + case SN_MinNative: case SN_Multiply: case SN_Subtract: case SN_Xor: if (!is_element_type_primitive (fsig->params [0])) return NULL; +#ifndef TARGET_ARM64 + if (((id == SN_Max) || (id == SN_Min)) && type_enum_is_float(arg0_type)) + return NULL; +#endif return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id); case SN_AndNot: { if (!is_element_type_primitive (fsig->params [0])) @@ -1619,6 +1641,40 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi return NULL; #endif } + case SN_MultiplyAddEstimate: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + + int mul_op; + int add_op; + + if (type_enum_is_float (arg0_type)) { + mul_op = OP_FMUL; + add_op = OP_FADD; + } else { + mul_op = OP_IMUL; + add_op = OP_IADD; + +#ifdef TARGET_ARM64 + if (!COMPILE_LLVM (cfg) && (arg0_type == MONO_TYPE_I8 || arg0_type == MONO_TYPE_U8 || arg0_type == MONO_TYPE_I || arg0_type == MONO_TYPE_U)) + return NULL; +#endif +#ifdef TARGET_AMD64 + if (!COMPILE_LLVM (cfg)) + return NULL; +#endif + } + + MonoInst *mul_ins = emit_simd_ins (cfg, klass, OP_XBINOP, args [0]->dreg, args [1]->dreg); + mul_ins->inst_c0 = mul_op; + mul_ins->inst_c1 = arg0_type; + + MonoInst *add_ins = emit_simd_ins (cfg, klass, OP_XBINOP, mul_ins->dreg, args [2]->dreg); + add_ins->inst_c0 = add_op; + add_ins->inst_c1 = arg0_type; + + return add_ins; + } case SN_As: case SN_AsByte: case SN_AsDouble: @@ -2147,6 +2203,88 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi return ret; } } + case SN_IsNaN: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + if (!type_enum_is_float(arg0_type)) + return emit_xzero (cfg, klass); + int op = -1; +#if defined(TARGET_ARM64) || defined(TARGET_AMD64) + op = OP_ONES_COMPLEMENT; +#elif defined(TARGET_WASM) + op = OP_WASM_ONESCOMPLEMENT; +#endif + if (op == -1) + return NULL; + MonoInst *xcmp = emit_xcompare (cfg, klass, arg0_type, args [0], args [0]); + MonoInst *xnot = emit_simd_ins (cfg, klass, op, xcmp->dreg, -1); + xnot->inst_c1 = arg0_type; + return xnot; + } + case SN_IsNegative: + case SN_IsPositive: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + if (type_enum_is_unsigned(arg0_type)) { + if (id == SN_IsNegative) { + return emit_xzero (cfg, klass); + } else { + return emit_xones (cfg, klass); + } + } + + MonoInst *arg0 = args [0]; + MonoClass *op_klass = klass; + + if (type_enum_is_float (arg0_type)) { + if (arg0_type == MONO_TYPE_R4) { + arg0_type = MONO_TYPE_I4; + op_klass = mono_defaults.int32_class; + } else { + arg0_type = MONO_TYPE_I8; + op_klass = mono_defaults.int64_class; + } + op_klass = create_class_instance (m_class_get_name_space (klass), m_class_get_name (klass), m_class_get_byval_arg (op_klass)); + arg0 = emit_simd_ins (cfg, op_klass, OP_XCAST, arg0->dreg, -1); + } + + int cmpId = (id == SN_IsNegative) ? SN_LessThan : SN_GreaterThanOrEqual; + MonoInst *ins = emit_xcompare_for_intrinsic (cfg, op_klass, cmpId, arg0_type, arg0, emit_xzero (cfg, op_klass)); + + if (op_klass != klass) { + ins = emit_simd_ins (cfg, klass, OP_XCAST, ins->dreg, -1); + } + return ins; + } + case SN_IsPositiveInfinity: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + if (arg0_type == MONO_TYPE_R4) { + guint32 value[4]; + + value [0] = 0x7F800000; + value [1] = 0x7F800000; + value [2] = 0x7F800000; + value [3] = 0x7F800000; + + MonoInst *arg1 = emit_xconst_v128 (cfg, klass, (guint8*)value); + return emit_xcompare (cfg, klass, arg0_type, args [0], arg1); + } else if (arg0_type == MONO_TYPE_R8) { + guint64 value[2]; + + value [0] = 0x7FF0000000000000; + value [1] = 0x7FF0000000000000; + + MonoInst *arg1 = emit_xconst_v128 (cfg, klass, (guint8*)value); + return emit_xcompare (cfg, klass, arg0_type, args [0], arg1); + } + return emit_xzero (cfg, klass); + } + case SN_IsZero: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + return emit_xcompare (cfg, klass, arg0_type, args [0], emit_xzero (cfg, klass)); + } case SN_Narrow: { if (!is_element_type_primitive (fsig->params [0])) return NULL; @@ -2713,6 +2851,7 @@ static guint16 vector_2_3_4_methods[] = { SN_Abs, SN_Add, SN_Clamp, + SN_ClampNative, SN_Conjugate, SN_CopyTo, SN_Distance, @@ -2723,7 +2862,9 @@ static guint16 vector_2_3_4_methods[] = { SN_LengthSquared, SN_Lerp, SN_Max, + SN_MaxNative, SN_Min, + SN_MinNative, SN_Multiply, SN_Negate, SN_Normalize, @@ -2944,10 +3085,8 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f float value[4]; value [0] = 1.0f; value [1] = 1.0f; - value [2] = 1.0f; - value [3] = 1.0f; - if (len == 3) - value [3] = 0.0f; + value [2] = (len > 2) ? 1.0f : 0.0f; + value [3] = (len > 3) ? 1.0f : 0.0f; return emit_xconst_v128 (cfg, klass, (guint8*)value); } case SN_set_Item: { @@ -3018,11 +3157,17 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f case SN_op_Multiply: case SN_op_Subtraction: case SN_Max: - case SN_Min: { + case SN_MaxNative: + case SN_Min: + case SN_MinNative: { const char *klass_name = m_class_get_name (klass); // FIXME https://github.com/dotnet/runtime/issues/82408 if ((id == SN_op_Multiply || id == SN_Multiply || id == SN_op_Division || id == SN_Divide) && !strcmp (klass_name, "Quaternion")) return NULL; +#ifndef TARGET_ARM64 + if ((id == SN_Max) || (id == SN_Min)) + return NULL; +#endif return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, MONO_TYPE_R4, id); } case SN_Dot: { @@ -3079,9 +3224,14 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f } case SN_CopyTo: return NULL; - case SN_Clamp: { + case SN_Clamp: + case SN_ClampNative: { if (!(!fsig->hasthis && fsig->param_count == 3 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type) && mono_metadata_type_equal (fsig->params [2], type))) return NULL; +#ifndef TARGET_ARM64 + if (id == SN_Clamp) + return NULL; +#endif MonoInst *max = emit_simd_ins (cfg, klass, OP_XBINOP, args[0]->dreg, args[1]->dreg); max->inst_c0 = OP_FMAX; @@ -3152,26 +3302,44 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f #endif } case SN_Lerp: { -#if defined (TARGET_ARM64) - MonoInst* v1 = args [1]; if (!strcmp ("Quaternion", m_class_get_name (klass))) return NULL; - - MonoInst *diffs = emit_simd_ins (cfg, klass, OP_XBINOP, v1->dreg, args [0]->dreg); - diffs->inst_c0 = OP_FSUB; - diffs->inst_c1 = MONO_TYPE_R4; + float value[4]; + value [0] = 1.0f; + value [1] = 1.0f; + value [2] = (len > 2) ? 1.0f : 0.0f; + value [3] = (len > 3) ? 1.0f : 0.0f; + MonoInst *ins_one = emit_xconst_v128 (cfg, klass, (guint8*)value); + + MonoInst *ins_amount = args [2]; + + if (!type_is_simd_vector (fsig->params [2])) { + ins_amount = emit_simd_ins (cfg, klass, type_to_expand_op (etype->type), ins_amount->dreg, -1); + ins_amount->inst_c1 = MONO_TYPE_R4; + } + + // diff = 1.0 - amount + MonoInst *ins_diff = emit_simd_ins (cfg, klass, OP_XBINOP, ins_one->dreg, ins_amount->dreg); + ins_diff->inst_c0 = OP_FSUB; + ins_diff->inst_c1 = MONO_TYPE_R4; - MonoInst *scaled_diffs = handle_mul_div_by_scalar (cfg, klass, MONO_TYPE_R4, args [2]->dreg, diffs->dreg, OP_FMUL); - - MonoInst *result = emit_simd_ins (cfg, klass, OP_XBINOP, args [0]->dreg, scaled_diffs->dreg); + // prodx = x * diff + MonoInst *ins_prodx = emit_simd_ins (cfg, klass, OP_XBINOP, args [0]->dreg, ins_diff->dreg); + ins_prodx->inst_c0 = OP_FMUL; + ins_prodx->inst_c1 = MONO_TYPE_R4; + + // prody = y * amount + MonoInst *ins_prody = emit_simd_ins (cfg, klass, OP_XBINOP, args [1]->dreg, ins_amount->dreg); + ins_prody->inst_c0 = OP_FMUL; + ins_prody->inst_c1 = MONO_TYPE_R4; + + // result = prodx + prody + MonoInst *result = emit_simd_ins (cfg, klass, OP_XBINOP, ins_prodx->dreg, ins_prody->dreg); result->inst_c0 = OP_FADD; result->inst_c1 = MONO_TYPE_R4; return result; -#else - return NULL; -#endif } case SN_Normalize: { #if defined (TARGET_ARM64) diff --git a/src/mono/mono/mini/simd-methods.h b/src/mono/mono/mini/simd-methods.h index 071da07c9e5bf..fd7f56e4c7200 100644 --- a/src/mono/mono/mini/simd-methods.h +++ b/src/mono/mono/mini/simd-methods.h @@ -1,5 +1,6 @@ METHOD2(".ctor", ctor) METHOD(Clamp) +METHOD(ClampNative) METHOD(Conjugate) METHOD(CopyTo) METHOD(Distance) @@ -11,6 +12,11 @@ METHOD(GreaterThanAny) METHOD(GreaterThanOrEqual) METHOD(GreaterThanOrEqualAll) METHOD(GreaterThanOrEqualAny) +METHOD(IsNaN) +METHOD(IsNegative) +METHOD(IsPositive) +METHOD(IsPositiveInfinity) +METHOD(IsZero) METHOD(LessThan) METHOD(LessThanAll) METHOD(LessThanAny) @@ -20,10 +26,13 @@ METHOD(LessThanOrEqualAny) METHOD(Length) METHOD(LengthSquared) METHOD(Lerp) -METHOD(Min) METHOD(Max) -METHOD(MinScalar) +METHOD(MaxNative) METHOD(MaxScalar) +METHOD(Min) +METHOD(MinNative) +METHOD(MinScalar) +METHOD(MultiplyAddEstimate) METHOD(Normalize) METHOD(PopCount) METHOD(LeadingZeroCount)