From 8f7418419ac1985c689fb99616b2afdcfbb95ef0 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 20 Apr 2021 12:02:06 +0200 Subject: [PATCH 1/2] Fixed inconsistency with ReadOnlySpan2D.Slice parameters --- .../Memory/ReadOnlySpan2D{T}.cs | 12 ++++++------ .../Memory/Test_ReadOnlySpan2D{T}.cs | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Microsoft.Toolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs b/Microsoft.Toolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs index e5c13a5f179..63f1ed9a4c8 100644 --- a/Microsoft.Toolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs +++ b/Microsoft.Toolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs @@ -803,15 +803,15 @@ public ref T DangerousGetReferenceAt(int i, int j) /// /// The target row to map within the current instance. /// The target column to map within the current instance. - /// The width to map within the current instance. /// The height to map within the current instance. + /// The width to map within the current instance. /// /// Thrown when either , or /// are negative or not within the bounds that are valid for the current instance. /// /// A new instance representing a slice of the current one. [Pure] - public ReadOnlySpan2D Slice(int row, int column, int width, int height) + public ReadOnlySpan2D Slice(int row, int column, int height, int width) { if ((uint)row >= Height) { @@ -823,14 +823,14 @@ public ReadOnlySpan2D Slice(int row, int column, int width, int height) ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } - if ((uint)width > (this.width - column)) + if ((uint)height > (Height - row)) { - ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); + ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } - if ((uint)height > (Height - row)) + if ((uint)width > (this.width - column)) { - ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); + ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } nint shift = ((nint)(uint)this.stride * (nint)(uint)row) + (nint)(uint)column; diff --git a/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_ReadOnlySpan2D{T}.cs b/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_ReadOnlySpan2D{T}.cs index 75f127bdf5f..951d7b73d46 100644 --- a/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_ReadOnlySpan2D{T}.cs +++ b/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_ReadOnlySpan2D{T}.cs @@ -412,7 +412,7 @@ public void Test_ReadOnlySpan2DT_Slice_1() ReadOnlySpan2D span2d = new ReadOnlySpan2D(array); - ReadOnlySpan2D slice1 = span2d.Slice(1, 1, 2, 1); + ReadOnlySpan2D slice1 = span2d.Slice(1, 1, 1, 2); Assert.AreEqual(slice1.Length, 2); Assert.AreEqual(slice1.Height, 1); @@ -431,11 +431,11 @@ public void Test_ReadOnlySpan2DT_Slice_1() Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(-1, 1, 1, 1)); Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(1, -1, 1, 1)); - Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(1, 1, -1, 1)); Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(1, 1, 1, -1)); + Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(1, 1, -1, 1)); Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(10, 1, 1, 1)); - Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(1, 12, 12, 1)); - Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(1, 1, 1, 55)); + Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(1, 12, 1, 12)); + Assert.ThrowsException(() => new ReadOnlySpan2D(array).Slice(1, 1, 55, 1)); } [TestCategory("ReadOnlySpan2DT")] @@ -458,7 +458,7 @@ public void Test_ReadOnlySpan2DT_Slice_2() Assert.AreEqual(slice1[0, 0], 1); Assert.AreEqual(slice1[1, 1], 5); - ReadOnlySpan2D slice2 = slice1.Slice(1, 0, 2, 1); + ReadOnlySpan2D slice2 = slice1.Slice(1, 0, 1, 2); Assert.AreEqual(slice2.Length, 2); Assert.AreEqual(slice2.Height, 1); From 6e40cf80e38ddd058ccdbafd5203b257d390c5c8 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 20 Apr 2021 12:21:07 +0200 Subject: [PATCH 2/2] Added new unit tests for [ReadOnly]Span2D indexers --- .../Memory/Test_ReadOnlySpan2D{T}.cs | 83 +++++++++++++++++++ .../Memory/Test_Span2D{T}.cs | 83 +++++++++++++++++++ 2 files changed, 166 insertions(+) diff --git a/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_ReadOnlySpan2D{T}.cs b/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_ReadOnlySpan2D{T}.cs index 951d7b73d46..6c71c8b7de8 100644 --- a/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_ReadOnlySpan2D{T}.cs +++ b/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_ReadOnlySpan2D{T}.cs @@ -400,6 +400,89 @@ ref Unsafe.AsRef(null), Assert.IsTrue(Unsafe.AreSame(ref r0, ref array[0, 0])); } +#if NETCOREAPP3_1_OR_GREATER + [TestCategory("Span2DT")] + [TestMethod] + public unsafe void Test_ReadOnlySpan2DT_Index_Indexer_1() + { + int[,] array = new int[4, 4]; + + ReadOnlySpan2D span2d = new ReadOnlySpan2D(array); + + ref int arrayRef = ref array[1, 3]; + ref readonly int span2dRef = ref span2d[1, ^1]; + + Assert.IsTrue(Unsafe.AreSame(ref arrayRef, ref Unsafe.AsRef(in span2dRef))); + } + + [TestCategory("Span2DT")] + [TestMethod] + public unsafe void Test_ReadOnlySpan2DT_Index_Indexer_2() + { + int[,] array = new int[4, 4]; + + ReadOnlySpan2D span2d = new ReadOnlySpan2D(array); + + ref int arrayRef = ref array[2, 1]; + ref readonly int span2dRef = ref span2d[^2, ^3]; + + Assert.IsTrue(Unsafe.AreSame(ref arrayRef, ref Unsafe.AsRef(in span2dRef))); + } + + [TestCategory("Span2DT")] + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public unsafe void Test_ReadOnlySpan2DT_Index_Indexer_Fail() + { + int[,] array = new int[4, 4]; + + ReadOnlySpan2D span2d = new ReadOnlySpan2D(array); + + ref readonly int span2dRef = ref span2d[^6, 2]; + } + + [TestCategory("Span2DT")] + [TestMethod] + public unsafe void Test_ReadOnlySpan2DT_Range_Indexer_1() + { + int[,] array = new int[4, 4]; + + ReadOnlySpan2D span2d = new ReadOnlySpan2D(array); + ReadOnlySpan2D slice = span2d[1.., 1..]; + + Assert.AreEqual(slice.Length, 9); + Assert.IsTrue(Unsafe.AreSame(ref array[1, 1], ref Unsafe.AsRef(in slice[0, 0]))); + Assert.IsTrue(Unsafe.AreSame(ref array[3, 3], ref Unsafe.AsRef(in slice[2, 2]))); + } + + [TestCategory("Span2DT")] + [TestMethod] + public unsafe void Test_ReadOnlySpan2DT_Range_Indexer_2() + { + int[,] array = new int[4, 4]; + + ReadOnlySpan2D span2d = new ReadOnlySpan2D(array); + ReadOnlySpan2D slice = span2d[0..^2, 1..^1]; + + Assert.AreEqual(slice.Length, 4); + Assert.IsTrue(Unsafe.AreSame(ref array[0, 1], ref Unsafe.AsRef(in slice[0, 0]))); + Assert.IsTrue(Unsafe.AreSame(ref array[1, 2], ref Unsafe.AsRef(in slice[1, 1]))); + } + + [TestCategory("Span2DT")] + [TestMethod] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public unsafe void Test_ReadOnlySpan2DT_Range_Indexer_Fail() + { + int[,] array = new int[4, 4]; + + ReadOnlySpan2D span2d = new ReadOnlySpan2D(array); + _ = span2d[0..6, 2..^1]; + + Assert.Fail(); + } +#endif + [TestCategory("ReadOnlySpan2DT")] [TestMethod] public void Test_ReadOnlySpan2DT_Slice_1() diff --git a/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_Span2D{T}.cs b/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_Span2D{T}.cs index 57d4b65e21e..3d661d581b1 100644 --- a/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_Span2D{T}.cs +++ b/UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_Span2D{T}.cs @@ -564,6 +564,89 @@ ref Unsafe.AsRef(null), Assert.IsTrue(Unsafe.AreSame(ref r0, ref array[0, 0])); } +#if NETCOREAPP3_1_OR_GREATER + [TestCategory("Span2DT")] + [TestMethod] + public unsafe void Test_Span2DT_Index_Indexer_1() + { + int[,] array = new int[4, 4]; + + Span2D span2d = new Span2D(array); + + ref int arrayRef = ref array[1, 3]; + ref int span2dRef = ref span2d[1, ^1]; + + Assert.IsTrue(Unsafe.AreSame(ref arrayRef, ref span2dRef)); + } + + [TestCategory("Span2DT")] + [TestMethod] + public unsafe void Test_Span2DT_Index_Indexer_2() + { + int[,] array = new int[4, 4]; + + Span2D span2d = new Span2D(array); + + ref int arrayRef = ref array[2, 1]; + ref int span2dRef = ref span2d[^2, ^3]; + + Assert.IsTrue(Unsafe.AreSame(ref arrayRef, ref span2dRef)); + } + + [TestCategory("Span2DT")] + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public unsafe void Test_Span2DT_Index_Indexer_Fail() + { + int[,] array = new int[4, 4]; + + Span2D span2d = new Span2D(array); + + ref int span2dRef = ref span2d[^6, 2]; + } + + [TestCategory("Span2DT")] + [TestMethod] + public unsafe void Test_Span2DT_Range_Indexer_1() + { + int[,] array = new int[4, 4]; + + Span2D span2d = new Span2D(array); + Span2D slice = span2d[1.., 1..]; + + Assert.AreEqual(slice.Length, 9); + Assert.IsTrue(Unsafe.AreSame(ref array[1, 1], ref slice[0, 0])); + Assert.IsTrue(Unsafe.AreSame(ref array[3, 3], ref slice[2, 2])); + } + + [TestCategory("Span2DT")] + [TestMethod] + public unsafe void Test_Span2DT_Range_Indexer_2() + { + int[,] array = new int[4, 4]; + + Span2D span2d = new Span2D(array); + Span2D slice = span2d[0..^2, 1..^1]; + + Assert.AreEqual(slice.Length, 4); + Assert.IsTrue(Unsafe.AreSame(ref array[0, 1], ref slice[0, 0])); + Assert.IsTrue(Unsafe.AreSame(ref array[1, 2], ref slice[1, 1])); + } + + [TestCategory("Span2DT")] + [TestMethod] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public unsafe void Test_Span2DT_Range_Indexer_Fail() + { + int[,] array = new int[4, 4]; + + Span2D span2d = new Span2D(array); + _ = span2d[0..6, 2..^1]; + + Assert.Fail(); + } +#endif + [TestCategory("Span2DT")] [TestMethod] public void Test_Span2DT_Slice_1()