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 33d5c9c4843948..5cf9aa45bd0ef7 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -16,10 +16,18 @@ public partial struct Matrix3x2 : System.IEquatable public float M32; public Matrix3x2(float m11, float m12, float m21, float m22, float m31, float m32) { throw null; } public static System.Numerics.Matrix3x2 Identity { get { throw null; } } - public float this[int row, int column] { readonly get { throw null; } set { throw null; } } public readonly bool IsIdentity { get { throw null; } } - public System.Numerics.Vector2 Translation { readonly get { throw null; } set { } } + public System.Numerics.Vector2 Translation { readonly get { throw null; } set { throw null; } } + public System.Numerics.Vector2 X { readonly get { throw null; } set { throw null; } } + public System.Numerics.Vector2 Y { readonly get { throw null; } set { throw null; } } + public System.Numerics.Vector2 Z { readonly get { throw null; } set { throw null; } } + public System.Numerics.Vector2 this[int row] { readonly get { throw null; } set { throw null; } } + public float this[int row, int column] { readonly get { throw null; } set { throw null; } } public static System.Numerics.Matrix3x2 Add(System.Numerics.Matrix3x2 value1, System.Numerics.Matrix3x2 value2) { throw null; } + public static Matrix3x2 Create(float value) { throw null; } + public static Matrix3x2 Create(System.Numerics.Vector2 value) { throw null; } + public static Matrix3x2 Create(System.Numerics.Vector2 x, System.Numerics.Vector2 y, System.Numerics.Vector2 z) { throw null; } + public static Matrix3x2 Create(float m11, float m12, float m21, float m22, float m31, float m32) { throw null; } public static System.Numerics.Matrix3x2 CreateRotation(float radians) { throw null; } public static System.Numerics.Matrix3x2 CreateRotation(float radians, System.Numerics.Vector2 centerPoint) { throw null; } public static System.Numerics.Matrix3x2 CreateScale(System.Numerics.Vector2 scales) { throw null; } @@ -35,6 +43,8 @@ public partial struct Matrix3x2 : System.IEquatable public readonly bool Equals(System.Numerics.Matrix3x2 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public readonly float GetDeterminant() { throw null; } + public readonly float GetElement(int row, int column) { throw null; } + public readonly System.Numerics.Vector2 GetRow(int index) { throw null; } public override readonly int GetHashCode() { throw null; } public static bool Invert(System.Numerics.Matrix3x2 matrix, out System.Numerics.Matrix3x2 result) { throw null; } public static System.Numerics.Matrix3x2 Lerp(System.Numerics.Matrix3x2 matrix1, System.Numerics.Matrix3x2 matrix2, float amount) { throw null; } @@ -50,6 +60,8 @@ public partial struct Matrix3x2 : System.IEquatable public static System.Numerics.Matrix3x2 operator -(System.Numerics.Matrix3x2 value) { throw null; } public static System.Numerics.Matrix3x2 Subtract(System.Numerics.Matrix3x2 value1, System.Numerics.Matrix3x2 value2) { throw null; } public override readonly string ToString() { throw null; } + public readonly System.Numerics.Matrix3x2 WithElement(int row, int column, float value) { throw null; } + public readonly System.Numerics.Matrix3x2 WithRow(int index, System.Numerics.Vector2 value) { throw null; } } public partial struct Matrix4x4 : System.IEquatable { @@ -72,10 +84,20 @@ public partial struct Matrix4x4 : System.IEquatable public Matrix4x4(System.Numerics.Matrix3x2 value) { throw null; } public Matrix4x4(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44) { throw null; } public static System.Numerics.Matrix4x4 Identity { get { throw null; } } - public float this[int row, int column] { readonly get { throw null; } set { throw null; } } public readonly bool IsIdentity { get { throw null; } } - public System.Numerics.Vector3 Translation { readonly get { throw null; } set { } } + public System.Numerics.Vector3 Translation { readonly get { throw null; } set { throw null; } } + public System.Numerics.Vector4 X { readonly get { throw null; } set { throw null; } } + public System.Numerics.Vector4 Y { readonly get { throw null; } set { throw null; } } + public System.Numerics.Vector4 Z { readonly get { throw null; } set { throw null; } } + public System.Numerics.Vector4 W { readonly get { throw null; } set { throw null; } } + public System.Numerics.Vector4 this[int row] { readonly get { throw null; } set { throw null; } } + public float this[int row, int column] { readonly get { throw null; } set { throw null; } } public static System.Numerics.Matrix4x4 Add(System.Numerics.Matrix4x4 value1, System.Numerics.Matrix4x4 value2) { throw null; } + public static Matrix4x4 Create(float value) { throw null; } + public static Matrix4x4 Create(System.Numerics.Matrix3x2 value) { throw null; } + public static Matrix4x4 Create(System.Numerics.Vector4 value) { throw null; } + public static Matrix4x4 Create(System.Numerics.Vector4 x, System.Numerics.Vector4 y, System.Numerics.Vector4 z, System.Numerics.Vector4 w) { throw null; } + public static Matrix4x4 Create(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44) { throw null; } public static System.Numerics.Matrix4x4 CreateBillboard(System.Numerics.Vector3 objectPosition, System.Numerics.Vector3 cameraPosition, System.Numerics.Vector3 cameraUpVector, System.Numerics.Vector3 cameraForwardVector) { throw null; } public static System.Numerics.Matrix4x4 CreateBillboardLeftHanded(System.Numerics.Vector3 objectPosition, System.Numerics.Vector3 cameraPosition, System.Numerics.Vector3 cameraUpVector, System.Numerics.Vector3 cameraForwardVector) { throw null; } public static System.Numerics.Matrix4x4 CreateConstrainedBillboard(System.Numerics.Vector3 objectPosition, System.Numerics.Vector3 cameraPosition, System.Numerics.Vector3 rotateAxis, System.Numerics.Vector3 cameraForwardVector, System.Numerics.Vector3 objectForwardVector) { throw null; } @@ -120,6 +142,8 @@ public partial struct Matrix4x4 : System.IEquatable public readonly bool Equals(System.Numerics.Matrix4x4 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public readonly float GetDeterminant() { throw null; } + public readonly float GetElement(int row, int column) { throw null; } + public readonly System.Numerics.Vector4 GetRow(int index) { throw null; } public override readonly int GetHashCode() { throw null; } public static bool Invert(System.Numerics.Matrix4x4 matrix, out System.Numerics.Matrix4x4 result) { throw null; } public static System.Numerics.Matrix4x4 Lerp(System.Numerics.Matrix4x4 matrix1, System.Numerics.Matrix4x4 matrix2, float amount) { throw null; } @@ -137,14 +161,19 @@ public partial struct Matrix4x4 : System.IEquatable public override readonly string ToString() { throw null; } public static System.Numerics.Matrix4x4 Transform(System.Numerics.Matrix4x4 value, System.Numerics.Quaternion rotation) { throw null; } public static System.Numerics.Matrix4x4 Transpose(System.Numerics.Matrix4x4 matrix) { throw null; } + public readonly System.Numerics.Matrix4x4 WithElement(int row, int column, float value) { throw null; } + public readonly System.Numerics.Matrix4x4 WithRow(int index, System.Numerics.Vector4 value) { throw null; } } public partial struct Plane : System.IEquatable { public System.Numerics.Vector3 Normal; public float D; - public Plane(System.Numerics.Vector3 normal, float d) { throw null; } public Plane(System.Numerics.Vector4 value) { throw null; } + public Plane(System.Numerics.Vector3 normal, float d) { throw null; } public Plane(float x, float y, float z, float d) { throw null; } + public static Plane Create(System.Numerics.Vector4 value) { throw null; } + public static Plane Create(System.Numerics.Vector3 normal, float d) { throw null; } + public static Plane Create(float x, float y, float z, float d) { throw null; } public static System.Numerics.Plane CreateFromVertices(System.Numerics.Vector3 point1, System.Numerics.Vector3 point2, System.Numerics.Vector3 point3) { throw null; } public static float Dot(System.Numerics.Plane plane, System.Numerics.Vector4 value) { throw null; } public static float DotCoordinate(System.Numerics.Plane plane, System.Numerics.Vector3 value) { throw null; } @@ -174,6 +203,8 @@ public partial struct Quaternion : System.IEquatable public static System.Numerics.Quaternion Add(System.Numerics.Quaternion value1, System.Numerics.Quaternion value2) { throw null; } public static System.Numerics.Quaternion Concatenate(System.Numerics.Quaternion value1, System.Numerics.Quaternion value2) { throw null; } public static System.Numerics.Quaternion Conjugate(System.Numerics.Quaternion value) { throw null; } + public static System.Numerics.Quaternion Create(System.Numerics.Vector3 vectorPart, float scalarPart) { throw null; } + public static System.Numerics.Quaternion Create(float x, float y, float z, float w) { throw null; } public static System.Numerics.Quaternion CreateFromAxisAngle(System.Numerics.Vector3 axis, float angle) { throw null; } public static System.Numerics.Quaternion CreateFromRotationMatrix(System.Numerics.Matrix4x4 matrix) { throw null; } public static System.Numerics.Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float roll) { throw null; } @@ -215,8 +246,11 @@ public static partial class Vector public static System.Numerics.Vector As(this System.Numerics.Vector vector) { throw null; } public static System.Numerics.Plane AsPlane(this System.Numerics.Vector4 value) { throw null; } public static System.Numerics.Quaternion AsQuaternion(this System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector2 AsVector2(this System.Numerics.Vector3 value) { throw null; } public static System.Numerics.Vector2 AsVector2(this System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector3 AsVector3(this System.Numerics.Vector2 value) { throw null; } public static System.Numerics.Vector3 AsVector3(this System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector3 AsVector3Unsafe(this System.Numerics.Vector2 value) { throw null; } public static System.Numerics.Vector4 AsVector4(this System.Numerics.Plane value) { throw null; } public static System.Numerics.Vector4 AsVector4(this System.Numerics.Quaternion value) { throw null; } public static System.Numerics.Vector4 AsVector4(this System.Numerics.Vector2 value) { throw null; } @@ -274,6 +308,8 @@ public static partial class Vector public static int CountWhereAllBitsSet(System.Numerics.Vector vector) { 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 CreateScalar(T value) { throw null; } + public static System.Numerics.Vector CreateScalarUnsafe(T value) { 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; } @@ -561,13 +597,15 @@ public partial struct Vector2 : System.IEquatable, Syst public static System.Numerics.Vector2 CopySign(System.Numerics.Vector2 value, System.Numerics.Vector2 sign) { throw null; } public static int Count(System.Numerics.Vector2 vector, float value) { throw null; } public static int CountWhereAllBitsSet(System.Numerics.Vector2 vector) { throw null; } - public static System.Numerics.Vector2 Create(float value) { throw null; } - public static System.Numerics.Vector2 Create(float x, float y) { throw null; } - public static System.Numerics.Vector2 Create(System.ReadOnlySpan values) { throw null; } public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector2 Cos(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 Create(float value) { throw null; } + public static System.Numerics.Vector2 Create(float x, float y) { throw null; } + public static System.Numerics.Vector2 Create(System.ReadOnlySpan values) { throw null; } + public static System.Numerics.Vector2 CreateScalar(float x) { throw null; } + public static System.Numerics.Vector2 CreateScalarUnsafe(float x) { throw null; } 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; } @@ -726,14 +764,16 @@ public partial struct Vector3 : System.IEquatable, Syst public static System.Numerics.Vector3 CopySign(System.Numerics.Vector3 value, System.Numerics.Vector3 sign) { throw null; } public static int Count(System.Numerics.Vector3 vector, float value) { throw null; } public static int CountWhereAllBitsSet(System.Numerics.Vector3 vector) { throw null; } - public static System.Numerics.Vector3 Create(float value) { throw null; } - public static System.Numerics.Vector3 Create(System.Numerics.Vector2 vector, float z) { throw null; } - public static System.Numerics.Vector3 Create(float x, float y, float z) { throw null; } - public static System.Numerics.Vector3 Create(System.ReadOnlySpan values) { throw null; } public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector3 Cos(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 Create(float value) { throw null; } + public static System.Numerics.Vector3 Create(System.Numerics.Vector2 vector, float z) { throw null; } + public static System.Numerics.Vector3 Create(float x, float y, float z) { throw null; } + public static System.Numerics.Vector3 Create(System.ReadOnlySpan values) { throw null; } + public static System.Numerics.Vector3 CreateScalar(float x) { throw null; } + public static System.Numerics.Vector3 CreateScalarUnsafe(float x) { throw null; } 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; } @@ -893,15 +933,17 @@ public partial struct Vector4 : System.IEquatable, Syst public static System.Numerics.Vector4 CopySign(System.Numerics.Vector4 value, System.Numerics.Vector4 sign) { throw null; } public static int Count(System.Numerics.Vector4 vector, float value) { throw null; } public static int CountWhereAllBitsSet(System.Numerics.Vector4 vector) { throw null; } + public readonly void CopyTo(float[] array) { } + public readonly void CopyTo(float[] array, int index) { } + public readonly void CopyTo(System.Span destination) { } + public static System.Numerics.Vector4 Cos(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 Create(float value) { throw null; } public static System.Numerics.Vector4 Create(System.Numerics.Vector2 vector, float z, float w) { throw null; } public static System.Numerics.Vector4 Create(System.Numerics.Vector3 vector, float w) { throw null; } public static System.Numerics.Vector4 Create(float x, float y, float z, float w) { throw null; } public static System.Numerics.Vector4 Create(System.ReadOnlySpan values) { throw null; } - public readonly void CopyTo(float[] array) { } - public readonly void CopyTo(float[] array, int index) { } - public readonly void CopyTo(System.Span destination) { } - public static System.Numerics.Vector4 Cos(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 CreateScalar(float x) { throw null; } + public static System.Numerics.Vector4 CreateScalarUnsafe(float x) { throw null; } 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; } diff --git a/src/libraries/System.Numerics.Vectors/tests/Matrix3x2Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Matrix3x2Tests.cs index 4374cb75b2f7a3..f06cc4e73dcfa8 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Matrix3x2Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Matrix3x2Tests.cs @@ -208,6 +208,8 @@ public void Matrix3x2InvertAffineTest() Assert.True(MathHelper.Equal(i, Matrix3x2.Identity)); } + + // A test for CreateRotation (float) [Fact] public void Matrix3x2CreateRotationTest() @@ -1081,5 +1083,138 @@ public unsafe void Matrix3x2FieldOffsetTest() Assert.Equal(new IntPtr(basePtr + 4), new IntPtr(&mat.M31)); Assert.Equal(new IntPtr(basePtr + 5), new IntPtr(&mat.M32)); } + + [Fact] + public void Matrix3x2CreateBroadcastScalarTest() + { + Matrix3x2 a = Matrix3x2.Create(float.Pi); + + Assert.Equal(Vector2.Create(float.Pi), a.X); + Assert.Equal(Vector2.Create(float.Pi), a.Y); + Assert.Equal(Vector2.Create(float.Pi), a.Z); + } + + [Fact] + public void Matrix3x2CreateBroadcastVectorTest() + { + Matrix3x2 a = Matrix3x2.Create(Vector2.Create(float.Pi, float.E)); + + Assert.Equal(Vector2.Create(float.Pi, float.E), a.X); + Assert.Equal(Vector2.Create(float.Pi, float.E), a.Y); + Assert.Equal(Vector2.Create(float.Pi, float.E), a.Z); + } + + [Fact] + public void Matrix3x2CreateVectorsTest() + { + Matrix3x2 a = Matrix3x2.Create( + Vector2.Create(11.0f, 12.0f), + Vector2.Create(21.0f, 22.0f), + Vector2.Create(31.0f, 32.0f) + ); + + Assert.Equal(Vector2.Create(11.0f, 12.0f), a.X); + Assert.Equal(Vector2.Create(21.0f, 22.0f), a.Y); + Assert.Equal(Vector2.Create(31.0f, 32.0f), a.Z); + } + + [Fact] + public void Matrix3x2GetElementTest() + { + Matrix3x2 a = GenerateTestMatrix(); + + Assert.Equal(a.M11, a.X.X); + Assert.Equal(a.M11, a[0, 0]); + Assert.Equal(a.M11, a.GetElement(0, 0)); + + Assert.Equal(a.M12, a.X.Y); + Assert.Equal(a.M12, a[0, 1]); + Assert.Equal(a.M12, a.GetElement(0, 1)); + + Assert.Equal(a.M21, a.Y.X); + Assert.Equal(a.M21, a[1, 0]); + Assert.Equal(a.M21, a.GetElement(1, 0)); + + Assert.Equal(a.M22, a.Y.Y); + Assert.Equal(a.M22, a[1, 1]); + Assert.Equal(a.M22, a.GetElement(1, 1)); + + Assert.Equal(a.M31, a.Z.X); + Assert.Equal(a.M31, a[2, 0]); + Assert.Equal(a.M31, a.GetElement(2, 0)); + + Assert.Equal(a.M32, a.Z.Y); + Assert.Equal(a.M32, a[2, 1]); + Assert.Equal(a.M32, a.GetElement(2, 1)); + } + + [Fact] + public void Matrix3x2GetRowTest() + { + Matrix3x2 a = GenerateTestMatrix(); + + Vector2 vx = new Vector2(a.M11, a.M12); + Assert.Equal(vx, a.X); + Assert.Equal(vx, a[0]); + Assert.Equal(vx, a.GetRow(0)); + + Vector2 vy = new Vector2(a.M21, a.M22); + Assert.Equal(vy, a.Y); + Assert.Equal(vy, a[1]); + Assert.Equal(vy, a.GetRow(1)); + + Vector2 vz = new Vector2(a.M31, a.M32); + Assert.Equal(vz, a.Z); + Assert.Equal(vz, a[2]); + Assert.Equal(vz, a.GetRow(2)); + } + + [Fact] + public void Matrix3x2WithElementTest() + { + Matrix3x2 a = Matrix3x2.Identity; + + a[0, 0] = 11.0f; + Assert.Equal(11.5f, a.WithElement(0, 0, 11.5f).M11); + Assert.Equal(11.0f, a.M11); + + a[0, 1] = 12.0f; + Assert.Equal(12.5f, a.WithElement(0, 1, 12.5f).M12); + Assert.Equal(12.0f, a.M12); + + a[1, 0] = 21.0f; + Assert.Equal(21.5f, a.WithElement(1, 0, 21.5f).M21); + Assert.Equal(21.0f, a.M21); + + a[1, 1] = 22.0f; + Assert.Equal(22.5f, a.WithElement(1, 1, 22.5f).M22); + Assert.Equal(22.0f, a.M22); + + a[2, 0] = 31.0f; + Assert.Equal(31.5f, a.WithElement(2, 0, 31.5f).M31); + Assert.Equal(31.0f, a.M31); + + a[2, 1] = 32.0f; + Assert.Equal(32.5f, a.WithElement(2, 1, 32.5f).M32); + Assert.Equal(32.0f, a.M32); + } + + [Fact] + public void Matrix3x2WithRowTest() + { + Matrix3x2 a = Matrix3x2.Identity; + + a[0] = Vector2.Create(11.0f, 12.0f); + Assert.Equal(Vector2.Create(11.5f, 12.5f), a.WithRow(0, Vector2.Create(11.5f, 12.5f)).X); + Assert.Equal(Vector2.Create(11.0f, 12.0f), a.X); + + a[1] = Vector2.Create(21.0f, 22.0f); + Assert.Equal(Vector2.Create(21.5f, 22.5f), a.WithRow(1, Vector2.Create(21.5f, 22.5f)).Y); + Assert.Equal(Vector2.Create(21.0f, 22.0f), a.Y); + + a[2] = Vector2.Create(31.0f, 32.0f); + Assert.Equal(Vector2.Create(31.5f, 32.5f), a.WithRow(2, Vector2.Create(31.5f, 32.5f)).Z); + Assert.Equal(Vector2.Create(31.0f, 32.0f), a.Z); + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Matrix4x4Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Matrix4x4Tests.cs index fa52f037b22cd5..87e035215ede69 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Matrix4x4Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Matrix4x4Tests.cs @@ -3168,5 +3168,231 @@ public void PerspectiveOffCenterFarPlaneAtInfinityTest() Assert.Equal(-1.0f, m.M33); Assert.Equal(-nearPlaneDistance, m.M43); } + + [Fact] + public void Matrix4x4CreateBroadcastScalarTest() + { + Matrix4x4 a = Matrix4x4.Create(float.Pi); + + Assert.Equal(Vector4.Create(float.Pi), a.X); + Assert.Equal(Vector4.Create(float.Pi), a.Y); + Assert.Equal(Vector4.Create(float.Pi), a.Z); + Assert.Equal(Vector4.Create(float.Pi), a.W); + } + + [Fact] + public void Matrix4x4CreateBroadcastVectorTest() + { + Matrix4x4 a = Matrix4x4.Create(Vector4.Create(float.Pi, float.E, float.PositiveInfinity, float.NegativeInfinity)); + + Assert.Equal(Vector4.Create(float.Pi, float.E, float.PositiveInfinity, float.NegativeInfinity), a.X); + Assert.Equal(Vector4.Create(float.Pi, float.E, float.PositiveInfinity, float.NegativeInfinity), a.Y); + Assert.Equal(Vector4.Create(float.Pi, float.E, float.PositiveInfinity, float.NegativeInfinity), a.Z); + Assert.Equal(Vector4.Create(float.Pi, float.E, float.PositiveInfinity, float.NegativeInfinity), a.W); + } + + [Fact] + public void Matrix4x4CreateVectorsTest() + { + Matrix4x4 a = Matrix4x4.Create( + Vector4.Create(11.0f, 12.0f, 13.0f, 14.0f), + Vector4.Create(21.0f, 22.0f, 23.0f, 24.0f), + Vector4.Create(31.0f, 32.0f, 33.0f, 34.0f), + Vector4.Create(41.0f, 42.0f, 43.0f, 44.0f) + ); + + Assert.Equal(Vector4.Create(11.0f, 12.0f, 13.0f, 14.0f), a.X); + Assert.Equal(Vector4.Create(21.0f, 22.0f, 23.0f, 24.0f), a.Y); + Assert.Equal(Vector4.Create(31.0f, 32.0f, 33.0f, 34.0f), a.Z); + Assert.Equal(Vector4.Create(41.0f, 42.0f, 43.0f, 44.0f), a.W); + } + + [Fact] + public void Matrix4x4GetElementTest() + { + Matrix4x4 a = GenerateTestMatrix(); + + Assert.Equal(a.M11, a.X.X); + Assert.Equal(a.M11, a[0, 0]); + Assert.Equal(a.M11, a.GetElement(0, 0)); + + Assert.Equal(a.M12, a.X.Y); + Assert.Equal(a.M12, a[0, 1]); + Assert.Equal(a.M12, a.GetElement(0, 1)); + + Assert.Equal(a.M13, a.X.Z); + Assert.Equal(a.M13, a[0, 2]); + Assert.Equal(a.M13, a.GetElement(0, 2)); + + Assert.Equal(a.M14, a.X.W); + Assert.Equal(a.M14, a[0, 3]); + Assert.Equal(a.M14, a.GetElement(0, 3)); + + Assert.Equal(a.M21, a.Y.X); + Assert.Equal(a.M21, a[1, 0]); + Assert.Equal(a.M21, a.GetElement(1, 0)); + + Assert.Equal(a.M22, a.Y.Y); + Assert.Equal(a.M22, a[1, 1]); + Assert.Equal(a.M22, a.GetElement(1, 1)); + + Assert.Equal(a.M23, a.Y.Z); + Assert.Equal(a.M23, a[1, 2]); + Assert.Equal(a.M23, a.GetElement(1, 2)); + + Assert.Equal(a.M24, a.Y.W); + Assert.Equal(a.M24, a[1, 3]); + Assert.Equal(a.M24, a.GetElement(1, 3)); + + Assert.Equal(a.M31, a.Z.X); + Assert.Equal(a.M31, a[2, 0]); + Assert.Equal(a.M31, a.GetElement(2, 0)); + + Assert.Equal(a.M32, a.Z.Y); + Assert.Equal(a.M32, a[2, 1]); + Assert.Equal(a.M32, a.GetElement(2, 1)); + + Assert.Equal(a.M33, a.Z.Z); + Assert.Equal(a.M33, a[2, 2]); + Assert.Equal(a.M33, a.GetElement(2, 2)); + + Assert.Equal(a.M34, a.Z.W); + Assert.Equal(a.M34, a[2, 3]); + Assert.Equal(a.M34, a.GetElement(2, 3)); + + Assert.Equal(a.M41, a.W.X); + Assert.Equal(a.M41, a[3, 0]); + Assert.Equal(a.M41, a.GetElement(3, 0)); + + Assert.Equal(a.M42, a.W.Y); + Assert.Equal(a.M42, a[3, 1]); + Assert.Equal(a.M42, a.GetElement(3, 1)); + + Assert.Equal(a.M43, a.W.Z); + Assert.Equal(a.M43, a[3, 2]); + Assert.Equal(a.M43, a.GetElement(3, 2)); + + Assert.Equal(a.M44, a.W.W); + Assert.Equal(a.M44, a[3, 3]); + Assert.Equal(a.M44, a.GetElement(3, 3)); + } + + [Fact] + public void Matrix4x4GetRowTest() + { + Matrix4x4 a = GenerateTestMatrix(); + + Vector4 vx = new Vector4(a.M11, a.M12, a.M13, a.M14); + Assert.Equal(vx, a.X); + Assert.Equal(vx, a[0]); + Assert.Equal(vx, a.GetRow(0)); + + Vector4 vy = new Vector4(a.M21, a.M22, a.M23, a.M24); + Assert.Equal(vy, a.Y); + Assert.Equal(vy, a[1]); + Assert.Equal(vy, a.GetRow(1)); + + Vector4 vz = new Vector4(a.M31, a.M32, a.M33, a.M34); + Assert.Equal(vz, a.Z); + Assert.Equal(vz, a[2]); + Assert.Equal(vz, a.GetRow(2)); + + Vector4 vw = new Vector4(a.M41, a.M42, a.M43, a.M44); + Assert.Equal(vw, a.W); + Assert.Equal(vw, a[3]); + Assert.Equal(vw, a.GetRow(3)); + } + + [Fact] + public void Matrix4x4WithElementTest() + { + Matrix4x4 a = Matrix4x4.Identity; + + a[0, 0] = 11.0f; + Assert.Equal(11.5f, a.WithElement(0, 0, 11.5f).M11); + Assert.Equal(11.0f, a.M11); + + a[0, 1] = 12.0f; + Assert.Equal(12.5f, a.WithElement(0, 1, 12.5f).M12); + Assert.Equal(12.0f, a.M12); + + a[0, 2] = 13.0f; + Assert.Equal(13.5f, a.WithElement(0, 2, 13.5f).M13); + Assert.Equal(13.0f, a.M13); + + a[0, 3] = 14.0f; + Assert.Equal(14.5f, a.WithElement(0, 3, 14.5f).M14); + Assert.Equal(14.0f, a.M14); + + a[1, 0] = 21.0f; + Assert.Equal(21.5f, a.WithElement(1, 0, 21.5f).M21); + Assert.Equal(21.0f, a.M21); + + a[1, 1] = 22.0f; + Assert.Equal(22.5f, a.WithElement(1, 1, 22.5f).M22); + Assert.Equal(22.0f, a.M22); + + a[1, 2] = 23.0f; + Assert.Equal(23.5f, a.WithElement(1, 2, 23.5f).M23); + Assert.Equal(23.0f, a.M23); + + a[1, 3] = 24.0f; + Assert.Equal(24.5f, a.WithElement(1, 3, 24.5f).M24); + Assert.Equal(24.0f, a.M24); + + a[2, 0] = 31.0f; + Assert.Equal(31.5f, a.WithElement(2, 0, 31.5f).M31); + Assert.Equal(31.0f, a.M31); + + a[2, 1] = 32.0f; + Assert.Equal(32.5f, a.WithElement(2, 1, 32.5f).M32); + Assert.Equal(32.0f, a.M32); + + a[2, 2] = 33.0f; + Assert.Equal(33.5f, a.WithElement(2, 2, 33.5f).M33); + Assert.Equal(33.0f, a.M33); + + a[2, 3] = 34.0f; + Assert.Equal(34.5f, a.WithElement(2, 3, 34.5f).M34); + Assert.Equal(34.0f, a.M34); + + a[3, 0] = 41.0f; + Assert.Equal(41.5f, a.WithElement(3, 0, 41.5f).M41); + Assert.Equal(41.0f, a.M41); + + a[3, 1] = 42.0f; + Assert.Equal(42.5f, a.WithElement(3, 1, 42.5f).M42); + Assert.Equal(42.0f, a.M42); + + a[3, 2] = 43.0f; + Assert.Equal(43.5f, a.WithElement(3, 2, 43.5f).M43); + Assert.Equal(43.0f, a.M43); + + a[3, 3] = 44.0f; + Assert.Equal(44.5f, a.WithElement(3, 3, 44.5f).M44); + Assert.Equal(44.0f, a.M44); + } + + [Fact] + public void Matrix4x4WithRowTest() + { + Matrix4x4 a = Matrix4x4.Identity; + + a[0] = Vector4.Create(11.0f, 12.0f, 13.0f, 14.0f); + Assert.Equal(Vector4.Create(11.5f, 12.5f, 13.5f, 14.5f), a.WithRow(0, Vector4.Create(11.5f, 12.5f, 13.5f, 14.5f)).X); + Assert.Equal(Vector4.Create(11.0f, 12.0f, 13.0f, 14.0f), a.X); + + a[1] = Vector4.Create(21.0f, 22.0f, 23.0f, 24.0f); + Assert.Equal(Vector4.Create(21.5f, 22.5f, 23.5f, 24.5f), a.WithRow(1, Vector4.Create(21.5f, 22.5f, 23.5f, 24.5f)).Y); + Assert.Equal(Vector4.Create(21.0f, 22.0f, 23.0f, 24.0f), a.Y); + + a[2] = Vector4.Create(31.0f, 32.0f, 33.0f, 34.0f); + Assert.Equal(Vector4.Create(31.5f, 32.5f, 33.5f, 34.5f), a.WithRow(2, Vector4.Create(31.5f, 32.5f, 33.5f, 34.5f)).Z); + Assert.Equal(Vector4.Create(31.0f, 32.0f, 33.0f, 34.0f), a.Z); + + a[3] = Vector4.Create(41.0f, 42.0f, 43.0f, 44.0f); + Assert.Equal(Vector4.Create(41.5f, 42.5f, 43.5f, 44.5f), a.WithRow(3, Vector4.Create(41.5f, 42.5f, 43.5f, 44.5f)).W); + Assert.Equal(Vector4.Create(41.0f, 42.0f, 43.0f, 44.0f), a.W); + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs index 53a0ed94db0527..d605f6dbd14471 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs @@ -1849,5 +1849,52 @@ public void WithElementTest(float x, float y) Assert.Equal(x, vector.X); Assert.Equal(y, vector.Y); } + + [Theory] + [InlineData(1.0f, 2.0f)] + [InlineData(5.0f, 6.0f)] + public void AsVector3Test(float x, float y) + { + var vector = Vector2.Create(x, y).AsVector3(); + + Assert.Equal(x, vector.X); + Assert.Equal(y, vector.Y); + Assert.Equal(0, vector.Z); + } + + [Theory] + [InlineData(1.0f, 2.0f)] + [InlineData(5.0f, 6.0f)] + public void AsVector3UnsafeTest(float x, float y) + { + var vector = Vector2.Create(x, y).AsVector3Unsafe(); + + Assert.Equal(x, vector.X); + Assert.Equal(y, vector.Y); + } + + [Fact] + public void CreateScalarTest() + { + var vector = Vector2.CreateScalar(float.Pi); + + Assert.Equal(float.Pi, vector.X); + Assert.Equal(0, vector.Y); + + vector = Vector2.CreateScalar(float.E); + + Assert.Equal(float.E, vector.X); + Assert.Equal(0, vector.Y); + } + + [Fact] + public void CreateScalarUnsafeTest() + { + var vector = Vector2.CreateScalarUnsafe(float.Pi); + Assert.Equal(float.Pi, vector.X); + + vector = Vector2.CreateScalarUnsafe(float.E); + Assert.Equal(float.E, vector.X); + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs index 880cf4be75e7cb..bcc025d34f826f 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs @@ -1876,5 +1876,42 @@ public void WithElementTest(float x, float y, float z) Assert.Equal(y, vector.Y); Assert.Equal(z, vector.Z); } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f)] + [InlineData(5.0f, 6.0f, 7.0f)] + public void AsVector2Test(float x, float y, float z) + { + var vector = Vector3.Create(x, y, z).AsVector2(); + + Assert.Equal(x, vector.X); + Assert.Equal(y, vector.Y); + } + + [Fact] + public void CreateScalarTest() + { + var vector = Vector3.CreateScalar(float.Pi); + + Assert.Equal(float.Pi, vector.X); + Assert.Equal(0, vector.Y); + Assert.Equal(0, vector.Z); + + vector = Vector3.CreateScalar(float.E); + + Assert.Equal(float.E, vector.X); + Assert.Equal(0, vector.Y); + Assert.Equal(0, vector.Z); + } + + [Fact] + public void CreateScalarUnsafeTest() + { + var vector = Vector3.CreateScalarUnsafe(float.Pi); + Assert.Equal(float.Pi, vector.X); + + vector = Vector3.CreateScalarUnsafe(float.E); + Assert.Equal(float.E, vector.X); + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs index b89616e47a2d69..fd983119d2acf8 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs @@ -2295,5 +2295,33 @@ public void WithElementTest(float x, float y, float z, float w) Assert.Equal(z, vector.Z); Assert.Equal(w, vector.W); } + + [Fact] + public void CreateScalarTest() + { + var vector = Vector4.CreateScalar(float.Pi); + + Assert.Equal(float.Pi, vector.X); + Assert.Equal(0, vector.Y); + Assert.Equal(0, vector.Z); + Assert.Equal(0, vector.W); + + vector = Vector4.CreateScalar(float.E); + + Assert.Equal(float.E, vector.X); + Assert.Equal(0, vector.Y); + Assert.Equal(0, vector.Z); + Assert.Equal(0, vector.W); + } + + [Fact] + public void CreateScalarUnsafeTest() + { + var vector = Vector4.CreateScalarUnsafe(float.Pi); + Assert.Equal(float.Pi, vector.X); + + vector = Vector4.CreateScalarUnsafe(float.E); + Assert.Equal(float.E, vector.X); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.Impl.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.Impl.cs index fd98190e2125d4..09815c5089a570 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.Impl.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.Impl.cs @@ -15,9 +15,6 @@ public partial struct Matrix3x2 // syntax. We do this because it saves roughly 8-bytes of IL per method which // in turn helps improve inlining chances. - internal const uint RowCount = 3; - internal const uint ColumnCount = 2; - [UnscopedRef] [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ref Impl AsImpl() => ref Unsafe.As(ref this); @@ -38,80 +35,6 @@ internal struct Impl : IEquatable public Vector2 Y; public Vector2 Z; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Init(float m11, float m12, - float m21, float m22, - float m31, float m32) - { - X = Vector2.Create(m11, m12); - Y = Vector2.Create(m21, m22); - Z = Vector2.Create(m31, m32); - } - - public static Impl Identity - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - Impl result; - - result.X = Vector2.UnitX; - result.Y = Vector2.UnitY; - result.Z = Vector2.Zero; - - return result; - } - } - - public float this[int row, int column] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get - { - if ((uint)row >= RowCount) - { - ThrowHelper.ThrowArgumentOutOfRangeException(); - } - return Unsafe.Add(ref Unsafe.AsRef(in X), row)[column]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set - { - if ((uint)row >= RowCount) - { - ThrowHelper.ThrowArgumentOutOfRangeException(); - } - Unsafe.Add(ref X, row)[column] = value; - } - } - - public readonly bool IsIdentity - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return (X == Vector2.UnitX) - && (Y == Vector2.UnitY) - && (Z == Vector2.Zero); - } - } - - public Vector2 Translation - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get - { - return Z; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set - { - Z = value; - } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl operator +(in Impl left, in Impl right) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.cs index 0c84691bce6bd4..c1db9962a56fa6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.cs @@ -13,6 +13,9 @@ namespace System.Numerics [Intrinsic] public partial struct Matrix3x2 : IEquatable { + private const int RowCount = 3; + private const int ColumnCount = 2; + // In an ideal world, we'd have 3x Vector2 fields. However, Matrix3x2 was shipped with // 6x public float fields and as such we cannot change the "backing" fields without it being // a breaking change. Likewise, we cannot switch to using something like ExplicitLayout @@ -24,37 +27,41 @@ public partial struct Matrix3x2 : IEquatable // at the relevant points. /// The first element of the first row. + /// This element exists at index: [0, 0] and is part of row . public float M11; /// The second element of the first row. + /// This element exists at index: [0, 1] and is part of row . public float M12; /// The first element of the second row. + /// This element exists at index: [1, 0] and is part of row . public float M21; /// The second element of the second row. + /// This element exists at index: [1, 1] and is part of row . public float M22; /// The first element of the third row. + /// This element exists at index: [2, 0] and is part of row . public float M31; /// The second element of the third row. + /// This element exists at index: [2, 1] and is part of row . public float M32; - /// Creates a 3x2 matrix from the specified components. - /// The value to assign to the first element in the first row. - /// The value to assign to the second element in the first row. - /// The value to assign to the first element in the second row. - /// The value to assign to the second element in the second row. - /// The value to assign to the first element in the third row. - /// The value to assign to the second element in the third row. + /// Initializes a using the specified elements. + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . public Matrix3x2(float m11, float m12, float m21, float m22, float m31, float m32) { - Unsafe.SkipInit(out this); - - AsImpl().Init( + this = Create( m11, m12, m21, m22, m31, m32 @@ -62,48 +69,260 @@ public Matrix3x2(float m11, float m12, } /// Gets the multiplicative identity matrix. - /// The multiplicative identify matrix. + /// The multiplicative identity matrix. public static Matrix3x2 Identity { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => Impl.Identity.AsM3x2(); + get => Create(Vector2.UnitX, Vector2.UnitY, Vector2.Zero); } - /// Gets or sets the element at the specified indices. - /// The index of the row containing the element to get or set. - /// The index of the column containing the element to get or set. - /// The element at [][]. - /// - /// was less than zero or greater than the number of rows. - /// -or- - /// was less than zero or greater than the number of columns. - /// - public float this[int row, int column] + /// Gets a value that indicates whether the current matrix is an identity matrix. + /// if the current matrix is an identity matrix; otherwise, . + public readonly bool IsIdentity { [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get => AsROImpl()[row, column]; + get => (X == Vector2.UnitX) + && (Y == Vector2.UnitY) + && (Z == Vector2.Zero); + } + + /// Gets or sets the translation component of this matrix. + /// The translation component is stored as . + public Vector2 Translation + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => Z; [MethodImpl(MethodImplOptions.AggressiveInlining)] - set => AsImpl()[row, column] = value; + set => Z = value; } - /// Gets a value that indicates whether the current matrix is the identity matrix. - /// if the current matrix is the identity matrix; otherwise, . - public readonly bool IsIdentity + /// Gets or sets the first row of the matrix. + /// This row comprises and ; it exists at index: [0]. + public Vector2 X { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => AsROImpl().IsIdentity; + readonly get => AsROImpl().X; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => AsImpl().X = value; } - /// Gets or sets the translation component of this matrix. - /// The translation component of the current instance. - public Vector2 Translation + /// Gets or sets the second row of the matrix. + /// This row comprises and ; it exists at index: [1]. + public Vector2 Y + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => AsROImpl().Y; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => AsImpl().Y = value; + } + + /// Gets or sets the third row of the matrix. + /// This row comprises and ; it exists at index: [2]. + public Vector2 Z + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => AsROImpl().Z; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => AsImpl().Z = value; + } + + /// Gets or sets the row at the specified index. + /// The index of the row to get or set. + /// The row at index: []. + /// was less than zero or greater than or equal to the number of rows (3). + public Vector2 this[int row] + { + // When row is a known constant, we can use a switch to get + // optimal codegen as we are likely coming from register. + // + // However, if either is non constant we're going to end up having + // to touch memory so just directly compute the relevant index. + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get + { + if (RuntimeHelpers.IsKnownConstant(row)) + { + switch (row) + { + case 0: + { + return X; + } + + case 1: + { + return Y; + } + + case 2: + { + return Z; + } + + default: + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + return default; + } + } + } + else + { + if ((uint)row >= RowCount) + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + return Unsafe.Add(ref Unsafe.AsRef(in AsROImpl()).X, row); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + if (RuntimeHelpers.IsKnownConstant(row)) + { + switch (row) + { + case 0: + { + X = value; + break; + } + + case 1: + { + Y = value; + break; + } + + case 2: + { + Z = value; + break; + } + + default: + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + break; + } + } + } + else + { + if ((uint)row >= RowCount) + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + Unsafe.Add(ref AsImpl().X, row) = value; + } + } + } + + /// Gets or sets the element at the specified row and column. + /// The index of the row containing the element to get or set. + /// The index of the column containing the element to get or set. + /// The element at index: [, ]. + /// + /// was less than zero or greater than or equal to the number of rows (3). + /// -or- + /// was less than zero or greater than or equal to the number of columns (2). + /// + public float this[int row, int column] { + // When both row and column are known constants, we can use a switch to + // get optimal codegen as we are likely coming from register. + // + // However, if either is non constant we're going to end up having to + // touch memory so just directly compute the relevant index. + // + // The JIT will elide any dead code paths if only one of the inputs is constant. + [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get => AsROImpl().Translation; + readonly get + { + if (RuntimeHelpers.IsKnownConstant(row) && RuntimeHelpers.IsKnownConstant(column)) + { + switch (row) + { + case 0: + { + return X.GetElement(column); + } + + case 1: + { + return Y.GetElement(column); + } + + case 2: + { + return Z.GetElement(column); + } + + default: + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + return default; + } + } + } + else + { + if (((uint)row >= RowCount) || ((uint)column >= ColumnCount)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + return Unsafe.Add(ref Unsafe.AsRef(in M11), (row * ColumnCount) + column); + } + } [MethodImpl(MethodImplOptions.AggressiveInlining)] - set => AsImpl().Translation = value; + set + { + if (RuntimeHelpers.IsKnownConstant(row) && RuntimeHelpers.IsKnownConstant(column)) + { + switch (row) + { + case 0: + { + X = X.WithElement(column, value); + break; + } + + case 1: + { + Y = Y.WithElement(column, value); + break; + } + + case 2: + { + Z = Z.WithElement(column, value); + break; + } + + default: + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + break; + } + } + } + else + { + if (((uint)row >= RowCount) || ((uint)column >= ColumnCount)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + Unsafe.Add(ref M11, (row * ColumnCount) + column) = value; + } + } } /// Adds each element in one matrix with its corresponding element in a second matrix. @@ -174,6 +393,52 @@ public Vector2 Translation public static Matrix3x2 Add(Matrix3x2 value1, Matrix3x2 value2) => (value1.AsImpl() + value2.AsImpl()).AsM3x2(); + /// Creates a whose 6 elements are set to the specified value. + /// The value to assign to all 6 elements. + /// A whose 6 elements are set to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix3x2 Create(float value) => Create(Vector2.Create(value)); + + /// Creates a whose 3 rows are set to the specified value. + /// The value to assign to all 3 rows. + /// A whose 3 rows are set to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix3x2 Create(Vector2 value) => Create(value, value, value); + + /// Creates a from the specified rows. + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// A whose rows are set to the specified values. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix3x2 Create(Vector2 x, Vector2 y, Vector2 z) + { + Unsafe.SkipInit(out Matrix3x2 result); + + result.X = x; + result.Y = y; + result.Z = z; + + return result; + } + + /// Creates a from the specified elements. + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// A whose elements are set to the specified values. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix3x2 Create(float m11, float m12, + float m21, float m22, + float m31, float m32) => Create( + Vector2.Create(m11, m12), + Vector2.Create(m21, m22), + Vector2.Create(m31, m32) + ); + /// Creates a rotation matrix using the given rotation in radians. /// The amount of rotation, in radians. /// The rotation matrix. @@ -314,7 +579,7 @@ public static Matrix3x2 Subtract(Matrix3x2 value1, Matrix3x2 value2) public override readonly bool Equals([NotNullWhen(true)] object? obj) => AsROImpl().Equals(obj); - /// Returns a value that indicates whether this instance and another 3x2 matrix are equal. + /// Returns a value that indicates whether this instance and another are equal. /// The other matrix. /// if the two matrices are equal; otherwise, . /// Two matrices are equal if all their corresponding elements are equal. @@ -329,6 +594,25 @@ public readonly bool Equals(Matrix3x2 other) public readonly float GetDeterminant() => AsROImpl().GetDeterminant(); + /// Gets the element at the specified row and column. + /// The index of the row containing the element to get. + /// The index of the column containing the element to get. + /// The element at index: [, ]. + /// + /// was less than zero or greater than or equal to the number of rows (3). + /// -or- + /// was less than zero or greater than or equal to the number of columns (2). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly float GetElement(int row, int column) => this[row, column]; + + /// Gets or sets the row at the specified index. + /// The index of the row to get. + /// The row at index: []. + /// was less than zero or greater than or equal to the number of rows (3). + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Vector2 GetRow(int index) => this[index]; + /// Returns the hash code for this instance. /// The hash code. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -340,5 +624,36 @@ public override readonly int GetHashCode() /// The numeric values in the returned string are formatted by using the conventions of the current culture. For example, for the en-US culture, the returned string might appear as { {M11:1.1 M12:1.2} {M21:2.1 M22:2.2} {M31:3.1 M32:3.2} }. public override readonly string ToString() => $"{{ {{M11:{M11} M12:{M12}}} {{M21:{M21} M22:{M22}}} {{M31:{M31} M32:{M32}}} }}"; + + /// Creates a new with the element at the specified row and column set to the given value and the remaining elements set to the same value as that in the current matrix. + /// The index of the row containing the element to replace. + /// The index of the column containing the element to replace. + /// The value to assign to the element at index: [, ]. + /// A with the value of the element at index: [, ] set to and the remaining elements set to the same value as that in the current matrix. + /// + /// was less than zero or greater than or equal to the number of rows (3). + /// -or- + /// was less than zero or greater than or equal to the number of columns (2). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Matrix3x2 WithElement(int row, int column, float value) + { + Matrix3x2 result = this; + result[row, column] = value; + return result; + } + + /// Creates a new with the row at the specified index set to the given value and the remaining rows set to the same value as that in the current matrix. + /// The index of the row to replace. + /// The value to assign to the row at index: []. + /// A with the value of the row at index: [] set to and the remaining rows set to the same value as that in the current matrix. + /// was less than zero or greater than or equal to the number of rows (3). + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Matrix3x2 WithRow(int index, Vector2 value) + { + Matrix3x2 result = this; + result[index] = value; + return result; + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.Impl.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.Impl.cs index 5ca3cfeb40cc6b..708d1e03b1b945 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.Impl.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.Impl.cs @@ -18,9 +18,6 @@ public partial struct Matrix4x4 // syntax. We do this because it saves roughly 8-bytes of IL per method which // in turn helps improve inlining chances. - internal const uint RowCount = 4; - internal const uint ColumnCount = 4; - [UnscopedRef] [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ref Impl AsImpl() => ref Unsafe.As(ref this); @@ -44,90 +41,6 @@ internal struct Impl : IEquatable public Vector4 Z; public Vector4 W; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Init(float m11, float m12, float m13, float m14, - float m21, float m22, float m23, float m24, - float m31, float m32, float m33, float m34, - float m41, float m42, float m43, float m44) - { - X = Vector4.Create(m11, m12, m13, m14); - Y = Vector4.Create(m21, m22, m23, m24); - Z = Vector4.Create(m31, m32, m33, m34); - W = Vector4.Create(m41, m42, m43, m44); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Init(in Matrix3x2.Impl value) - { - X = Vector4.Create(value.X, 0, 0); - Y = Vector4.Create(value.Y, 0, 0); - Z = Vector4.UnitZ; - W = Vector4.Create(value.Z, 0, 1); - } - - public static Impl Identity - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - Impl result; - - result.X = Vector4.UnitX; - result.Y = Vector4.UnitY; - result.Z = Vector4.UnitZ; - result.W = Vector4.UnitW; - - return result; - } - } - - public float this[int row, int column] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get - { - if ((uint)row >= RowCount) - { - ThrowHelper.ThrowArgumentOutOfRangeException(); - } - return Unsafe.Add(ref Unsafe.AsRef(in X), row)[column]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set - { - if ((uint)row >= RowCount) - { - ThrowHelper.ThrowArgumentOutOfRangeException(); - } - Unsafe.Add(ref X, row)[column] = value; - } - } - - public readonly bool IsIdentity - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return (X == Vector4.UnitX) - && (Y == Vector4.UnitY) - && (Z == Vector4.UnitZ) - && (W == Vector4.UnitW); - } - } - - public Vector3 Translation - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get => W.AsVector3(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set - { - W = Vector4.Create(value, W.W); - } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl operator +(in Impl left, in Impl right) { @@ -159,19 +72,6 @@ public Vector3 Translation || (left.W != right.W); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Impl operator *(in Impl left, in Impl right) - { - Impl result; - - result.X = Vector4.Transform(left.X, in right); - result.Y = Vector4.Transform(left.Y, in right); - result.Z = Vector4.Transform(left.Z, in right); - result.W = Vector4.Transform(left.W, in right); - - return result; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Impl operator *(in Impl left, float right) { @@ -1049,7 +949,7 @@ public static Impl CreateWorld(in Vector3 position, in Vector3 forward, in Vecto [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe bool Decompose(in Impl matrix, out Vector3 scale, out Quaternion rotation, out Vector3 translation) { - Impl matTemp = Identity; + Impl matTemp = Matrix4x4.Identity.AsImpl(); Vector3* canonicalBasis = stackalloc Vector3[3] { Vector3.UnitX, diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs index 7e92e304ef9c2b..2e0c6f4c411ca6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs @@ -13,6 +13,9 @@ namespace System.Numerics [Intrinsic] public partial struct Matrix4x4 : IEquatable { + internal const int RowCount = 4; + internal const int ColumnCount = 4; + // In an ideal world, we'd have 4x Vector4 fields. However, Matrix4x4 was shipped with // 16x public float fields and as such we cannot change the "backing" fields without it being // a breaking change. Likewise, we cannot switch to using something like ExplicitLayout @@ -24,78 +27,92 @@ public partial struct Matrix4x4 : IEquatable // at the relevant points. /// The first element of the first row. + /// This element exists at index: [0, 0] and is part of row . public float M11; /// The second element of the first row. + /// This element exists at index: [0, 1] and is part of row . public float M12; /// The third element of the first row. + /// This element exists at index: [0, 2] and is part of row . public float M13; /// The fourth element of the first row. + /// This element exists at index: [0, 3] and is part of row . public float M14; /// The first element of the second row. + /// This element exists at index: [1, 0] and is part of row . public float M21; /// The second element of the second row. + /// This element exists at index: [1, 1] and is part of row . public float M22; /// The third element of the second row. + /// This element exists at index: [1, 2] and is part of row . public float M23; /// The fourth element of the second row. + /// This element exists at index: [1, 3] and is part of row . public float M24; /// The first element of the third row. + /// This element exists at index: [2, 0] and is part of row . public float M31; /// The second element of the third row. + /// This element exists at index: [2, 1] and is part of row . public float M32; /// The third element of the third row. + /// This element exists at index: [2, 2] and is part of row . public float M33; /// The fourth element of the third row. + /// This element exists at index: [2, 3] and is part of row . public float M34; /// The first element of the fourth row. + /// This element exists at index: [3, 0] and is part of row . public float M41; /// The second element of the fourth row. + /// This element exists at index: [3, 1] and is part of row . public float M42; /// The third element of the fourth row. + /// This element exists at index: [3, 2] and is part of row . public float M43; /// The fourth element of the fourth row. + /// This element exists at index: [3, 3] and is part of row . public float M44; - /// Creates a 4x4 matrix from the specified components. - /// The value to assign to the first element in the first row. - /// The value to assign to the second element in the first row. - /// The value to assign to the third element in the first row. - /// The value to assign to the fourth element in the first row. - /// The value to assign to the first element in the second row. - /// The value to assign to the second element in the second row. - /// The value to assign to the third element in the second row. - /// The value to assign to the third element in the second row. - /// The value to assign to the first element in the third row. - /// The value to assign to the second element in the third row. - /// The value to assign to the third element in the third row. - /// The value to assign to the fourth element in the third row. - /// The value to assign to the first element in the fourth row. - /// The value to assign to the second element in the fourth row. - /// The value to assign to the third element in the fourth row. - /// The value to assign to the fourth element in the fourth row. + /// Initializes a using the specified elements. + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . public Matrix4x4(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44) { - Unsafe.SkipInit(out this); - - AsImpl().Init( + this = Create( m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, @@ -103,13 +120,12 @@ public Matrix4x4(float m11, float m12, float m13, float m14, ); } - /// Creates a object from a specified object. - /// A 3x2 matrix. - /// This constructor creates a 4x4 matrix whose , , , , , , , and components are zero, and whose and components are one. + /// Initializes a using the specified . + /// The to assign to the first two elements of , , and . + /// The last two elements of , , and are initialized to zero; while is initialized to . public Matrix4x4(Matrix3x2 value) { - Unsafe.SkipInit(out this); - AsImpl().Init(in value.AsImpl()); + this = Create(value); } /// Gets the multiplicative identity matrix. @@ -117,44 +133,298 @@ public Matrix4x4(Matrix3x2 value) public static Matrix4x4 Identity { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => Impl.Identity.AsM4x4(); + get => Create(Vector4.UnitX, Vector4.UnitY, Vector4.UnitZ, Vector4.UnitW); } - /// Gets or sets the element at the specified indices. - /// The index of the row containing the element to get or set. - /// The index of the column containing the element to get or set. - /// The element at [][]. - /// - /// was less than zero or greater than the number of rows. - /// -or- - /// was less than zero or greater than the number of columns. - /// - public float this[int row, int column] + /// Indicates whether the current matrix is the identity matrix. + /// if the current matrix is the identity matrix; otherwise, . + public readonly bool IsIdentity { [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get => AsROImpl()[row, column]; + get => (X == Vector4.UnitX) + && (Y == Vector4.UnitY) + && (Z == Vector4.UnitZ) + && (W == Vector4.UnitW); + } + + /// Gets or sets the translation component of this matrix. + /// The translation component is stored as first 3 columns of . + public Vector3 Translation + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => W.AsVector3(); [MethodImpl(MethodImplOptions.AggressiveInlining)] - set => AsImpl()[row, column] = value; + set => W = Vector4.Create(value, W.W); } - /// Indicates whether the current matrix is the identity matrix. - /// if the current matrix is the identity matrix; otherwise, . - public readonly bool IsIdentity + /// Gets or sets the first row of the matrix. + /// This row comprises , , , and ; it exists at index: [0]. + public Vector4 X + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => AsROImpl().X; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => AsImpl().X = value; + } + + /// Gets or sets the second row of the matrix. + /// This row comprises , , , and ; it exists at index: [1]. + public Vector4 Y { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => AsROImpl().IsIdentity; + readonly get => AsROImpl().Y; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => AsImpl().Y = value; } - /// Gets or sets the translation component of this matrix. - /// The translation component of the current instance. - public Vector3 Translation + /// Gets or sets the third row of the matrix. + /// This row comprises , , , and ; it exists at index: [2]. + public Vector4 Z + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => AsROImpl().Z; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => AsImpl().Z = value; + } + + /// Gets or sets the fourth row of the matrix. + /// This row comprises , , , and ; it exists at index: [3]. + public Vector4 W { [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get => AsROImpl().Translation; + readonly get => AsROImpl().W; [MethodImpl(MethodImplOptions.AggressiveInlining)] - set => AsImpl().Translation = value; + set => AsImpl().W = value; + } + + /// Gets or sets the row at the specified index. + /// The index of the row to get or set. + /// The row that at index: []. + /// was less than zero or greater than or equal to the number of rows (4). + public Vector4 this[int row] + { + // When row is a known constant, we can use a switch to get + // optimal codegen as we are likely coming from register. + // + // However, if either is non constant we're going to end up having + // to touch memory so just directly compute the relevant index. + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get + { + ref readonly Impl impl = ref AsROImpl(); + + if (RuntimeHelpers.IsKnownConstant(row)) + { + switch (row) + { + case 0: + { + return impl.X; + } + + case 1: + { + return impl.Y; + } + + case 2: + { + return impl.Z; + } + + case 3: + { + return impl.W; + } + + default: + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + return default; + } + } + } + else + { + if ((uint)row >= RowCount) + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + return Unsafe.Add(ref Unsafe.AsRef(in impl.X), row); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + ref Impl impl = ref AsImpl(); + + if (RuntimeHelpers.IsKnownConstant(row)) + { + switch (row) + { + case 0: + { + impl.X = value; + break; + } + + case 1: + { + impl.Y = value; + break; + } + + case 2: + { + impl.Z = value; + break; + } + + case 3: + { + impl.W = value; + break; + } + + default: + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + break; + } + } + } + else + { + if ((uint)row >= RowCount) + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + Unsafe.Add(ref Unsafe.AsRef(in impl.X), row) = value; + } + } + } + + /// Gets or sets the element at the specified row and column. + /// The index of the row containing the element to get or set. + /// The index of the column containing the element to get or set. + /// The element at index: [, ]. + /// + /// was less than zero or greater than or equal to the number of rows (4). + /// -or- + /// was less than zero or greater than or equal to the number of columns (4). + /// + public float this[int row, int column] + { + // When both row and column are known constants, we can use a switch to + // get optimal codegen as we are likely coming from register. + // + // However, if either is non constant we're going to end up having to + // touch memory so just directly compute the relevant index. + // + // The JIT will elide any dead code paths if only one of the inputs is constant. + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get + { + if (RuntimeHelpers.IsKnownConstant(row) && RuntimeHelpers.IsKnownConstant(column)) + { + ref readonly Impl impl = ref AsROImpl(); + + switch (row) + { + case 0: + { + return impl.X.GetElement(column); + } + + case 1: + { + return impl.Y.GetElement(column); + } + + case 2: + { + return impl.Z.GetElement(column); + } + + case 3: + { + return impl.W.GetElement(column); + } + + default: + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + return default; + } + } + } + else + { + if (((uint)row >= RowCount) || ((uint)column >= ColumnCount)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + return Unsafe.Add(ref Unsafe.AsRef(in M11), (row * ColumnCount) + column); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + if (RuntimeHelpers.IsKnownConstant(row) && RuntimeHelpers.IsKnownConstant(column)) + { + ref Impl impl = ref AsImpl(); + + switch (row) + { + case 0: + { + impl.X = impl.X.WithElement(column, value); + break; + } + + case 1: + { + impl.Y = impl.Y.WithElement(column, value); + break; + } + + case 2: + { + impl.Z = impl.Z.WithElement(column, value); + break; + } + + case 3: + { + impl.W = impl.W.WithElement(column, value); + break; + } + + default: + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + break; + } + } + } + else + { + if (((uint)row >= RowCount) || ((uint)column >= ColumnCount)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + Unsafe.Add(ref Unsafe.AsRef(in M11), (row * ColumnCount) + column) = value; + } + } } /// Adds each element in one matrix with its corresponding element in a second matrix. @@ -188,8 +458,13 @@ public Vector3 Translation /// The second matrix. /// The product matrix. /// The method defines the operation of the multiplication operator for objects. - public static Matrix4x4 operator *(Matrix4x4 value1, Matrix4x4 value2) - => (value1.AsImpl() * value2.AsImpl()).AsM4x4(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix4x4 operator *(Matrix4x4 value1, Matrix4x4 value2) => Create( + Vector4.Transform(value1.X, value2), + Vector4.Transform(value1.Y, value2), + Vector4.Transform(value1.Z, value2), + Vector4.Transform(value1.W, value2) + ); /// Multiplies a matrix by a float to compute the product. /// The matrix to scale. @@ -224,6 +499,78 @@ public Vector3 Translation public static Matrix4x4 Add(Matrix4x4 value1, Matrix4x4 value2) => (value1.AsImpl() + value2.AsImpl()).AsM4x4(); + /// Creates a whose 16 elements are set to the specified value. + /// The value to assign to all 16 elements. + /// A whose 16 elements are set to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix4x4 Create(float value) => Create(Vector4.Create(value)); + + /// Creates a from the specified . + /// The to assign to the first two elements of , , and . + /// A that was initialized using the elements from . + /// The last two elements of , , and are initialized to zero; while is initialized to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix4x4 Create(Matrix3x2 value) => Create( + value.X.AsVector4(), + value.Y.AsVector4(), + Vector4.UnitZ, + Vector4.Create(value.Z, 0, 1) + ); + + /// Creates a whose 4 rows are set to the specified value. + /// The value to assign to all 4 rows. + /// A whose 4 rows are set to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix4x4 Create(Vector4 value) => Create(value, value, value, value); + + /// Creates a from the specified rows. + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// A whose rows are set to the specified values. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix4x4 Create(Vector4 x, Vector4 y, Vector4 z, Vector4 w) + { + Unsafe.SkipInit(out Matrix4x4 result); + + result.X = x; + result.Y = y; + result.Z = z; + result.W = w; + + return result; + } + + /// Creates a from the specified elements. + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// The value to assign to . + /// A whose elements are set to the specified values. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix4x4 Create(float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44) => Create( + Vector4.Create(m11, m12, m13, m14), + Vector4.Create(m21, m22, m23, m24), + Vector4.Create(m31, m32, m33, m34), + Vector4.Create(m41, m42, m43, m44) + ); + /// Creates a right-handed spherical billboard matrix that rotates around a specified object position. /// The position of the object that the billboard will rotate around. /// The position of the camera. @@ -643,8 +990,7 @@ public static Matrix4x4 Lerp(Matrix4x4 matrix1, Matrix4x4 matrix2, float amount) /// The first matrix. /// The second matrix. /// The product matrix. - public static Matrix4x4 Multiply(Matrix4x4 value1, Matrix4x4 value2) - => (value1.AsImpl() * value2.AsImpl()).AsM4x4(); + public static Matrix4x4 Multiply(Matrix4x4 value1, Matrix4x4 value2) => value1 * value2; /// Multiplies a matrix by a float to compute the product. /// The matrix to scale. @@ -702,6 +1048,25 @@ public readonly bool Equals(Matrix4x4 other) public readonly float GetDeterminant() => AsROImpl().GetDeterminant(); + /// Gets the element at the specified row and column. + /// The index of the row containing the element to get. + /// The index of the column containing the element to get. + /// The element at index: [, ]. + /// + /// was less than zero or greater than or equal to the number of rows (4). + /// -or- + /// was less than zero or greater than or equal to the number of columns (4). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly float GetElement(int row, int column) => this[row, column]; + + /// Gets or sets the row at the specified index. + /// The index of the row to get. + /// The row at index: []. + /// was less than zero or greater than or equal to the number of rows (4). + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Vector4 GetRow(int index) => this[index]; + /// Returns the hash code for this instance. /// The hash code. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -713,5 +1078,36 @@ public override readonly int GetHashCode() /// The numeric values in the returned string are formatted by using the conventions of the current culture. For example, for the en-US culture, the returned string might appear as { {M11:1.1 M12:1.2 M13:1.3 M14:1.4} {M21:2.1 M22:2.2 M23:2.3 M24:2.4} {M31:3.1 M32:3.2 M33:3.3 M34:3.4} {M41:4.1 M42:4.2 M43:4.3 M44:4.4} }. public override readonly string ToString() => $"{{ {{M11:{M11} M12:{M12} M13:{M13} M14:{M14}}} {{M21:{M21} M22:{M22} M23:{M23} M24:{M24}}} {{M31:{M31} M32:{M32} M33:{M33} M34:{M34}}} {{M41:{M41} M42:{M42} M43:{M43} M44:{M44}}} }}"; + + /// Creates a new with the element at the specified row and column set to the given value and the remaining elements set to the same value as that in the current matrix. + /// The index of the row containing the element to replace. + /// The index of the column containing the element to replace. + /// The value to assign to the element at index: [, ]. + /// A with the value of the element at index: [, ] set to and the remaining elements set to the same value as that in the current matrix. + /// + /// was less than zero or greater than or equal to the number of rows (4). + /// -or- + /// was less than zero or greater than or equal to the number of columns (4). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Matrix4x4 WithElement(int row, int column, float value) + { + Matrix4x4 result = this; + result[row, column] = value; + return result; + } + + /// Creates a new with the row at the specified index set to the given value and the remaining rows set to the same value as that in the current matrix. + /// The index of the row to replace. + /// The value to assign to the row at index: []. + /// A with the value of the row at index: [] set to and the remaining rows set to the same value as that in the current matrix. + /// was less than zero or greater than or equal to the number of rows (4). + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Matrix4x4 WithRow(int index, Vector4 value) + { + Matrix4x4 result = this; + result[index] = value; + return result; + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs index 67df1c546b0ae1..5e756f452c9a92 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs @@ -20,7 +20,7 @@ public struct Plane : IEquatable /// The distance of the plane along its normal from the origin. public float D; - /// Creates a object from the X, Y, and Z components of its normal, and its distance from the origin on that normal. + /// Initializes a from the X, Y, and Z components of its normal, and its distance from the origin on that normal. /// The X component of the normal. /// The Y component of the normal. /// The Z component of the normal. @@ -31,7 +31,7 @@ public Plane(float x, float y, float z, float d) this = Create(x, y, z, d); } - /// Creates a object from a specified normal and the distance along the normal from the origin. + /// Initializes a from a specified normal and the distance along the normal from the origin. /// The plane's normal vector. /// The plane's distance from the origin along its normal vector. [Intrinsic] @@ -40,7 +40,7 @@ public Plane(Vector3 normal, float d) this = Create(normal, d); } - /// Creates a object from a specified four-dimensional vector. + /// Initializes a from a specified four-dimensional vector. /// A vector whose first three elements describe the normal vector, and whose defines the distance along that normal from the origin. [Intrinsic] public Plane(Vector4 value) @@ -48,21 +48,27 @@ public Plane(Vector4 value) this = value.AsPlane(); } - /// Creates a object from the X, Y, and Z components of its normal, and its distance from the origin on that normal. - /// The X component of the normal. - /// The Y component of the normal. - /// The Z component of the normal. - /// The distance of the plane along its normal from the origin. - /// A new object from the X, Y, and Z components of its normal, and its distance from the origin on that normal. + /// Creates a from a specified four-dimensional vector. + /// A vector whose first three elements describe the normal vector, and whose defines the distance along that normal from the origin. + /// A created using . [Intrinsic] - internal static Plane Create(float x, float y, float z, float d) => Vector128.Create(x, y, z, d).AsPlane(); + public static Plane Create(Vector4 value) => value.AsPlane(); - /// Creates a object from a specified normal and the distance along the normal from the origin. + /// Creates a from a specified normal and the distance along the normal from the origin. /// The plane's normal vector. /// The plane's distance from the origin along its normal vector.\ - /// A new object from a specified normal and the distance along the normal from the origin. + /// A created from a specified normal and the distance along the normal from the origin. + [Intrinsic] + public static Plane Create(Vector3 normal, float d) => Vector4.Create(normal, d).AsPlane(); + + /// Creates a from the X, Y, and Z components of its normal, and its distance from the origin on that normal. + /// The X component of the normal. + /// The Y component of the normal. + /// The Z component of the normal. + /// The distance of the plane along its normal from the origin. + /// A created from the X, Y, and Z components of its normal, and its distance from the origin on that normal. [Intrinsic] - internal static Plane Create(Vector3 normal, float d) => Vector4.Create(normal, d).AsPlane(); + public static Plane Create(float x, float y, float z, float d) => Vector128.Create(x, y, z, d).AsPlane(); /// Creates a object that contains three specified points. /// The first point defining the plane. @@ -139,8 +145,8 @@ public static Plane Normalize(Plane value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Plane Transform(Plane plane, Matrix4x4 matrix) { - Matrix4x4.Impl.Invert(matrix.AsImpl(), out Matrix4x4.Impl inverseMatrix); - return Vector4.Transform(plane.AsVector4(), Matrix4x4.Impl.Transpose(inverseMatrix)).AsPlane(); + Matrix4x4.Invert(matrix, out Matrix4x4 inverseMatrix); + return Vector4.Transform(plane.AsVector4(), Matrix4x4.Transpose(inverseMatrix)).AsPlane(); } /// Transforms a normalized plane by a Quaternion rotation. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 5c5389993c873c..264f0050c59883 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -27,7 +27,7 @@ public struct Quaternion : IEquatable internal const int Count = 4; - /// Constructs a quaternion from the specified components. + /// Initializes a from the specified components. /// The value to assign to the X component of the quaternion. /// The value to assign to the Y component of the quaternion. /// The value to assign to the Z component of the quaternion. @@ -38,7 +38,7 @@ public Quaternion(float x, float y, float z, float w) this = Create(x, y, z, w); } - /// Creates a quaternion from the specified vector and rotation parts. + /// Initializes a from the specified vector and rotation parts. /// The vector part of the quaternion. /// The rotation part of the quaternion. [Intrinsic] @@ -191,21 +191,21 @@ public static Quaternion Conjugate(Quaternion value) return (value.AsVector128() * Vector128.Create(-1.0f, -1.0f, -1.0f, 1.0f)).AsQuaternion(); } - /// Creates a quaternion from the specified components. + /// Creates a from the specified components. /// The value to assign to the X component of the quaternion. /// The value to assign to the Y component of the quaternion. /// The value to assign to the Z component of the quaternion. /// The value to assign to the W component of the quaternion. - /// A new quaternion created from the specified components.> + /// A created from the specified components.> [Intrinsic] - internal static Quaternion Create(float x, float y, float z, float w) => Vector128.Create(x, y, z, w).AsQuaternion(); + public static Quaternion Create(float x, float y, float z, float w) => Vector128.Create(x, y, z, w).AsQuaternion(); - /// Creates a quaternion from the specified vector and rotation parts. + /// Creates a from the specified vector and rotation parts. /// The vector part of the quaternion. /// The rotation part of the quaternion. - /// A new quaternion created from the specified vector and rotation parts. + /// A created from the specified vector and rotation parts. [Intrinsic] - internal static Quaternion Create(Vector3 vectorPart, float scalarPart) => Vector4.Create(vectorPart, scalarPart).AsQuaternion(); + public static Quaternion Create(Vector3 vectorPart, float scalarPart) => Vector4.Create(vectorPart, scalarPart).AsQuaternion(); /// Creates a quaternion from a unit vector and an angle to rotate around the vector. /// The unit vector to rotate around. 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 744efd825eecce..790f07d068fc51 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -751,7 +751,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 Vector CreateScalar(T value) + public static Vector CreateScalar(T value) { Vector result = Vector.Zero; result.SetElementUnsafe(0, value); @@ -765,7 +765,7 @@ internal static Vector CreateScalar(T value) /// The type of () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector CreateScalarUnsafe(T value) + public static Vector CreateScalarUnsafe(T value) { // This relies on us stripping the "init" flag from the ".locals" // declaration to let the upper bits be uninitialized. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs index 3c38c3852bdd9c..94134a583c42fb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs @@ -9,6 +9,16 @@ namespace System.Numerics { public static unsafe partial class Vector { + /// Reinterprets a to a new with the new elements zeroed. + /// The vector to reinterpret. + /// reinterpreted to a new with the new elements zeroed. + public static Vector3 AsVector3(this Vector2 value) => value.AsVector128().AsVector3(); + + /// Reinterprets a to a new with the new elements undefined. + /// The vector to reinterpret. + /// reinterpreted to a new with the new elements undefined. + public static Vector3 AsVector3Unsafe(this Vector2 value) => value.AsVector128Unsafe().AsVector3(); + /// Reinterprets a to a new with the new elements zeroed. /// The vector to reinterpret. /// reinterpreted to a new with the new elements zeroed. 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 b4f18603d7e199..b4c2b88a42894a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -415,13 +415,13 @@ public static Vector2 Create(ReadOnlySpan values) /// The value to assign to the field. /// A new with initialized and the remaining elements initialized to zero. [Intrinsic] - internal static Vector2 CreateScalar(float x) => Vector128.CreateScalar(x).AsVector2(); + public static Vector2 CreateScalar(float x) => Vector128.CreateScalar(x).AsVector2(); /// Creates a vector with initialized to the specified value and the remaining elements left uninitialized. /// The value to assign to the field. /// A new with initialized and the remaining elements left uninitialized. [Intrinsic] - internal static Vector2 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector2(); + public static Vector2 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector2(); /// /// Returns the z-value of the cross product of two vectors. @@ -901,10 +901,8 @@ public static (Vector2 Sin, Vector2 Cos) SinCos(Vector2 vector) /// The vector to transform. /// The transformation matrix. /// The transformed vector. - public static Vector2 Transform(Vector2 position, Matrix3x2 matrix) => Transform(position, in matrix.AsImpl()); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector2 Transform(Vector2 position, in Matrix3x2.Impl matrix) + public static Vector2 Transform(Vector2 position, Matrix3x2 matrix) { Vector2 result = matrix.X * position.X; result = MultiplyAddEstimate(matrix.Y, Create(position.Y), result); @@ -916,7 +914,7 @@ internal static Vector2 Transform(Vector2 position, in Matrix3x2.Impl matrix) /// The transformation matrix. /// The transformed vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 Transform(Vector2 position, Matrix4x4 matrix) => Vector4.Transform(position, in matrix.AsImpl()).AsVector128().AsVector2(); + public static Vector2 Transform(Vector2 position, Matrix4x4 matrix) => Vector4.Transform(position, matrix).AsVector2(); /// Transforms a vector by the specified Quaternion rotation value. /// The vector to rotate. @@ -929,10 +927,8 @@ internal static Vector2 Transform(Vector2 position, in Matrix3x2.Impl matrix) /// The source vector. /// The matrix. /// The transformed vector. - public static Vector2 TransformNormal(Vector2 normal, Matrix3x2 matrix) => TransformNormal(normal, in matrix.AsImpl()); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector2 TransformNormal(Vector2 normal, in Matrix3x2.Impl matrix) + public static Vector2 TransformNormal(Vector2 normal, Matrix3x2 matrix) { Vector2 result = matrix.X * normal.X; result = MultiplyAddEstimate(matrix.Y, Create(normal.Y), result); @@ -943,10 +939,8 @@ internal static Vector2 TransformNormal(Vector2 normal, in Matrix3x2.Impl matrix /// The source vector. /// The matrix. /// The transformed vector. - public static Vector2 TransformNormal(Vector2 normal, Matrix4x4 matrix) => TransformNormal(normal, in matrix.AsImpl()); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector2 TransformNormal(Vector2 normal, in Matrix4x4.Impl matrix) + public static Vector2 TransformNormal(Vector2 normal, Matrix4x4 matrix) { Vector4 result = matrix.X * normal.X; result = Vector4.MultiplyAddEstimate(matrix.Y, Vector4.Create(normal.Y), result); diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs index b818143530be72..dfaf6dca80891d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs @@ -9,6 +9,11 @@ namespace System.Numerics { public static unsafe partial class Vector { + /// Reinterprets a as a new . + /// The vector to reinterpret. + /// reinterpreted as a new . + public static Vector2 AsVector2(this Vector3 value) => value.AsVector128().AsVector2(); + /// Converts a to a new with the new elements zeroed. /// The vector to convert. /// converted to a new with the new elements zeroed. 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 57ceef2be01dbc..dd92866c93067e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -450,13 +450,13 @@ public static Vector3 Create(ReadOnlySpan values) /// The value to assign to the field. /// A new with initialized and the remaining elements initialized to zero. [Intrinsic] - internal static Vector3 CreateScalar(float x) => Vector128.CreateScalar(x).AsVector3(); + public static Vector3 CreateScalar(float x) => Vector128.CreateScalar(x).AsVector3(); /// Creates a vector with initialized to the specified value and the remaining elements left uninitialized. /// The value to assign to the field. /// A new with initialized and the remaining elements left uninitialized. [Intrinsic] - internal static Vector3 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector3(); + public static Vector3 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector3(); /// Computes the cross product of two vectors. /// The first vector. @@ -936,7 +936,7 @@ public static (Vector3 Sin, Vector3 Cos) SinCos(Vector3 vector) /// The transformation matrix. /// The transformed vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 Transform(Vector3 position, Matrix4x4 matrix) => Vector4.Transform(position, in matrix.AsImpl()).AsVector128().AsVector3(); + public static Vector3 Transform(Vector3 position, Matrix4x4 matrix) => Vector4.Transform(position, matrix).AsVector3(); /// Transforms a vector by the specified Quaternion rotation value. /// The vector to rotate. @@ -950,10 +950,7 @@ public static (Vector3 Sin, Vector3 Cos) SinCos(Vector3 vector) /// The matrix. /// The transformed vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 TransformNormal(Vector3 normal, Matrix4x4 matrix) => TransformNormal(normal, in matrix.AsImpl()); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector3 TransformNormal(Vector3 normal, in Matrix4x4.Impl matrix) + public static Vector3 TransformNormal(Vector3 normal, Matrix4x4 matrix) { Vector4 result = matrix.X * normal.X; 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 194c1334150a2c..4608e9a7d48e7b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -488,15 +488,15 @@ public static Vector4 Create(Vector3 vector, float w) /// Creates a vector with initialized to the specified value and the remaining elements initialized to zero. /// The value to assign to the field. - /// A new with initialized and the remaining elements initialized to zero. + /// A with initialized and the remaining elements initialized to zero. [Intrinsic] - internal static Vector4 CreateScalar(float x) => Vector128.CreateScalar(x).AsVector4(); + public static Vector4 CreateScalar(float x) => Vector128.CreateScalar(x).AsVector4(); /// Creates a vector with initialized to the specified value and the remaining elements left uninitialized. /// The value to assign to the field. - /// A new with initialized and the remaining elements left uninitialized. + /// A with initialized and the remaining elements left uninitialized. [Intrinsic] - internal static Vector4 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector4(); + public static Vector4 CreateScalarUnsafe(float x) => Vector128.CreateScalarUnsafe(x).AsVector4(); /// /// Computes the cross product of two vectors. For homogeneous coordinates, @@ -966,10 +966,8 @@ public static (Vector4 Sin, Vector4 Cos) SinCos(Vector4 vector) /// The vector to transform. /// The transformation matrix. /// The transformed vector. - public static Vector4 Transform(Vector2 position, Matrix4x4 matrix) => Transform(position, in matrix.AsImpl()); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector4 Transform(Vector2 position, in Matrix4x4.Impl matrix) + public static Vector4 Transform(Vector2 position, Matrix4x4 matrix) { // This implementation is based on the DirectX Math Library XMVector2Transform method // https://github.com/microsoft/DirectXMath/blob/master/Inc/DirectXMathVector.inl @@ -990,10 +988,8 @@ internal static Vector4 Transform(Vector2 position, in Matrix4x4.Impl matrix) /// The vector to transform. /// The transformation matrix. /// The transformed vector. - public static Vector4 Transform(Vector3 position, Matrix4x4 matrix) => Transform(position, in matrix.AsImpl()); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector4 Transform(Vector3 position, in Matrix4x4.Impl matrix) + public static Vector4 Transform(Vector3 position, Matrix4x4 matrix) { // This implementation is based on the DirectX Math Library XMVector3Transform method // https://github.com/microsoft/DirectXMath/blob/master/Inc/DirectXMathVector.inl @@ -1015,10 +1011,8 @@ internal static Vector4 Transform(Vector3 position, in Matrix4x4.Impl matrix) /// The vector to transform. /// The transformation matrix. /// The transformed vector. - public static Vector4 Transform(Vector4 vector, Matrix4x4 matrix) => Transform(vector, in matrix.AsImpl()); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector4 Transform(Vector4 vector, in Matrix4x4.Impl matrix) + public static Vector4 Transform(Vector4 vector, Matrix4x4 matrix) { // This implementation is based on the DirectX Math Library XMVector4Transform method // https://github.com/microsoft/DirectXMath/blob/master/Inc/DirectXMathVector.inl diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.Numerics.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.Numerics.cs index 699c8c5f6734c2..1cfbc41de7ce22 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.Numerics.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.Numerics.cs @@ -53,7 +53,7 @@ public static partial class Vector128 /// The vector to reinterpret. /// reinterpreted as a new . [Intrinsic] - internal static Plane AsPlane(this Vector128 value) + public static Plane AsPlane(this Vector128 value) { #if MONO return Unsafe.As, Plane>(ref value); @@ -66,7 +66,7 @@ internal static Plane AsPlane(this Vector128 value) /// The vector to reinterpret. /// reinterpreted as a new . [Intrinsic] - internal static Quaternion AsQuaternion(this Vector128 value) + public static Quaternion AsQuaternion(this Vector128 value) { #if MONO return Unsafe.As, Quaternion>(ref value); @@ -79,7 +79,7 @@ internal static Quaternion AsQuaternion(this Vector128 value) /// The plane to reinterpret. /// reinterpreted as a new . [Intrinsic] - internal static Vector128 AsVector128(this Plane value) + public static Vector128 AsVector128(this Plane value) { #if MONO return Unsafe.As>(ref value); @@ -92,7 +92,7 @@ internal static Vector128 AsVector128(this Plane value) /// The quaternion to reinterpret. /// reinterpreted as a new . [Intrinsic] - internal static Vector128 AsVector128(this Quaternion value) + public static Vector128 AsVector128(this Quaternion value) { #if MONO return Unsafe.As>(ref value); 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 02984d153ab9fd..000149994281b5 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -26,6 +26,8 @@ public static partial class Vector128 public static System.Runtime.Intrinsics.Vector128 AsNInt(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 AsNUInt(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Numerics.Plane AsPlane(this System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Numerics.Quaternion AsQuaternion(this System.Runtime.Intrinsics.Vector128 value) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 AsSByte(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsSingle(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } @@ -35,6 +37,8 @@ public static partial class Vector128 public static System.Runtime.Intrinsics.Vector128 AsUInt32(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 AsUInt64(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AsVector128(this System.Numerics.Plane value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AsVector128(this System.Numerics.Quaternion value) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsVector128(this System.Numerics.Vector2 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsVector128(this System.Numerics.Vector3 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsVector128(this System.Numerics.Vector4 value) { throw null; }