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 0713a7a6c38cd4..e65e1d034e888a 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -304,6 +304,7 @@ public partial struct Vector2 : System.IEquatable, Syst public float Y; public Vector2(float value) { throw null; } public Vector2(float x, float y) { throw null; } + public Vector2(System.ReadOnlySpan values) { throw null; } public static System.Numerics.Vector2 One { get { throw null; } } public static System.Numerics.Vector2 UnitX { get { throw null; } } public static System.Numerics.Vector2 UnitY { get { throw null; } } @@ -313,6 +314,8 @@ public partial struct Vector2 : System.IEquatable, Syst public static System.Numerics.Vector2 Clamp(System.Numerics.Vector2 value1, System.Numerics.Vector2 min, System.Numerics.Vector2 max) { throw null; } public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } + public readonly void CopyTo(System.Span destination) { } + public readonly bool TryCopyTo(System.Span destination) { throw null; } public static float Distance(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } public static float DistanceSquared(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } public static System.Numerics.Vector2 Divide(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } @@ -361,6 +364,7 @@ public partial struct Vector3 : System.IEquatable, Syst public Vector3(System.Numerics.Vector2 value, float z) { throw null; } public Vector3(float value) { throw null; } public Vector3(float x, float y, float z) { throw null; } + public Vector3(System.ReadOnlySpan values) { throw null; } public static System.Numerics.Vector3 One { get { throw null; } } public static System.Numerics.Vector3 UnitX { get { throw null; } } public static System.Numerics.Vector3 UnitY { get { throw null; } } @@ -371,6 +375,8 @@ public partial struct Vector3 : System.IEquatable, Syst public static System.Numerics.Vector3 Clamp(System.Numerics.Vector3 value1, System.Numerics.Vector3 min, System.Numerics.Vector3 max) { throw null; } public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } + public readonly void CopyTo(System.Span destination) { } + public readonly bool TryCopyTo(System.Span destination) { throw null; } public static System.Numerics.Vector3 Cross(System.Numerics.Vector3 vector1, System.Numerics.Vector3 vector2) { throw null; } public static float Distance(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } public static float DistanceSquared(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } @@ -420,6 +426,7 @@ public partial struct Vector4 : System.IEquatable, Syst public Vector4(System.Numerics.Vector3 value, float w) { throw null; } public Vector4(float value) { throw null; } public Vector4(float x, float y, float z, float w) { throw null; } + public Vector4(System.ReadOnlySpan values) { throw null; } public static System.Numerics.Vector4 One { get { throw null; } } public static System.Numerics.Vector4 UnitW { get { throw null; } } public static System.Numerics.Vector4 UnitX { get { throw null; } } @@ -431,6 +438,8 @@ public partial struct Vector4 : System.IEquatable, Syst public static System.Numerics.Vector4 Clamp(System.Numerics.Vector4 value1, System.Numerics.Vector4 min, System.Numerics.Vector4 max) { throw null; } public readonly void CopyTo(float[] array) { } public readonly void CopyTo(float[] array, int index) { } + public readonly void CopyTo(System.Span destination) { } + public readonly bool TryCopyTo(System.Span destination) { throw null; } public static float Distance(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } public static float DistanceSquared(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } public static System.Numerics.Vector4 Divide(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs index e46d916561db0e..32e98103ff51b5 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs @@ -38,6 +38,36 @@ public void Vector2CopyToTest() Assert.Equal(3.0, b[1]); } + [Fact] + public void Vector2CopyToSpanTest() + { + Vector2 vector = new Vector2(1.0f, 2.0f); + Span destination = new float[2]; + + Assert.Throws(() => vector.CopyTo(new Span(new float[1]))); + vector.CopyTo(destination); + + Assert.Equal(1.0f, vector.X); + Assert.Equal(2.0f, vector.Y); + Assert.Equal(vector.X, destination[0]); + Assert.Equal(vector.Y, destination[1]); + } + + [Fact] + public void Vector2TryCopyToTest() + { + Vector2 vector = new Vector2(1.0f, 2.0f); + Span destination = new float[2]; + + Assert.False(vector.TryCopyTo(new Span(new float[1]))); + Assert.True(vector.TryCopyTo(destination)); + + Assert.Equal(1.0f, vector.X); + Assert.Equal(2.0f, vector.Y); + Assert.Equal(vector.X, destination[0]); + Assert.Equal(vector.Y, destination[1]); + } + [Fact] public void Vector2GetHashCodeTest() { @@ -834,6 +864,18 @@ public void Vector2ConstructorTest4() Assert.Equal(expected, target); } + // A test for Vector2f (ReadOnlySpan) + [Fact] + public void Vector2ConstructorTest5() + { + float value = 1.0f; + Vector2 target = new Vector2(new[] { value, value }); + Vector2 expected = new Vector2(value); + + Assert.Equal(expected, target); + Assert.Throws(() => new Vector2(new float[1])); + } + // A test for Add (Vector2f, Vector2f) [Fact] public void Vector2AddTest() diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs index 0f50a8ca22ad42..1da75451a82ba3 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs @@ -40,6 +40,40 @@ public void Vector3CopyToTest() Assert.Equal(3.3f, b[2]); } + [Fact] + public void Vector3CopyToSpanTest() + { + Vector3 vector = new Vector3(1.0f, 2.0f, 3.0f); + Span destination = new float[3]; + + Assert.Throws(() => vector.CopyTo(new Span(new float[2]))); + vector.CopyTo(destination); + + Assert.Equal(1.0f, vector.X); + Assert.Equal(2.0f, vector.Y); + Assert.Equal(3.0f, vector.Z); + Assert.Equal(vector.X, destination[0]); + Assert.Equal(vector.Y, destination[1]); + Assert.Equal(vector.Z, destination[2]); + } + + [Fact] + public void Vector3TryCopyToTest() + { + Vector3 vector = new Vector3(1.0f, 2.0f, 3.0f); + Span destination = new float[3]; + + Assert.False(vector.TryCopyTo(new Span(new float[2]))); + Assert.True(vector.TryCopyTo(destination)); + + Assert.Equal(1.0f, vector.X); + Assert.Equal(2.0f, vector.Y); + Assert.Equal(3.0f, vector.Z); + Assert.Equal(vector.X, destination[0]); + Assert.Equal(vector.Y, destination[1]); + Assert.Equal(vector.Z, destination[2]); + } + [Fact] public void Vector3GetHashCodeTest() { @@ -887,6 +921,18 @@ public void Vector3ConstructorTest4() Assert.True(float.IsPositiveInfinity(target.Z), "Vector3f.constructor (Vector3f) did not return the expected value."); } + // A test for Vector3f (ReadOnlySpan) + [Fact] + public void Vector3ConstructorTest6() + { + float value = 1.0f; + Vector3 target = new Vector3(new[] { value, value, value }); + Vector3 expected = new Vector3(value); + + Assert.Equal(expected, target); + Assert.Throws(() => new Vector3(new float[2])); + } + // A test for Add (Vector3f, Vector3f) [Fact] public void Vector3AddTest() diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs index 5b8d417529c470..6fe43b76b05156 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs @@ -42,6 +42,44 @@ public void Vector4CopyToTest() Assert.Equal(3.3f, b[3]); } + [Fact] + public void Vector4CopyToSpanTest() + { + Vector4 vector = new Vector4(1.0f, 2.0f, 3.0f, 4.0f); + Span destination = new float[4]; + + Assert.Throws(() => vector.CopyTo(new Span(new float[3]))); + vector.CopyTo(destination); + + Assert.Equal(1.0f, vector.X); + Assert.Equal(2.0f, vector.Y); + Assert.Equal(3.0f, vector.Z); + Assert.Equal(4.0f, vector.W); + Assert.Equal(vector.X, destination[0]); + Assert.Equal(vector.Y, destination[1]); + Assert.Equal(vector.Z, destination[2]); + Assert.Equal(vector.W, destination[3]); + } + + [Fact] + public void Vector4TryCopyToTest() + { + Vector4 vector = new Vector4(1.0f, 2.0f, 3.0f, 4.0f); + Span destination = new float[4]; + + Assert.False(vector.TryCopyTo(new Span(new float[3]))); + Assert.True(vector.TryCopyTo(destination)); + + Assert.Equal(1.0f, vector.X); + Assert.Equal(2.0f, vector.Y); + Assert.Equal(3.0f, vector.Z); + Assert.Equal(4.0f, vector.W); + Assert.Equal(vector.X, destination[0]); + Assert.Equal(vector.Y, destination[1]); + Assert.Equal(vector.Z, destination[2]); + Assert.Equal(vector.W, destination[3]); + } + [Fact] public void Vector4GetHashCodeTest() { @@ -1099,6 +1137,18 @@ public void Vector4ConstructorTest5() Assert.True(float.Equals(float.Epsilon, target.W), "Vector4f.constructor (float, float, float, float) did not return the expected value."); } + // A test for Vector4f (ReadOnlySpan) + [Fact] + public void Vector4ConstructorTest7() + { + float value = 1.0f; + Vector4 target = new Vector4(new[] { value, value, value, value }); + Vector4 expected = new Vector4(value); + + Assert.Equal(expected, target); + Assert.Throws(() => new Vector4(new float[3])); + } + // A test for Add (Vector4f, Vector4f) [Fact] public void Vector4AddTest() 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 b20b73ae05a687..ae0e87bded858b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -4,7 +4,9 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; +using Internal.Runtime.CompilerServices; namespace System.Numerics { @@ -39,6 +41,18 @@ public Vector2(float x, float y) Y = y; } + /// Constructs a vector from the given . The span must contain at least 2 elements. + /// The span of elements to assign to the vector. + public Vector2(ReadOnlySpan values) + { + if (values.Length < 2) + { + Vector.ThrowInsufficientNumberOfElementsException(2); + } + + this = Unsafe.ReadUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + } + /// Returns a vector whose 2 elements are equal to zero. /// A vector whose two elements are equal to zero (that is, it returns the vector (0,0). public static Vector2 Zero @@ -530,6 +544,34 @@ public readonly void CopyTo(float[] array, int index) array[index + 1] = Y; } + /// Copies the vector to the given .The length of the destination span must be at least 2. + /// The destination span which the values are copied into. + /// If number of elements in source vector is greater than those available in destination span. + public readonly void CopyTo(Span destination) + { + if (destination.Length < 2) + { + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + } + + Unsafe.WriteUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(destination)), this); + } + + /// Attempts to copy the vector to the given . The length of the destination span must be at least 2. + /// The destination span which the values are copied into. + /// if the source vector was successfully copied to . if is not large enough to hold the source vector. + public readonly bool TryCopyTo(Span destination) + { + if (destination.Length < 2) + { + return false; + } + + Unsafe.WriteUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(destination)), this); + + return true; + } + /// Returns a value that indicates whether this instance and a specified object are equal. /// The object to compare with the current instance. /// if the current instance and are equal; otherwise, . If is , the method returns . 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 bb34093c7133a4..85657b13225390 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -4,7 +4,9 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; +using Internal.Runtime.CompilerServices; namespace System.Numerics { @@ -52,6 +54,18 @@ public Vector3(float x, float y, float z) Z = z; } + /// Constructs a vector from the given . The span must contain at least 3 elements. + /// The span of elements to assign to the vector. + public Vector3(ReadOnlySpan values) + { + if (values.Length < 3) + { + Vector.ThrowInsufficientNumberOfElementsException(3); + } + + this = Unsafe.ReadUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + } + /// Gets a vector whose 3 elements are equal to zero. /// A vector whose three elements are equal to zero (that is, it returns the vector (0,0,0). public static Vector3 Zero @@ -553,6 +567,34 @@ public readonly void CopyTo(float[] array, int index) array[index + 2] = Z; } + /// Copies the vector to the given . The length of the destination span must be at least 3. + /// The destination span which the values are copied into. + /// If number of elements in source vector is greater than those available in destination span. + public readonly void CopyTo(Span destination) + { + if (destination.Length < 3) + { + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + } + + Unsafe.WriteUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(destination)), this); + } + + /// Attempts to copy the vector to the given . The length of the destination span must be at least 3. + /// The destination span which the values are copied into. + /// if the source vector was successfully copied to . if is not large enough to hold the source vector. + public readonly bool TryCopyTo(Span destination) + { + if (destination.Length < 3) + { + return false; + } + + Unsafe.WriteUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(destination)), this); + + return true; + } + /// Returns a value that indicates whether this instance and a specified object are equal. /// The object to compare with the current instance. /// if the current instance and are equal; otherwise, . If is , the method returns . 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 c376d53f25de7d..2c920df2587d5c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -4,7 +4,9 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; +using Internal.Runtime.CompilerServices; namespace System.Numerics { @@ -66,6 +68,18 @@ public Vector4(float x, float y, float z, float w) W = w; } + /// Constructs a vector from the given . The span must contain at least 4 elements. + /// The span of elements to assign to the vector. + public Vector4(ReadOnlySpan values) + { + if (values.Length < 4) + { + Vector.ThrowInsufficientNumberOfElementsException(4); + } + + this = Unsafe.ReadUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + } + /// Gets a vector whose 4 elements are equal to zero. /// A vector whose four elements are equal to zero (that is, it returns the vector (0,0,0,0). public static Vector4 Zero @@ -640,6 +654,34 @@ public readonly void CopyTo(float[] array, int index) array[index + 3] = W; } + /// Copies the vector to the given . The length of the destination span must be at least 4. + /// The destination span which the values are copied into. + /// If number of elements in source vector is greater than those available in destination span. + public readonly void CopyTo(Span destination) + { + if (destination.Length < 4) + { + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + } + + Unsafe.WriteUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(destination)), this); + } + + /// Attempts to copy the vector to the given . The length of the destination span must be at least 4. + /// The destination span which the values are copied into. + /// if the source vector was successfully copied to . if is not large enough to hold the source vector. + public readonly bool TryCopyTo(Span destination) + { + if (destination.Length < 4) + { + return false; + } + + Unsafe.WriteUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(destination)), this); + + return true; + } + /// Returns a value that indicates whether this instance and another vector are equal. /// The other vector. /// if the two vectors are equal; otherwise, .