diff --git a/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj b/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj index c17b0876c5af..9f7e3eabb372 100644 --- a/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj +++ b/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj @@ -7,6 +7,8 @@ true true true + true + $(DefineConstants);HAS_INTRINSICS netstandard1.0;portable-net45+win8+wp8+wpa81 net46-Debug;net46-Release;netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;netfx-Windows_NT-Debug;netfx-Windows_NT-Release;netstandard-Debug;netstandard-Release;netstandard1.0-Debug;netstandard1.0-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release;uapaot-Windows_NT-Debug;uapaot-Windows_NT-Release @@ -62,6 +64,9 @@ + + + diff --git a/src/System.Numerics.Vectors/src/System/Numerics/Matrix4x4.cs b/src/System.Numerics.Vectors/src/System/Numerics/Matrix4x4.cs index 16931d6d369e..0420cece86b2 100644 --- a/src/System.Numerics.Vectors/src/System/Numerics/Matrix4x4.cs +++ b/src/System.Numerics.Vectors/src/System/Numerics/Matrix4x4.cs @@ -3,12 +3,17 @@ // See the LICENSE file in the project root for more information. using System.Globalization; +using System.Runtime.InteropServices; +#if HAS_INTRINSICS +using System.Runtime.Intrinsics.X86; +#endif namespace System.Numerics { /// /// A structure encapsulating a 4x4 matrix. /// + [StructLayout(LayoutKind.Sequential)] public struct Matrix4x4 : IEquatable { #region Public Fields @@ -1755,8 +1760,29 @@ public static Matrix4x4 Transform(Matrix4x4 value, Quaternion rotation) /// /// The source matrix. /// The transposed matrix. - public static Matrix4x4 Transpose(Matrix4x4 matrix) + public static unsafe Matrix4x4 Transpose(Matrix4x4 matrix) { +#if HAS_INTRINSICS + if (Sse.IsSupported) + { + var row1 = Sse.LoadVector128(&matrix.M11); + var row2 = Sse.LoadVector128(&matrix.M21); + var row3 = Sse.LoadVector128(&matrix.M31); + var row4 = Sse.LoadVector128(&matrix.M41); + + var l12 = Sse.UnpackLow(row1, row2); + var l34 = Sse.UnpackLow(row3, row4); + var h12 = Sse.UnpackHigh(row1, row2); + var h34 = Sse.UnpackHigh(row3, row4); + + Sse.Store(&matrix.M11, Sse.MoveLowToHigh(l12, l34)); + Sse.Store(&matrix.M21, Sse.MoveHighToLow(l34, l12)); + Sse.Store(&matrix.M31, Sse.MoveLowToHigh(h12, h34)); + Sse.Store(&matrix.M41, Sse.MoveHighToLow(h34, h12)); + + return matrix; + } +#endif Matrix4x4 result; result.M11 = matrix.M11; @@ -1786,8 +1812,19 @@ public static Matrix4x4 Transpose(Matrix4x4 matrix) /// The second source matrix. /// The relative weight of the second source matrix. /// The interpolated matrix. - public static Matrix4x4 Lerp(Matrix4x4 matrix1, Matrix4x4 matrix2, float amount) + public static unsafe Matrix4x4 Lerp(Matrix4x4 matrix1, Matrix4x4 matrix2, float amount) { +#if HAS_INTRINSICS + if (Sse.IsSupported) + { + var amountVec = Sse.SetAllVector128(amount); + Sse.Store(&matrix1.M11, VectorMath.Lerp(Sse.LoadVector128(&matrix1.M11), Sse.LoadVector128(&matrix2.M11), amountVec)); + Sse.Store(&matrix1.M21, VectorMath.Lerp(Sse.LoadVector128(&matrix1.M21), Sse.LoadVector128(&matrix2.M21), amountVec)); + Sse.Store(&matrix1.M31, VectorMath.Lerp(Sse.LoadVector128(&matrix1.M31), Sse.LoadVector128(&matrix2.M31), amountVec)); + Sse.Store(&matrix1.M41, VectorMath.Lerp(Sse.LoadVector128(&matrix1.M41), Sse.LoadVector128(&matrix2.M41), amountVec)); + return matrix1; + } +#endif Matrix4x4 result; // First row @@ -1822,29 +1859,7 @@ public static Matrix4x4 Lerp(Matrix4x4 matrix1, Matrix4x4 matrix2, float amount) /// /// The source matrix. /// The negated matrix. - public static Matrix4x4 Negate(Matrix4x4 value) - { - Matrix4x4 result; - - result.M11 = -value.M11; - result.M12 = -value.M12; - result.M13 = -value.M13; - result.M14 = -value.M14; - result.M21 = -value.M21; - result.M22 = -value.M22; - result.M23 = -value.M23; - result.M24 = -value.M24; - result.M31 = -value.M31; - result.M32 = -value.M32; - result.M33 = -value.M33; - result.M34 = -value.M34; - result.M41 = -value.M41; - result.M42 = -value.M42; - result.M43 = -value.M43; - result.M44 = -value.M44; - - return result; - } + public static Matrix4x4 Negate(Matrix4x4 value) => -value; /// /// Adds two matrices together. @@ -1852,29 +1867,7 @@ public static Matrix4x4 Negate(Matrix4x4 value) /// The first source matrix. /// The second source matrix. /// The resulting matrix. - public static Matrix4x4 Add(Matrix4x4 value1, Matrix4x4 value2) - { - Matrix4x4 result; - - result.M11 = value1.M11 + value2.M11; - result.M12 = value1.M12 + value2.M12; - result.M13 = value1.M13 + value2.M13; - result.M14 = value1.M14 + value2.M14; - result.M21 = value1.M21 + value2.M21; - result.M22 = value1.M22 + value2.M22; - result.M23 = value1.M23 + value2.M23; - result.M24 = value1.M24 + value2.M24; - result.M31 = value1.M31 + value2.M31; - result.M32 = value1.M32 + value2.M32; - result.M33 = value1.M33 + value2.M33; - result.M34 = value1.M34 + value2.M34; - result.M41 = value1.M41 + value2.M41; - result.M42 = value1.M42 + value2.M42; - result.M43 = value1.M43 + value2.M43; - result.M44 = value1.M44 + value2.M44; - - return result; - } + public static Matrix4x4 Add(Matrix4x4 value1, Matrix4x4 value2) => value1 + value2; /// /// Subtracts the second matrix from the first. @@ -1882,29 +1875,7 @@ public static Matrix4x4 Add(Matrix4x4 value1, Matrix4x4 value2) /// The first source matrix. /// The second source matrix. /// The result of the subtraction. - public static Matrix4x4 Subtract(Matrix4x4 value1, Matrix4x4 value2) - { - Matrix4x4 result; - - result.M11 = value1.M11 - value2.M11; - result.M12 = value1.M12 - value2.M12; - result.M13 = value1.M13 - value2.M13; - result.M14 = value1.M14 - value2.M14; - result.M21 = value1.M21 - value2.M21; - result.M22 = value1.M22 - value2.M22; - result.M23 = value1.M23 - value2.M23; - result.M24 = value1.M24 - value2.M24; - result.M31 = value1.M31 - value2.M31; - result.M32 = value1.M32 - value2.M32; - result.M33 = value1.M33 - value2.M33; - result.M34 = value1.M34 - value2.M34; - result.M41 = value1.M41 - value2.M41; - result.M42 = value1.M42 - value2.M42; - result.M43 = value1.M43 - value2.M43; - result.M44 = value1.M44 - value2.M44; - - return result; - } + public static Matrix4x4 Subtract(Matrix4x4 value1, Matrix4x4 value2) => value1 - value2; /// /// Multiplies a matrix by another matrix. @@ -1912,36 +1883,7 @@ public static Matrix4x4 Subtract(Matrix4x4 value1, Matrix4x4 value2) /// The first source matrix. /// The second source matrix. /// The result of the multiplication. - public static Matrix4x4 Multiply(Matrix4x4 value1, Matrix4x4 value2) - { - Matrix4x4 result; - - // First row - result.M11 = value1.M11 * value2.M11 + value1.M12 * value2.M21 + value1.M13 * value2.M31 + value1.M14 * value2.M41; - result.M12 = value1.M11 * value2.M12 + value1.M12 * value2.M22 + value1.M13 * value2.M32 + value1.M14 * value2.M42; - result.M13 = value1.M11 * value2.M13 + value1.M12 * value2.M23 + value1.M13 * value2.M33 + value1.M14 * value2.M43; - result.M14 = value1.M11 * value2.M14 + value1.M12 * value2.M24 + value1.M13 * value2.M34 + value1.M14 * value2.M44; - - // Second row - result.M21 = value1.M21 * value2.M11 + value1.M22 * value2.M21 + value1.M23 * value2.M31 + value1.M24 * value2.M41; - result.M22 = value1.M21 * value2.M12 + value1.M22 * value2.M22 + value1.M23 * value2.M32 + value1.M24 * value2.M42; - result.M23 = value1.M21 * value2.M13 + value1.M22 * value2.M23 + value1.M23 * value2.M33 + value1.M24 * value2.M43; - result.M24 = value1.M21 * value2.M14 + value1.M22 * value2.M24 + value1.M23 * value2.M34 + value1.M24 * value2.M44; - - // Third row - result.M31 = value1.M31 * value2.M11 + value1.M32 * value2.M21 + value1.M33 * value2.M31 + value1.M34 * value2.M41; - result.M32 = value1.M31 * value2.M12 + value1.M32 * value2.M22 + value1.M33 * value2.M32 + value1.M34 * value2.M42; - result.M33 = value1.M31 * value2.M13 + value1.M32 * value2.M23 + value1.M33 * value2.M33 + value1.M34 * value2.M43; - result.M34 = value1.M31 * value2.M14 + value1.M32 * value2.M24 + value1.M33 * value2.M34 + value1.M34 * value2.M44; - - // Fourth row - result.M41 = value1.M41 * value2.M11 + value1.M42 * value2.M21 + value1.M43 * value2.M31 + value1.M44 * value2.M41; - result.M42 = value1.M41 * value2.M12 + value1.M42 * value2.M22 + value1.M43 * value2.M32 + value1.M44 * value2.M42; - result.M43 = value1.M41 * value2.M13 + value1.M42 * value2.M23 + value1.M43 * value2.M33 + value1.M44 * value2.M43; - result.M44 = value1.M41 * value2.M14 + value1.M42 * value2.M24 + value1.M43 * value2.M34 + value1.M44 * value2.M44; - - return result; - } + public static Matrix4x4 Multiply(Matrix4x4 value1, Matrix4x4 value2) => value1 * value2; /// /// Multiplies a matrix by a scalar value. @@ -1949,37 +1891,27 @@ public static Matrix4x4 Multiply(Matrix4x4 value1, Matrix4x4 value2) /// The source matrix. /// The scaling factor. /// The scaled matrix. - public static Matrix4x4 Multiply(Matrix4x4 value1, float value2) - { - Matrix4x4 result; - - result.M11 = value1.M11 * value2; - result.M12 = value1.M12 * value2; - result.M13 = value1.M13 * value2; - result.M14 = value1.M14 * value2; - result.M21 = value1.M21 * value2; - result.M22 = value1.M22 * value2; - result.M23 = value1.M23 * value2; - result.M24 = value1.M24 * value2; - result.M31 = value1.M31 * value2; - result.M32 = value1.M32 * value2; - result.M33 = value1.M33 * value2; - result.M34 = value1.M34 * value2; - result.M41 = value1.M41 * value2; - result.M42 = value1.M42 * value2; - result.M43 = value1.M43 * value2; - result.M44 = value1.M44 * value2; - - return result; - } + public static Matrix4x4 Multiply(Matrix4x4 value1, float value2) => value1 * value2; /// /// Returns a new matrix with the negated elements of the given matrix. /// /// The source matrix. /// The negated matrix. - public static Matrix4x4 operator -(Matrix4x4 value) + public static unsafe Matrix4x4 operator -(Matrix4x4 value) { +#if HAS_INTRINSICS + if (Sse.IsSupported) + { + var zero = Sse.SetZeroVector128(); + Sse.Store(&value.M11, Sse.Subtract(zero, Sse.LoadVector128(&value.M11))); + Sse.Store(&value.M21, Sse.Subtract(zero, Sse.LoadVector128(&value.M21))); + Sse.Store(&value.M31, Sse.Subtract(zero, Sse.LoadVector128(&value.M31))); + Sse.Store(&value.M41, Sse.Subtract(zero, Sse.LoadVector128(&value.M41))); + + return value; + } +#endif Matrix4x4 m; m.M11 = -value.M11; @@ -2008,8 +1940,18 @@ public static Matrix4x4 Multiply(Matrix4x4 value1, float value2) /// The first source matrix. /// The second source matrix. /// The resulting matrix. - public static Matrix4x4 operator +(Matrix4x4 value1, Matrix4x4 value2) + public static unsafe Matrix4x4 operator +(Matrix4x4 value1, Matrix4x4 value2) { +#if HAS_INTRINSICS + if (Sse.IsSupported) + { + Sse.Store(&value1.M11, Sse.Add(Sse.LoadVector128(&value1.M11), Sse.LoadVector128(&value1.M11))); + Sse.Store(&value1.M21, Sse.Add(Sse.LoadVector128(&value1.M21), Sse.LoadVector128(&value1.M21))); + Sse.Store(&value1.M31, Sse.Add(Sse.LoadVector128(&value1.M31), Sse.LoadVector128(&value1.M31))); + Sse.Store(&value1.M41, Sse.Add(Sse.LoadVector128(&value1.M41), Sse.LoadVector128(&value1.M41))); + return value1; + } +#endif Matrix4x4 m; m.M11 = value1.M11 + value2.M11; @@ -2038,8 +1980,18 @@ public static Matrix4x4 Multiply(Matrix4x4 value1, float value2) /// The first source matrix. /// The second source matrix. /// The result of the subtraction. - public static Matrix4x4 operator -(Matrix4x4 value1, Matrix4x4 value2) + public static unsafe Matrix4x4 operator -(Matrix4x4 value1, Matrix4x4 value2) { +#if HAS_INTRINSICS + if (Sse.IsSupported) + { + Sse.Store(&value1.M11, Sse.Subtract(Sse.LoadVector128(&value1.M11), Sse.LoadVector128(&value1.M11))); + Sse.Store(&value1.M21, Sse.Subtract(Sse.LoadVector128(&value1.M21), Sse.LoadVector128(&value1.M21))); + Sse.Store(&value1.M31, Sse.Subtract(Sse.LoadVector128(&value1.M31), Sse.LoadVector128(&value1.M31))); + Sse.Store(&value1.M41, Sse.Subtract(Sse.LoadVector128(&value1.M41), Sse.LoadVector128(&value1.M41))); + return value1; + } +#endif Matrix4x4 m; m.M11 = value1.M11 - value2.M11; @@ -2068,8 +2020,44 @@ public static Matrix4x4 Multiply(Matrix4x4 value1, float value2) /// The first source matrix. /// The second source matrix. /// The result of the multiplication. - public static Matrix4x4 operator *(Matrix4x4 value1, Matrix4x4 value2) + public static unsafe Matrix4x4 operator *(Matrix4x4 value1, Matrix4x4 value2) { +#if HAS_INTRINSICS + if (Sse.IsSupported) + { + var row = Sse.LoadVector128(&value1.M11); + Sse.Store(&value1.M11, + Sse.Add(Sse.Add(Sse.Multiply(Sse.Shuffle(row, row, 0x00), Sse.LoadVector128(&value2.M11)), + Sse.Multiply(Sse.Shuffle(row, row, 0x55), Sse.LoadVector128(&value2.M21))), + Sse.Add(Sse.Multiply(Sse.Shuffle(row, row, 0xAA), Sse.LoadVector128(&value2.M31)), + Sse.Multiply(Sse.Shuffle(row, row, 0xFF), Sse.LoadVector128(&value2.M41))))); + + // 0x00 is _MM_SHUFFLE(0,0,0,0), 0x55 is _MM_SHUFFLE(1,1,1,1), etc. + // TODO: Replace with a method once it's added to the API. + + row = Sse.LoadVector128(&value1.M21); + Sse.Store(&value1.M21, + Sse.Add(Sse.Add(Sse.Multiply(Sse.Shuffle(row, row, 0x00), Sse.LoadVector128(&value2.M11)), + Sse.Multiply(Sse.Shuffle(row, row, 0x55), Sse.LoadVector128(&value2.M21))), + Sse.Add(Sse.Multiply(Sse.Shuffle(row, row, 0xAA), Sse.LoadVector128(&value2.M31)), + Sse.Multiply(Sse.Shuffle(row, row, 0xFF), Sse.LoadVector128(&value2.M41))))); + + row = Sse.LoadVector128(&value1.M31); + Sse.Store(&value1.M31, + Sse.Add(Sse.Add(Sse.Multiply(Sse.Shuffle(row, row, 0x00), Sse.LoadVector128(&value2.M11)), + Sse.Multiply(Sse.Shuffle(row, row, 0x55), Sse.LoadVector128(&value2.M21))), + Sse.Add(Sse.Multiply(Sse.Shuffle(row, row, 0xAA), Sse.LoadVector128(&value2.M31)), + Sse.Multiply(Sse.Shuffle(row, row, 0xFF), Sse.LoadVector128(&value2.M41))))); + + row = Sse.LoadVector128(&value1.M41); + Sse.Store(&value1.M41, + Sse.Add(Sse.Add(Sse.Multiply(Sse.Shuffle(row, row, 0x00), Sse.LoadVector128(&value2.M11)), + Sse.Multiply(Sse.Shuffle(row, row, 0x55), Sse.LoadVector128(&value2.M21))), + Sse.Add(Sse.Multiply(Sse.Shuffle(row, row, 0xAA), Sse.LoadVector128(&value2.M31)), + Sse.Multiply(Sse.Shuffle(row, row, 0xFF), Sse.LoadVector128(&value2.M41))))); + return value1; + } +#endif Matrix4x4 m; // First row @@ -2105,8 +2093,19 @@ public static Matrix4x4 Multiply(Matrix4x4 value1, float value2) /// The source matrix. /// The scaling factor. /// The scaled matrix. - public static Matrix4x4 operator *(Matrix4x4 value1, float value2) + public static unsafe Matrix4x4 operator *(Matrix4x4 value1, float value2) { +#if HAS_INTRINSICS + if (Sse.IsSupported) + { + var value2Vec = Sse.SetAllVector128(value2); + Sse.Store(&value1.M11, Sse.Multiply(Sse.LoadVector128(&value1.M11), value2Vec)); + Sse.Store(&value1.M21, Sse.Multiply(Sse.LoadVector128(&value1.M21), value2Vec)); + Sse.Store(&value1.M31, Sse.Multiply(Sse.LoadVector128(&value1.M31), value2Vec)); + Sse.Store(&value1.M41, Sse.Multiply(Sse.LoadVector128(&value1.M41), value2Vec)); + return value1; + } +#endif Matrix4x4 m; m.M11 = value1.M11 * value2; @@ -2134,13 +2133,22 @@ public static Matrix4x4 Multiply(Matrix4x4 value1, float value2) /// The first matrix to compare. /// The second matrix to compare. /// True if the given matrices are equal; False otherwise. - public static bool operator ==(Matrix4x4 value1, Matrix4x4 value2) + public static unsafe bool operator ==(Matrix4x4 value1, Matrix4x4 value2) { +#if HAS_INTRINSICS + if (Sse.IsSupported) + { + return + VectorMath.Equal(Sse.LoadVector128(&value1.M11), Sse.LoadVector128(&value2.M11)) && + VectorMath.Equal(Sse.LoadVector128(&value1.M21), Sse.LoadVector128(&value2.M21)) && + VectorMath.Equal(Sse.LoadVector128(&value1.M31), Sse.LoadVector128(&value2.M31)) && + VectorMath.Equal(Sse.LoadVector128(&value1.M41), Sse.LoadVector128(&value2.M41)); + } +#endif return (value1.M11 == value2.M11 && value1.M22 == value2.M22 && value1.M33 == value2.M33 && value1.M44 == value2.M44 && // Check diagonal element first for early out. - value1.M12 == value2.M12 && value1.M13 == value2.M13 && value1.M14 == value2.M14 && - value1.M21 == value2.M21 && value1.M23 == value2.M23 && value1.M24 == value2.M24 && - value1.M31 == value2.M31 && value1.M32 == value2.M32 && value1.M34 == value2.M34 && - value1.M41 == value2.M41 && value1.M42 == value2.M42 && value1.M43 == value2.M43); + value1.M12 == value2.M12 && value1.M13 == value2.M13 && value1.M14 == value2.M14 && value1.M21 == value2.M21 && + value1.M23 == value2.M23 && value1.M24 == value2.M24 && value1.M31 == value2.M31 && value1.M32 == value2.M32 && + value1.M34 == value2.M34 && value1.M41 == value2.M41 && value1.M42 == value2.M42 && value1.M43 == value2.M43); } /// @@ -2149,8 +2157,18 @@ public static Matrix4x4 Multiply(Matrix4x4 value1, float value2) /// The first matrix to compare. /// The second matrix to compare. /// True if the given matrices are not equal; False if they are equal. - public static bool operator !=(Matrix4x4 value1, Matrix4x4 value2) + public static unsafe bool operator !=(Matrix4x4 value1, Matrix4x4 value2) { +#if HAS_INTRINSICS + if (Sse.IsSupported) + { + return + VectorMath.NotEqual(Sse.LoadVector128(&value1.M11), Sse.LoadVector128(&value2.M11)) || + VectorMath.NotEqual(Sse.LoadVector128(&value1.M21), Sse.LoadVector128(&value2.M21)) || + VectorMath.NotEqual(Sse.LoadVector128(&value1.M31), Sse.LoadVector128(&value2.M31)) || + VectorMath.NotEqual(Sse.LoadVector128(&value1.M41), Sse.LoadVector128(&value2.M41)); + } +#endif return (value1.M11 != value2.M11 || value1.M12 != value2.M12 || value1.M13 != value2.M13 || value1.M14 != value2.M14 || value1.M21 != value2.M21 || value1.M22 != value2.M22 || value1.M23 != value2.M23 || value1.M24 != value2.M24 || value1.M31 != value2.M31 || value1.M32 != value2.M32 || value1.M33 != value2.M33 || value1.M34 != value2.M34 || @@ -2162,29 +2180,14 @@ public static Matrix4x4 Multiply(Matrix4x4 value1, float value2) /// /// The matrix to compare this instance to. /// True if the matrices are equal; False otherwise. - public bool Equals(Matrix4x4 other) - { - return (M11 == other.M11 && M22 == other.M22 && M33 == other.M33 && M44 == other.M44 && // Check diagonal element first for early out. - M12 == other.M12 && M13 == other.M13 && M14 == other.M14 && - M21 == other.M21 && M23 == other.M23 && M24 == other.M24 && - M31 == other.M31 && M32 == other.M32 && M34 == other.M34 && - M41 == other.M41 && M42 == other.M42 && M43 == other.M43); - } + public bool Equals(Matrix4x4 other) => this == other; /// /// Returns a boolean indicating whether the given Object is equal to this matrix instance. /// /// The Object to compare against. /// True if the Object is equal to this matrix; False otherwise. - public override bool Equals(object obj) - { - if (obj is Matrix4x4) - { - return Equals((Matrix4x4)obj); - } - - return false; - } + public override bool Equals(object obj) => (obj is Matrix4x4 other) && (this == other); /// /// Returns a String representing this matrix instance. diff --git a/src/System.Numerics.Vectors/src/System/Numerics/VectorMath.cs b/src/System.Numerics.Vectors/src/System/Numerics/VectorMath.cs new file mode 100644 index 000000000000..cec1e3a71bed --- /dev/null +++ b/src/System.Numerics.Vectors/src/System/Numerics/VectorMath.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System.Diagnostics; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace System.Numerics +{ + internal static class VectorMath + { + public static Vector128 Lerp(Vector128 a, Vector128 b, Vector128 t) + { + Debug.Assert(Sse.IsSupported); + return Sse.Add(a, Sse.Multiply(Sse.Subtract(b, a), t)); + } + + public static bool Equal(Vector128 vector1, Vector128 vector2) + { + Debug.Assert(Sse.IsSupported); + return Sse.MoveMask(Sse.CompareNotEqual(vector1, vector2)) == 0; + } + + public static bool NotEqual(Vector128 vector1, Vector128 vector2) + { + Debug.Assert(Sse.IsSupported); + return Sse.MoveMask(Sse.CompareNotEqual(vector1, vector2)) != 0; + } + } +}