diff --git a/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index 486ad29db961..9936f6695440 100644 --- a/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -301,6 +301,9 @@ public partial struct Vector : System.IEquatable>, public Vector(T value) { throw null; } public Vector(T[] values) { throw null; } public Vector(T[] values, int index) { throw null; } +#if netcoreapp + public Vector(Span values) { throw null; } +#endif public static int Count { get { throw null; } } public T this[int index] { get { throw null; } } public static System.Numerics.Vector One { get { throw null; } } diff --git a/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.csproj b/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.csproj index b585b3369a1e..7a37775f689f 100644 --- a/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.csproj +++ b/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.csproj @@ -3,7 +3,10 @@ {650277B5-9423-4ACE-BB54-2659995B21C7} - true + true + true + true + $(DefineConstants);netcoreapp @@ -22,14 +25,14 @@ - + - + diff --git a/src/System.Numerics.Vectors/src/ApiCompatBaseline.uapaot.txt b/src/System.Numerics.Vectors/src/ApiCompatBaseline.uapaot.txt new file mode 100644 index 000000000000..bc7a12f52664 --- /dev/null +++ b/src/System.Numerics.Vectors/src/ApiCompatBaseline.uapaot.txt @@ -0,0 +1 @@ +MembersMustExist : Member 'System.Numerics.Vector..ctor(System.Span)' does not exist in the implementation but it does exist in the contract. \ No newline at end of file diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/System.Numerics.Vectors/tests/GenericVectorTests.cs index e03022a21608..eb0e588d6483 100644 --- a/src/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -14,7 +14,7 @@ namespace System.Numerics.Tests /// /// Vector{T} tests that use random number generation and a unified generic test structure /// - public class GenericVectorTests + public partial class GenericVectorTests { // Static constructor in top-level class\ static System.Numerics.Vector dummy; @@ -2699,11 +2699,11 @@ private static void ValidateVector(Vector vector, Action indexVali } } - internal static T[] GenerateRandomValuesForVector() where T : struct + internal static T[] GenerateRandomValuesForVector(int? numValues = null) where T : struct { int minValue = GetMinValue(); int maxValue = GetMaxValue(); - return Util.GenerateRandomValues(Vector.Count, minValue, maxValue); + return Util.GenerateRandomValues(numValues ?? Vector.Count, minValue, maxValue); } internal static int GetMinValue() where T : struct @@ -2776,4 +2776,4 @@ internal static T GetValueWithAllOnesSet() where T : struct } #endregion } -} \ No newline at end of file +} diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.cs b/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.cs new file mode 100644 index 000000000000..cb5ed7b81ae8 --- /dev/null +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.cs @@ -0,0 +1,226 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; +using Xunit; +using Xunit.Sdk; + +namespace System.Numerics.Tests +{ + /// + /// Vector{T} tests that use random number generation and a unified generic test structure + /// + public partial class GenericVectorTests + { + #region Constructor Tests + + #region Tests for Span based constructor + [Fact] + public void ConstructorWithSpanByte() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanSByte() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanUInt16() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanInt16() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanUInt32() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanInt32() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanUInt64() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanInt64() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanSingle() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanDouble() => TestConstructorWithSpan(); + + private void TestConstructorWithSpan() where T : struct + { + T[] values = GenerateRandomValuesForVector().ToArray(); + var valueSpan = new Span(values); + + var vector = new Vector(valueSpan); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[index], val); + }); + } + + [Fact] + public void SpanBasedConstructorWithLessElements_Byte() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_SByte() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_UInt16() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Int16() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_UInt32() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Int32() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_UInt64() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Int64() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Single() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Double() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + + private void TestSpanBasedConstructorWithLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count - 1).ToArray(); + var vector = new Vector(new Span(values)); + } + + #endregion Tests for Span based constructor + + #region Tests for Array based constructor + + [Fact] + public void ArrayBasedConstructor_Byte() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_SByte() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_UInt16() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Int16() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_UInt32() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Int32() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_UInt64() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Int64() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Single() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Double() => TestArrayBasedConstructor(); + + private void TestArrayBasedConstructor() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count).ToArray(); + var vector = new Vector(values); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[index], val); + }); + } + + [Fact] + public void ArrayIndexBasedConstructor_Byte() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_SByte() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_UInt16() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Int16() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_UInt32() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Int32() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_UInt64() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Int64() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Single() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Double() => TestArrayIndexBasedConstructor(); + + private void TestArrayIndexBasedConstructor() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count * 2).ToArray(); + int offset = Vector.Count - 1; + var vector = new Vector(values, offset); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[offset + index], val); + }); + } + + [Fact] + public void ArrayBasedConstructorWithLessElements_Byte() => TestArrayBasedConstructorWithLessElements(); + [Fact] + public void ArrayBasedConstructorWithLessElements_SByte() => TestArrayBasedConstructorWithLessElements(); + [Fact] + public void ArrayBasedConstructorWithLessElements_UInt16() => TestArrayBasedConstructorWithLessElements(); + [Fact] + public void ArrayBasedConstructorWithLessElements_Int16() => TestArrayBasedConstructorWithLessElements(); + [Fact] + public void ArrayBasedConstructorWithLessElements_UInt32() => TestArrayBasedConstructorWithLessElements(); + [Fact] + public void ArrayBasedConstructorWithLessElements_Int32() => TestArrayBasedConstructorWithLessElements(); + [Fact] + public void ArrayBasedConstructorWithLessElements_UInt64() => TestArrayBasedConstructorWithLessElements(); + [Fact] + public void ArrayBasedConstructorWithLessElements_Int64() => TestArrayBasedConstructorWithLessElements(); + [Fact] + public void ArrayBasedConstructorWithLessElements_Single() => TestArrayBasedConstructorWithLessElements(); + [Fact] + public void ArrayBasedConstructorWithLessElements_Double() => TestArrayBasedConstructorWithLessElements(); + + private void TestArrayBasedConstructorWithLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count - 1).ToArray(); + Assert.Throws(() => new Vector(values)); + } + + [Fact] + public void ArrayIndexBasedConstructorLessElements_Byte() => TestArrayIndexBasedConstructorLessElements(); + [Fact] + public void ArrayIndexBasedConstructorLessElements_SByte() => TestArrayIndexBasedConstructorLessElements(); + [Fact] + public void ArrayIndexBasedConstructorLessElements_UInt16() => TestArrayIndexBasedConstructorLessElements(); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Int16() => TestArrayIndexBasedConstructorLessElements(); + [Fact] + public void ArrayIndexBasedConstructorLessElements_UInt32() => TestArrayIndexBasedConstructorLessElements(); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Int32() => TestArrayIndexBasedConstructorLessElements(); + [Fact] + public void ArrayIndexBasedConstructorLessElements_UInt64() => TestArrayIndexBasedConstructorLessElements(); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Int64() => TestArrayIndexBasedConstructorLessElements(); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Single() => TestArrayIndexBasedConstructorLessElements(); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Double() => TestArrayIndexBasedConstructorLessElements(); + + private void TestArrayIndexBasedConstructorLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count * 2).ToArray(); + Assert.Throws(() => new Vector(values, Vector.Count + 1)); + } + + #endregion Tests for Array based constructor + + #region Tests for constructors using unsupported types + + [Fact] + public void ConstructorWithUnsupportedTypes_Guid() => TestConstructorWithUnsupportedTypes(); + [Fact] + public void ConstructorWithUnsupportedTypes_DateTime() => TestConstructorWithUnsupportedTypes(); + [Fact] + public void ConstructorWithUnsupportedTypes_Char() => TestConstructorWithUnsupportedTypes(); + + private void TestConstructorWithUnsupportedTypes() where T : struct + { + Assert.Throws(() => new Vector(new Span(new T[4]))); + } + + #endregion Tests for constructors using unsupported types + + #endregion Constructor Tests + } +} diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.tt b/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.tt new file mode 100644 index 000000000000..68a0c15077d3 --- /dev/null +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.tt @@ -0,0 +1,174 @@ +<#@ template debug="true" hostSpecific="true" #> +<#@ output extension=".cs" #> +<#@ Assembly Name="System.Core.dll" #> +<#@ Assembly Name="System.Xml.dll" #> +<#@ import namespace="System" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Runtime.InteropServices" #> +<#@ include file="..\..\Common\src\CoreLib\System\Numerics\GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #> + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; +using Xunit; +using Xunit.Sdk; + +namespace System.Numerics.Tests +{ + /// + /// Vector{T} tests that use random number generation and a unified generic test structure + /// + public partial class GenericVectorTests + { + #region Constructor Tests + + #region Tests for Span based constructor +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ConstructorWithSpan<#=type.Name#>() => TestConstructorWithSpan<<#=type.Name#>>(); +<# + } +#> + + private void TestConstructorWithSpan() where T : struct + { + T[] values = GenerateRandomValuesForVector().ToArray(); + var valueSpan = new Span(values); + + var vector = new Vector(valueSpan); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[index], val); + }); + } + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void SpanBasedConstructorWithLessElements_<#=type.Name#>() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements<<#=type.Name#>>()); +<# + } +#> + + private void TestSpanBasedConstructorWithLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count - 1).ToArray(); + var vector = new Vector(new Span(values)); + } + + #endregion Tests for Span based constructor + + #region Tests for Array based constructor + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ArrayBasedConstructor_<#=type.Name#>() => TestArrayBasedConstructor<<#=type.Name#>>(); +<# + } +#> + + private void TestArrayBasedConstructor() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count).ToArray(); + var vector = new Vector(values); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[index], val); + }); + } + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ArrayIndexBasedConstructor_<#=type.Name#>() => TestArrayIndexBasedConstructor<<#=type.Name#>>(); +<# + } +#> + + private void TestArrayIndexBasedConstructor() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count * 2).ToArray(); + int offset = Vector.Count - 1; + var vector = new Vector(values, offset); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[offset + index], val); + }); + } + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ArrayBasedConstructorWithLessElements_<#=type.Name#>() => TestArrayBasedConstructorWithLessElements<<#=type.Name#>>(); +<# + } +#> + + private void TestArrayBasedConstructorWithLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count - 1).ToArray(); + Assert.Throws(() => new Vector(values)); + } + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ArrayIndexBasedConstructorLessElements_<#=type.Name#>() => TestArrayIndexBasedConstructorLessElements<<#=type.Name#>>(); +<# + } +#> + + private void TestArrayIndexBasedConstructorLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count * 2).ToArray(); + Assert.Throws(() => new Vector(values, Vector.Count + 1)); + } + + #endregion Tests for Array based constructor + + #region Tests for constructors using unsupported types + +<# + Type[] unsupportedTypes = new[] + { + typeof(Guid), typeof(DateTime), typeof(char) + }; + + + foreach (var type in unsupportedTypes) + { +#> + [Fact] + public void ConstructorWithUnsupportedTypes_<#=type.Name#>() => TestConstructorWithUnsupportedTypes<<#=type.Name#>>(); +<# + } +#> + + private void TestConstructorWithUnsupportedTypes() where T : struct + { + Assert.Throws(() => new Vector(new Span(new T[4]))); + } + + #endregion Tests for constructors using unsupported types + + #endregion Constructor Tests + } +} diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.tt b/src/System.Numerics.Vectors/tests/GenericVectorTests.tt index 4790b1ac50f1..5fbd230724d2 100644 --- a/src/System.Numerics.Vectors/tests/GenericVectorTests.tt +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.tt @@ -5,7 +5,7 @@ <#@ import namespace="System" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Runtime.InteropServices" #> -<#@ include file="..\src\System\Numerics\GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #> +<#@ include file="..\..\common\src\corelib\System\Numerics\GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #> using System; using System.Globalization; @@ -19,7 +19,7 @@ namespace System.Numerics.Tests /// /// Vector{T} tests that use random number generation and a unified generic test structure /// - public class GenericVectorTests + public partial class GenericVectorTests { // Static constructor in top-level class\ static System.Numerics.Vector dummy; @@ -116,7 +116,7 @@ namespace System.Numerics.Tests }); } -<# +<# foreach (var type in supportedTypes) { #> @@ -1792,11 +1792,11 @@ namespace System.Numerics.Tests } } - internal static T[] GenerateRandomValuesForVector() where T : struct + internal static T[] GenerateRandomValuesForVector(int? numValues = null) where T : struct { int minValue = GetMinValue(); int maxValue = GetMaxValue(); - return Util.GenerateRandomValues(Vector.Count, minValue, maxValue); + return Util.GenerateRandomValues(numValues ?? Vector.Count, minValue, maxValue); } internal static int GetMinValue() where T : struct @@ -1869,4 +1869,4 @@ namespace System.Numerics.Tests } #endregion } -} \ No newline at end of file +} diff --git a/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.cs b/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.cs new file mode 100644 index 000000000000..4220c380852f --- /dev/null +++ b/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.cs @@ -0,0 +1,352 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using Xunit; +using Xunit.Sdk; +using Microsoft.Xunit.Performance; + +namespace System.Numerics.Tests +{ + public static class Constructor + { + private static Random s_random = new Random(); + + public const int DefaultInnerIterationsCount = 100000000; + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Byte() + { + Byte[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_SByte() + { + SByte[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_UInt16() + { + UInt16[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Int16() + { + Int16[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_UInt32() + { + UInt32[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Int32() + { + Int32[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_UInt64() + { + UInt64[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Int64() + { + Int64[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Single() + { + Single[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Double() + { + Double[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + + public static void Construct(Span values) where T : struct + { + for (var iteration = 0; iteration < Benchmark.InnerIterationCount; iteration++) + { + Vector vect = new Vector(values); + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Byte() + { + Byte[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_SByte() + { + SByte[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_UInt16() + { + UInt16[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Int16() + { + Int16[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_UInt32() + { + UInt32[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Int32() + { + Int32[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_UInt64() + { + UInt64[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Int64() + { + Int64[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Single() + { + Single[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Double() + { + Double[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + + public static void SpanCast(ReadOnlySpan values) where T : struct + { + for (var iteration = 0; iteration < Benchmark.InnerIterationCount; iteration++) + { + ReadOnlySpan> vectors = MemoryMarshal.Cast>(values); + Vector vector = vectors[0]; + } + } + + internal static T[] GenerateRandomValuesForVector() where T : struct + { + int minValue = GetMinValue(); + int maxValue = GetMaxValue(); + return Util.GenerateRandomValues(Vector.Count, minValue, maxValue); + } + + internal static int GetMinValue() where T : struct + { + if (typeof(T) == typeof(Int64) || typeof(T) == typeof(Single) || typeof(T) == typeof(Double) || typeof(T) == typeof(UInt32) || typeof(T) == typeof(UInt64)) + { + return int.MinValue; + } + TypeInfo typeInfo = typeof(T).GetTypeInfo(); + FieldInfo field = typeInfo.GetDeclaredField("MinValue"); + var value = field.GetValue(null); + return (int)(dynamic)value; + } + + internal static int GetMaxValue() where T : struct + { + if (typeof(T) == typeof(Int64) || typeof(T) == typeof(Single) || typeof(T) == typeof(Double) || typeof(T) == typeof(UInt32) || typeof(T) == typeof(UInt64)) + { + return int.MaxValue; + } + TypeInfo typeInfo = typeof(T).GetTypeInfo(); + FieldInfo field = typeInfo.GetDeclaredField("MaxValue"); + var value = field.GetValue(null); + return (int)(dynamic)value; + } + } +} diff --git a/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.tt b/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.tt new file mode 100644 index 000000000000..5fb58ea5a784 --- /dev/null +++ b/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.tt @@ -0,0 +1,119 @@ +<#@ template debug="true" hostSpecific="true" #> +<#@ output extension=".cs" #> +<#@ Assembly Name="System.Core.dll" #> +<#@ Assembly Name="System.Xml.dll" #> +<#@ import namespace="System" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Runtime.InteropServices" #> +<#@ include file="..\..\..\..\Common\src\CoreLib\System\Numerics\GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #> + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using Xunit; +using Xunit.Sdk; +using Microsoft.Xunit.Performance; + +namespace System.Numerics.Tests +{ + public static class Constructor + { + private static Random s_random = new Random(); + + public const int DefaultInnerIterationsCount = 100000000; + +<# + foreach (var type in supportedTypes) + { +#> + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_<#=type.Name#>() + { + <#=type.Name#>[] arrValues = GenerateRandomValuesForVector<<#=type.Name#>>(); + var spanValues = new Span<<#=type.Name#>>(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct<<#=type.Name#>>(spanValues); + } + } + } + +<# + } +#> + + public static void Construct(Span values) where T : struct + { + for (var iteration = 0; iteration < Benchmark.InnerIterationCount; iteration++) + { + Vector vect = new Vector(values); + } + } + +<# + foreach (var type in supportedTypes) + { +#> + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_<#=type.Name#>() + { + <#=type.Name#>[] arrValues = GenerateRandomValuesForVector<<#=type.Name#>>(); + var spanValues = new ReadOnlySpan<<#=type.Name#>>(arrValues); + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast<<#=type.Name#>>(spanValues); + } + } + } + +<# + } +#> + + public static void SpanCast(ReadOnlySpan values) where T : struct + { + for (var iteration = 0; iteration < Benchmark.InnerIterationCount; iteration++) + { + ReadOnlySpan> vectors = MemoryMarshal.Cast>(values); + Vector vector = vectors[0]; + } + } + + internal static T[] GenerateRandomValuesForVector() where T : struct + { + int minValue = GetMinValue(); + int maxValue = GetMaxValue(); + return Util.GenerateRandomValues(Vector.Count, minValue, maxValue); + } + + internal static int GetMinValue() where T : struct + { + if (typeof(T) == typeof(Int64) || typeof(T) == typeof(Single) || typeof(T) == typeof(Double) || typeof(T) == typeof(UInt32) || typeof(T) == typeof(UInt64)) + { + return int.MinValue; + } + TypeInfo typeInfo = typeof(T).GetTypeInfo(); + FieldInfo field = typeInfo.GetDeclaredField("MinValue"); + var value = field.GetValue(null); + return (int)(dynamic)value; + } + + internal static int GetMaxValue() where T : struct + { + if (typeof(T) == typeof(Int64) || typeof(T) == typeof(Single) || typeof(T) == typeof(Double) || typeof(T) == typeof(UInt32) || typeof(T) == typeof(UInt64)) + { + return int.MaxValue; + } + TypeInfo typeInfo = typeof(T).GetTypeInfo(); + FieldInfo field = typeInfo.GetDeclaredField("MaxValue"); + var value = field.GetValue(null); + return (int)(dynamic)value; + } + } +} diff --git a/src/System.Numerics.Vectors/tests/Performance/System.Numerics.Vectors.Performance.Tests.csproj b/src/System.Numerics.Vectors/tests/Performance/System.Numerics.Vectors.Performance.Tests.csproj index 842a2b5a1cd5..318d8f0e627a 100644 --- a/src/System.Numerics.Vectors/tests/Performance/System.Numerics.Vectors.Performance.Tests.csproj +++ b/src/System.Numerics.Vectors/tests/Performance/System.Numerics.Vectors.Performance.Tests.csproj @@ -63,7 +63,29 @@ + + TextTemplatingFileGenerator + GenericVectorConstructorTests.cs + + + + + + + Util.cs + + + True + True + GenericVectorConstructorTests.tt + + + + + GenerationConfig.ttinclude + + \ No newline at end of file diff --git a/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj b/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj index fc5d885a9281..a79a3da3e2f5 100644 --- a/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj +++ b/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj @@ -35,6 +35,13 @@ System\MathF.netstandard.cs + + + True + True + GenericVectorTests.netcoreapp.tt + + ConstantHelper.tt @@ -50,7 +57,14 @@ + + + + TextTemplatingFileGenerator + GenericVectorTests.netcoreapp.cs + + \ No newline at end of file