From 666f1fabfa38b45448b8526e4fbfeb3ceae2fd68 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Tue, 30 Jul 2019 14:15:31 +0100 Subject: [PATCH 01/30] - Convert SumF function into a generic function - Add new managed types (sbyte, byte, short, ushort, int, uint, long, ulong) - Add tests for some of the new types - Add new Benchmark tests --- Benchmarks/Benchmarks.cs | 314 +++++++++++++++++------------- LinqFaster.sln.DotSettings | 2 + LinqFaster/Sum.cs | 192 +++++++++--------- LinqFaster/Utils/NumericPolicy.cs | 97 +++++++++ Tests/SumTests.cs | 12 +- Tests/Test.cs | 6 + docs/linqfaster.xml | 35 +--- 7 files changed, 404 insertions(+), 254 deletions(-) create mode 100644 LinqFaster.sln.DotSettings create mode 100644 LinqFaster/Utils/NumericPolicy.cs diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index d3579b4..f26d748 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -20,12 +20,13 @@ public class Benchmarks const int LARGE_TEST_SIZE = 1000000; const int SMALL_TEST_SIZE = 100; - - public List list; - public int[] array; + public byte[] byteArray; + public short[] shortArray; + public int[] intArray; public int[] array2; public float[] floatArray; + public double[] doubleArray; public string[] strarray; @@ -34,205 +35,254 @@ public class Benchmarks public Benchmarks() { - - } [GlobalSetup] public void Setup() { Random r = new Random(); - array = new int[TEST_SIZE]; + byteArray = new byte[TEST_SIZE]; + shortArray = new short[TEST_SIZE]; + intArray = new int[TEST_SIZE]; array2 = new int[TEST_SIZE]; floatArray = new float[TEST_SIZE]; + doubleArray = new double[TEST_SIZE]; list = new List(TEST_SIZE); strarray = new string[TEST_SIZE]; for (int i = 0; i < TEST_SIZE; i++) { - array[i] = i % 2; + intArray[i] = i % 2; + byteArray[i] = (byte)intArray[i]; + shortArray[i] = (short)intArray[i]; array2[i] = i % 2; - list.Add(array[i]); - strarray[i] = array[i].ToString(); - floatArray[i] = array[i]; + list.Add(intArray[i]); + strarray[i] = intArray[i].ToString(); + floatArray[i] = intArray[i]; + doubleArray[i] = floatArray[i]; } array2[TEST_SIZE / 2] = 0; } + //[Benchmark] + //public int OrderByLinq() + //{ + // return intArray.OrderBy((x => x -1)).Sum(); + //} - /* - [Benchmark] - public int OrderByLinq() - { - return array.OrderBy((x => x -1)).Sum(); - } - - [Benchmark] - public int OrderByFast() - { - return array.OrderByF((x => x - 1)).Sum(); - } - + //[Benchmark] + //public int OrderByFast() + //{ + // return intArray.OrderByF((x => x - 1)).Sum(); + //} - [Benchmark] - public int SumLinq() + public int ByteSumLinq() { - return array.Sum(); + return byteArray.Aggregate(0, (current, b1) => current + b1); } [Benchmark] - public int SumFast() + public uint ByteSumFast() { - return array.SumF(); + return byteArray.SumF(); } - [Benchmark] - public int SumFastSIMD() - { - return array.SumS(); - } [Benchmark] - public double AverageLinq() + public int ShortSumLinq() { - return array.Average(); + return shortArray.Aggregate(0, (current, s1) => current + s1); } [Benchmark] - public double AverageFast() + public int ShortSumFast() { - return array.AverageF(); + return shortArray.SumF(); } - [Benchmark] - public double AverageFastSIMD() - { - return array.AverageS(); - } [Benchmark] - public int SumWithSelectLinq() + public int IntSumLinq() { - return array.Sum(x => x / 2); + return intArray.Sum(); } [Benchmark] - public int SumWithSelectFast() + public int IntSumFast() { - return array.SumF(x => x/2); - } - - - [Benchmark] - public double WhereAggregateLinq() - { - return array.Where(x => x % 2 == 0).Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / array.Length); + return intArray.SumF(); } - [Benchmark] - public double WhereAggregateFast() - { - return array.WhereAggregateF(x => x % 2 == 0,0.0,(acc,x)=> acc += x*x,acc => acc/array.Length); - } - [Benchmark] - public int[] SelectFast() - { - return array.SelectF(x => x * x); - } + //[Benchmark] + //public int SumFastSIMD() + //{ + // return intArray.SumS(); + //} [Benchmark] - public int[] SelectFastSIMD() + public float FloatSumLinq() { - return array.SelectS(x => x * x, x=>x*x); + return floatArray.Sum(); } - - [Benchmark] - public int[] RepeatLinq() + public float FloatSumFast() { - return Enumerable.Repeat(5, TEST_SIZE).ToArray(); + return floatArray.SumF(); } - [Benchmark] - public int[] RepeastFast() - { - return LinqFaster.RepeatArrayF(5, TEST_SIZE); - } - - - [Benchmark] - public int[] RepeastFastSIMD() - { - return LinqFasterSIMD.RepeatS(5, TEST_SIZE); - } - - [Benchmark] - public int[] RepeastFastSIMDB() - { - return LinqFasterSIMD.RepeatSB(5, TEST_SIZE); - } - - [Benchmark] - public int MinLinq() - { - return array.Min(); - } - - [Benchmark] - public int MinFast() - { - return array.MinF(); - } - - [Benchmark] - public int MinFastSIMD() - { - return array.MinS(); - } - - [Benchmark] - public bool SequenceEqual() - { - return array.SequenceEqual(array2); - }*/ - - [Benchmark] - public bool SequenceEqualF() - { - return array.SequenceEqualF(array2); - } - - - /* - [Benchmark] - public bool SequenceEqualP() - { - return array.SequenceEqualP(array2); - } [Benchmark] - public bool SequenceEqualS() + public double DoubleSumLinq() { - return array.SequenceEqualS(array2); + return doubleArray.Sum(); } [Benchmark] - public bool SequenceEqualSP() + public double DoubleSumFast() { - return array.SequenceEqualSP(array2); + return doubleArray.SumF(); } - */ + //[Benchmark] + //public double AverageLinq() + //{ + // return intArray.Average(); + //} + + //[Benchmark] + //public double AverageFast() + //{ + // return intArray.AverageF(); + //} + + //[Benchmark] + //public double AverageFastSIMD() + //{ + // return intArray.AverageS(); + //} + + //[Benchmark] + //public int SumWithSelectLinq() + //{ + // return intArray.Sum(x => x / 2); + //} + + //[Benchmark] + //public int SumWithSelectFast() + //{ + // return intArray.SumF(x => x/2); + //} + + + //[Benchmark] + //public double WhereAggregateLinq() + //{ + // return intArray.Where(x => x % 2 == 0).Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); + //} + + //[Benchmark] + //public double WhereAggregateFast() + //{ + // return intArray.WhereAggregateF(x => x % 2 == 0,0.0,(acc,x)=> acc += x*x,acc => acc/array.Length); + //} + + //[Benchmark] + //public int[] SelectFast() + //{ + // return intArray.SelectF(x => x * x); + //} + + //[Benchmark] + //public int[] SelectFastSIMD() + //{ + // return intArray.SelectS(x => x * x, x=>x*x); + //} + + + + //[Benchmark] + //public int[] RepeatLinq() + //{ + // return Enumerable.Repeat(5, TEST_SIZE).ToArray(); + //} + + //[Benchmark] + //public int[] RepeastFast() + //{ + // return LinqFaster.RepeatArrayF(5, TEST_SIZE); + //} + + + //[Benchmark] + //public int[] RepeastFastSIMD() + //{ + // return LinqFasterSIMD.RepeatS(5, TEST_SIZE); + //} + + //[Benchmark] + //public int[] RepeastFastSIMDB() + //{ + // return LinqFasterSIMD.RepeatSB(5, TEST_SIZE); + //} + + //[Benchmark] + //public int MinLinq() + //{ + // return intArray.Min(); + //} + + //[Benchmark] + //public int MinFast() + //{ + // return intArray.MinF(); + //} + + //[Benchmark] + //public int MinFastSIMD() + //{ + // return intArray.MinS(); + //} + + //[Benchmark] + //public bool SequenceEqual() + //{ + // return intArray.SequenceEqual(array2); + //} + + //[Benchmark] + //public bool SequenceEqualF() + //{ + // return intArray.SequenceEqualF(array2); + //} + + + //[Benchmark] + //public bool SequenceEqualP() + //{ + // return intArray.SequenceEqualP(array2); + //} + + //[Benchmark] + //public bool SequenceEqualS() + //{ + // return intArray.SequenceEqualS(array2); + //} + + //[Benchmark] + //public bool SequenceEqualSP() + //{ + // return intArray.SequenceEqualSP(array2); + //} public static void Main(string[] args) { - - var summary = BenchmarkRunner.Run(ManualConfig.Create(DefaultConfig.Instance).With(Job.RyuJitX64)); + Console.WriteLine(BenchmarkRunner.Run(ManualConfig.Create(DefaultConfig.Instance).With(Job.RyuJitX64)).ResultsDirectoryPath); + Console.WriteLine("Press enter to close"); Console.ReadLine(); } diff --git a/LinqFaster.sln.DotSettings b/LinqFaster.sln.DotSettings new file mode 100644 index 0000000..b417e4c --- /dev/null +++ b/LinqFaster.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/LinqFaster/Sum.cs b/LinqFaster/Sum.cs index e10b6ac..0f06a33 100644 --- a/LinqFaster/Sum.cs +++ b/LinqFaster/Sum.cs @@ -1,5 +1,8 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; + +using JM.LinqFaster.Utils; namespace JM.LinqFaster @@ -13,21 +16,114 @@ public static partial class LinqFaster /// /// The sequence to add. /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this byte[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this sbyte[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this ushort[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this short[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this uint[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SumF(this int[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong SumF(this ulong[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long SumF(this long[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float SumF(this float[] source) + { + return (float)NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double SumF(this double[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal SumF(this decimal[] source) + { + return NumericPolicies.Instance.SumF(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 SumF(this P p, T1[] source) + where P : INumericPolicy + where T1 : IConvertible + where T2 : IConvertible { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } - int sum = 0; + + T2 a = p.Zero(); checked { - foreach (var v in source) + foreach (T1 b in source) { - sum += v; + a = p.Add(a, b); } } - return sum; + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T SumF(this P p, T[] source) + where P : INumericPolicy + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + T a = p.Zero(); + checked + { + foreach (T b in source) + { + a = p.Add(a, b); + } + } + + return a; } /// @@ -59,28 +155,6 @@ public static int SumF(this T[] source, Func selector) return sum; } - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static long SumF(this long[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - long sum = 0; - checked - { - foreach (var v in source) - { - sum += v; - } - } - return sum; - } - /// /// Adds the transformed sequence of elements. /// @@ -110,27 +184,6 @@ public static long SumF(this T[] source, Func selector) return sum; } - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static float SumF(this float[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - - foreach (var v in source) - { - sum += v; - } - - return (float)sum; - } - /// /// Adds the transformed sequence of elements. /// @@ -158,26 +211,6 @@ public static float SumF(this T[] source, Func selector) return (float)sum; } - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static double SumF(this double[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - foreach (var v in source) - { - sum += v; - } - - return sum; - } - /// /// Adds the transformed sequence of elements. /// @@ -205,27 +238,6 @@ public static double SumF(this T[] source, Func selector) return sum; } - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static decimal SumF(this decimal[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - decimal sum = 0; - - foreach (var v in source) - { - sum += v; - } - - return sum; - } - /// /// Adds the transformed sequence of elements. /// @@ -254,7 +266,7 @@ public static decimal SumF(this T[] source, Func selector) } /*---- Spans ---*/ - + /// /// Adds a sequence of values. /// diff --git a/LinqFaster/Utils/NumericPolicy.cs b/LinqFaster/Utils/NumericPolicy.cs new file mode 100644 index 0000000..b439a31 --- /dev/null +++ b/LinqFaster/Utils/NumericPolicy.cs @@ -0,0 +1,97 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace JM.LinqFaster.Utils +{ + internal interface INumericPolicy + { + T Zero(); + + T Add(T a, T b); + } + + internal interface INumericPolicy + where T1 : IConvertible + { + T2 Zero(); + + T2 Add(T2 a, T1 b); + } + + /// + /// checked will be done at the for LOOP level + /// + [StructLayout(LayoutKind.Sequential, Size = 1)] + public struct NumericPolicies : + INumericPolicy, + INumericPolicy, + INumericPolicy, + INumericPolicy, + INumericPolicy, + INumericPolicy, + INumericPolicy, + INumericPolicy, + INumericPolicy, + INumericPolicy, + INumericPolicy + { + public static NumericPolicies Instance; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INumericPolicy.Zero() { return 0U; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INumericPolicy.Add(uint a, byte b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INumericPolicy.Zero() { return 0; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INumericPolicy.Add(int a, sbyte b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INumericPolicy.Zero() { return 0U; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INumericPolicy.Add(uint a, ushort b) { return a + b;} + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INumericPolicy.Zero() { return 0;} + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INumericPolicy.Add(int a, short b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INumericPolicy.Zero() { return 0U; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INumericPolicy.Add(uint a, uint b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INumericPolicy.Zero() { return 0; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INumericPolicy.Add(int a, int b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + ulong INumericPolicy.Zero() { return 0UL; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + ulong INumericPolicy.Add(ulong a, ulong b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + long INumericPolicy.Zero() { return 0; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + long INumericPolicy.Add(long a, long b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + double INumericPolicy.Zero() { return 0.0F; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + double INumericPolicy.Add(double a, float b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + double INumericPolicy.Zero() { return 0.0D; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + double INumericPolicy.Add(double a, double b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + decimal INumericPolicy.Zero() { return new decimal(0, 0, 0, false, 1); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + decimal INumericPolicy.Add(decimal a, decimal b) { return a + b; } + + } +} diff --git a/Tests/SumTests.cs b/Tests/SumTests.cs index bc66a61..554b909 100644 --- a/Tests/SumTests.cs +++ b/Tests/SumTests.cs @@ -13,18 +13,24 @@ public void SumArray() { var a = intArray.SumF(); var b = intArray.Sum(); - Assert.That(a, Is.EqualTo(b)); var c = floatArray.SumF(); var d = floatArray.Sum(); - Assert.That(c, Is.EqualTo(d)); var e = decimalArray.SumF(); var f = decimalArray.Sum(); - Assert.That(e, Is.EqualTo(f)); + + var g = byteArray.SumF(); + var h = byteArray.Aggregate(0, (current, b1) => current + b1); + Assert.That(g, Is.EqualTo(h)); + + var i = shortArray.SumF(); + var j = shortArray.Aggregate(0, (current, s1) => current + s1); + Assert.That(i, Is.EqualTo(j)); + } [Test] diff --git a/Tests/Test.cs b/Tests/Test.cs index 47cba34..395af24 100644 --- a/Tests/Test.cs +++ b/Tests/Test.cs @@ -8,6 +8,8 @@ namespace Tests public class Test { public const int TEST_SIZE = 1000; + public static byte[] byteArray; + public static short[] shortArray; public static int[] intArray; public static long[] longArray; public static float[] floatArray; @@ -40,6 +42,8 @@ public void Setup() squaredInts = (x => x * x); addXInts = (x, acc) => acc += x; + byteArray = new byte[TEST_SIZE]; + shortArray = new short[TEST_SIZE]; intArray = new int[TEST_SIZE]; floatArray = new float[TEST_SIZE]; intList = new List(TEST_SIZE); @@ -56,6 +60,8 @@ public void Setup() for (int i = 0; i < intArray.Length;i++) { intArray[i] = rand.Next(-100, 100); + byteArray[i] = (byte) intArray[i]; + shortArray[i] = (short) intArray[i]; intList.Add(intArray[i]); longArray[i] = intArray[i]; longList.Add(intArray[i]); diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index eea205f..882b0eb 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -1763,7 +1763,7 @@ A function to test each element for a condition. A sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate. - + Adds a sequence of values. @@ -1778,13 +1778,6 @@ A transformation function. The sum of the transformed elements. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds the transformed sequence of elements. @@ -1793,13 +1786,6 @@ A transformation function. The sum of the transformed elements. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds the transformed sequence of elements. @@ -1808,13 +1794,6 @@ A transformation function. The sum of the transformed elements. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds the transformed sequence of elements. @@ -1823,13 +1802,6 @@ A transformation function. The sum of the transformed elements. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds the transformed sequence of elements. @@ -2564,5 +2536,10 @@ A function that specifies how to merge the elements from the two sequences. A sequence that contains merged elements of two input sequences. + + + checked will be done at the for LOOP level + + From cf405acb742c2245666b29e86ccd0cc32b673995 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Wed, 31 Jul 2019 09:41:07 +0100 Subject: [PATCH 02/30] SumF for an Array - Make sure publics have Intellisense - Add Nullable types - Perform template on source selectors --- Benchmarks/Benchmarks.cs | 96 ++++-- LinqFaster/Sum.cs | 475 ++++++++++++++++++++++++------ LinqFaster/Utils/NumericPolicy.cs | 91 +++++- Tests/SumTests.cs | 27 +- Tests/Test.cs | 3 + docs/linqfaster.xml | 205 ++++++++++++- 6 files changed, 753 insertions(+), 144 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index f26d748..2301c84 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -24,6 +24,7 @@ public class Benchmarks public byte[] byteArray; public short[] shortArray; public int[] intArray; + public int?[] intNullArray; public int[] array2; public float[] floatArray; public double[] doubleArray; @@ -44,6 +45,7 @@ public void Setup() byteArray = new byte[TEST_SIZE]; shortArray = new short[TEST_SIZE]; intArray = new int[TEST_SIZE]; + intNullArray = new int?[TEST_SIZE]; array2 = new int[TEST_SIZE]; floatArray = new float[TEST_SIZE]; doubleArray = new double[TEST_SIZE]; @@ -55,6 +57,7 @@ public void Setup() intArray[i] = i % 2; byteArray[i] = (byte)intArray[i]; shortArray[i] = (short)intArray[i]; + intNullArray[i] = intArray[i]; array2[i] = i % 2; list.Add(intArray[i]); strarray[i] = intArray[i].ToString(); @@ -77,30 +80,30 @@ public void Setup() //} - [Benchmark] - public int ByteSumLinq() - { - return byteArray.Aggregate(0, (current, b1) => current + b1); - } + //[Benchmark] + //public int ByteSumLinq() + //{ + // return byteArray.Aggregate(0, (current, b1) => current + b1); + //} - [Benchmark] - public uint ByteSumFast() - { - return byteArray.SumF(); - } + //[Benchmark] + //public uint ByteSumFast() + //{ + // return byteArray.SumF(); + //} - [Benchmark] - public int ShortSumLinq() - { - return shortArray.Aggregate(0, (current, s1) => current + s1); - } + //[Benchmark] + //public int ShortSumLinq() + //{ + // return shortArray.Aggregate(0, (current, s1) => current + s1); + //} - [Benchmark] - public int ShortSumFast() - { - return shortArray.SumF(); - } + //[Benchmark] + //public int ShortSumFast() + //{ + // return shortArray.SumF(); + //} [Benchmark] @@ -115,6 +118,17 @@ public int IntSumFast() return intArray.SumF(); } + [Benchmark] + public int IntSumLinqSelect() + { + return intArray.Sum(x=>x); + } + + [Benchmark] + public int IntSumFastSelect() + { + return intArray.SumF(x=>x); + } //[Benchmark] //public int SumFastSIMD() @@ -123,29 +137,47 @@ public int IntSumFast() //} [Benchmark] - public float FloatSumLinq() + public int? IntNullSumLinq() { - return floatArray.Sum(); + return intNullArray.Sum(); } [Benchmark] - public float FloatSumFast() + public int? IntNullSumFast() { - return floatArray.SumF(); + return intNullArray.SumF(); } - [Benchmark] - public double DoubleSumLinq() + public int? IntNullSumFastSelect() { - return doubleArray.Sum(); + return intNullArray.SumF(x => x ?? 0); } - [Benchmark] - public double DoubleSumFast() - { - return doubleArray.SumF(); - } + //[Benchmark] + //public float FloatSumLinq() + //{ + // return floatArray.Sum(); + //} + + //[Benchmark] + //public float FloatSumFast() + //{ + // return floatArray.SumF(); + //} + + + //[Benchmark] + //public double DoubleSumLinq() + //{ + // return doubleArray.Sum(); + //} + + //[Benchmark] + //public double DoubleSumFast() + //{ + // return doubleArray.SumF(); + //} //[Benchmark] //public double AverageLinq() diff --git a/LinqFaster/Sum.cs b/LinqFaster/Sum.cs index 0f06a33..b4d1156 100644 --- a/LinqFaster/Sum.cs +++ b/LinqFaster/Sum.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq.Expressions; using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; @@ -22,108 +23,182 @@ public static uint SumF(this byte[] source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SumF(this sbyte[] source) { return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint SumF(this ushort[] source) { return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SumF(this short[] source) { return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint SumF(this uint[] source) { - return NumericPolicies.Instance.SumF(source); + return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SumF(this int[] source) { - return NumericPolicies.Instance.SumF(source); + return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong SumF(this ulong[] source) { - return NumericPolicies.Instance.SumF(source); + return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long SumF(this long[] source) { - return NumericPolicies.Instance.SumF(source); + return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float SumF(this float[] source) { return (float)NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double SumF(this double[] source) { - return NumericPolicies.Instance.SumF(source); + return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal SumF(this decimal[] source) { - return NumericPolicies.Instance.SumF(source); + return NumericPolicies.Instance.SumF(source); } + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static T2 SumF(this P p, T1[] source) - where P : INumericPolicy - where T1 : IConvertible - where T2 : IConvertible + public static T2 SumF(this T[] source, Func selector) + where T : struct, IConvertible + where T2 : struct, IConvertible // Make sure these are not nullable { if (source == null) { throw Error.ArgumentNull(nameof(source)); } - T2 a = p.Zero(); + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + T2 a = default(T2); checked { - foreach (T1 b in source) + foreach (T b in source) { - a = p.Add(a, b); + a = GenericOperators.Add(a, selector(b)); } } return a; } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static T SumF(this P p, T[] source) - where P : INumericPolicy + public static uint? SumF(this byte?[] source) { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } + return NumericPolicies.Instance.SumFNullable(source); + } - T a = p.Zero(); - checked - { - foreach (T b in source) - { - a = p.Add(a, b); - } - } + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this byte?[] source, Func selector) + where T2 : struct, IConvertible + { + return SumFNullableSelector(source, selector); + } - return a; + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? SumF(this sbyte?[] source) + { + return NumericPolicies.Instance.SumFNullable(source); } /// @@ -132,27 +207,46 @@ public static decimal SumF(this decimal[] source) /// The sequence of values to transform then sum. /// A transformation function. /// The sum of the transformed elements. - public static int SumF(this T[] source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this sbyte?[] source, Func selector) + where T2 : struct, IConvertible { - if (source == null) - { - throw Error.ArgumentNull("source"); - } + return SumFNullableSelector(source, selector); + } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? SumF(this ushort?[] source) + { + return NumericPolicies.Instance.SumFNullable(source); + } - int sum = 0; - checked - { - foreach (var v in source) - { - sum += selector(v); - } - } - return sum; + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this ushort?[] source, Func selector) + where T2 : struct, IConvertible + { + return SumFNullableSelector(source, selector); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? SumF(this short?[] source) + { + return NumericPolicies.Instance.SumFNullable(source); } /// @@ -161,27 +255,166 @@ public static int SumF(this T[] source, Func selector) /// The sequence of values to transform then sum. /// A transformation function. /// The sum of the transformed elements. - public static long SumF(this T[] source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this short?[] source, Func selector) + where T2 : struct, IConvertible { - if (source == null) - { - throw Error.ArgumentNull("source"); - } + return SumFNullableSelector(source, selector); + } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? SumF(this uint?[] source) + { + return NumericPolicies.Instance.SumFNullable(source); + } - long sum = 0; - checked - { - foreach (var v in source) - { - sum += selector(v); - } - } - return sum; + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this uint?[] source, Func selector) + where T2 : struct, IConvertible + { + return SumFNullableSelector(source, selector); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? SumF(this int?[] source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this int?[] source, Func selector) + where T2 : struct, IConvertible + { + return SumFNullableSelector(source, selector); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong? SumF(this ulong?[] source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this ulong?[] source, Func selector) + where T2 : struct, IConvertible + { + return SumFNullableSelector(source, selector); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long? SumF(this long?[] source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this long?[] source, Func selector) + where T2 : struct, IConvertible + { + return SumFNullableSelector(source, selector); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float? SumF(this float?[] source) + { + return (float)NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this float?[] source, Func selector) + where T2 : struct, IConvertible + { + return SumFNullableSelector(source, selector); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double? SumF(this double?[] source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this double?[] source, Func selector) + where T2 : struct, IConvertible + { + return SumFNullableSelector(source, selector); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal? SumF(this decimal?[] source) + { + return NumericPolicies.Instance.SumFNullable(source); } /// @@ -190,65 +423,107 @@ public static long SumF(this T[] source, Func selector) /// The sequence of values to transform then sum. /// A transformation function. /// The sum of the transformed elements. - public static float SumF(this T[] source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this decimal?[] source, Func selector) + where T2 : struct, IConvertible + { + return SumFNullableSelector(source, selector); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 SumF(this P p, T1[] source) + where P : INumericPolicy + where T1 : IConvertible { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } - if (selector == null) + T2 a = p.Zero(); + checked { - throw Error.ArgumentNull("selector"); + foreach (T1 b in source) + { + a = p.Add(a, b); + } } - double sum = 0; - foreach (var v in source) + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T SumF(this P p, T[] source) + where P : INumericPolicy + { + if (source == null) { - sum += selector(v); + throw Error.ArgumentNull(nameof(source)); } - return (float)sum; + T a = p.Zero(); + checked + { + foreach (T b in source) + { + a = p.Add(a, b); + } + } + + return a; } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static double SumF(this T[] source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 SumFNullable(this P p, T1?[] source) + where P : INullableNumericPolicy + where T1 : struct, IConvertible { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } - if (selector == null) + T2 a = p.Zero(); + checked { - throw Error.ArgumentNull("selector"); + for (int index = 0; index < source.Length; index++) + { + a = p.Add(a, source[index]); + } } - double sum = 0; - foreach (var v in source) + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T SumFNullable(this P p, T?[] source) + where P : INullableNumericPolicy + where T : struct + { + if (source == null) { - sum += selector(v); + throw Error.ArgumentNull(nameof(source)); } - return sum; + T a = p.Zero(); + checked + { + for (int index = 0; index < source.Length; index++) + { + a = p.Add(a, source[index]); + } + } + + return a; } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static decimal SumF(this T[] source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 SumFNullableSelector(T?[] source, Func selector) + where T : struct { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -256,15 +531,19 @@ public static decimal SumF(this T[] source, Func selector) throw Error.ArgumentNull("selector"); } - decimal sum = 0; - foreach (var v in source) + T2 a = default(T2); + checked { - sum += selector(v); + foreach (T? b in source) + { + a = GenericOperators.Add(a, selector(b)); + } } - return sum; + return a; } + /*---- Spans ---*/ /// diff --git a/LinqFaster/Utils/NumericPolicy.cs b/LinqFaster/Utils/NumericPolicy.cs index b439a31..a9eff03 100644 --- a/LinqFaster/Utils/NumericPolicy.cs +++ b/LinqFaster/Utils/NumericPolicy.cs @@ -19,11 +19,28 @@ internal interface INumericPolicy T2 Add(T2 a, T1 b); } + internal interface INullableNumericPolicy + where T : struct + { + T Zero(); + + T Add(T a, Nullable b); + } + + internal interface INullableNumericPolicy + where T1 : struct, IConvertible + { + T2 Zero(); + + T2 Add(T2 a, Nullable b); + } + + /// /// checked will be done at the for LOOP level /// [StructLayout(LayoutKind.Sequential, Size = 1)] - public struct NumericPolicies : + internal struct NumericPolicies : INumericPolicy, INumericPolicy, INumericPolicy, @@ -34,9 +51,21 @@ public struct NumericPolicies : INumericPolicy, INumericPolicy, INumericPolicy, - INumericPolicy + INumericPolicy, + + INullableNumericPolicy, + INullableNumericPolicy, + INullableNumericPolicy, + INullableNumericPolicy, + INullableNumericPolicy, + INullableNumericPolicy, + INullableNumericPolicy, + INullableNumericPolicy, + INullableNumericPolicy, + INullableNumericPolicy, + INullableNumericPolicy { - public static NumericPolicies Instance; + internal static NumericPolicies Instance; [MethodImpl(MethodImplOptions.AggressiveInlining)] uint INumericPolicy.Zero() { return 0U; } @@ -93,5 +122,61 @@ public struct NumericPolicies : [MethodImpl(MethodImplOptions.AggressiveInlining)] decimal INumericPolicy.Add(decimal a, decimal b) { return a + b; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INullableNumericPolicy.Zero() { return 0U; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INullableNumericPolicy.Add(uint a, byte? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INullableNumericPolicy.Zero() { return 0; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INullableNumericPolicy.Add(int a, sbyte? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INullableNumericPolicy.Zero() { return 0U; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INullableNumericPolicy.Add(uint a, ushort? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INullableNumericPolicy.Zero() { return 0; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INullableNumericPolicy.Add(int a, short? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INullableNumericPolicy.Zero() { return 0U; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint INullableNumericPolicy.Add(uint a, uint? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INullableNumericPolicy.Zero() { return 0; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + int INullableNumericPolicy.Add(int a, int? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + ulong INullableNumericPolicy.Zero() { return 0UL; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + ulong INullableNumericPolicy.Add(ulong a, ulong? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + long INullableNumericPolicy.Zero() { return 0; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + long INullableNumericPolicy.Add(long a, long? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + double INullableNumericPolicy.Zero() { return 0.0F; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + double INullableNumericPolicy.Add(double a, float? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + double INullableNumericPolicy.Zero() { return 0.0D; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + double INullableNumericPolicy.Add(double a, double? b) { return a + b ?? a; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + decimal INullableNumericPolicy.Zero() { return new decimal(0, 0, 0, false, 1); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + decimal INullableNumericPolicy.Add(decimal a, decimal? b) { return a + b ?? a; } + } } diff --git a/Tests/SumTests.cs b/Tests/SumTests.cs index 554b909..4a99e15 100644 --- a/Tests/SumTests.cs +++ b/Tests/SumTests.cs @@ -1,19 +1,27 @@ -using NUnit.Framework; +using System.Linq; + using JM.LinqFaster; -using System.Linq; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class SumTests + internal class SumTests { [Test] - public void SumArray() + public void SumArray() { var a = intArray.SumF(); var b = intArray.Sum(); Assert.That(a, Is.EqualTo(b)); + var an = intNullArray.SumF(); + var bn = intNullArray.Sum(); + var cn = intNullArray.SumF(x => x ?? 0); + Assert.That(an, Is.EqualTo(bn)); + Assert.That(an, Is.EqualTo(cn)); var c = floatArray.SumF(); var d = floatArray.Sum(); @@ -33,11 +41,17 @@ public void SumArray() } + [Test] - public void SumArraySelector() { + public void SumArraySelector() + { var a = intArray.SumF(x => x + 1); var b = intArray.Sum(x => x + 1); + var an = intNullArray.SumF(x => x ?? 0); + var bn = intNullArray.Sum(x => x ?? 0); + Assert.That(an, Is.EqualTo(bn)); + Assert.That(a, Is.EqualTo(b)); var c = floatArray.SumF(squaredFloats); @@ -66,7 +80,8 @@ public void SumList() } [Test] - public void SumListSelector() { + public void SumListSelector() + { var a = intList.SumF(x => x + 1); var b = intList.Sum(x => x + 1); diff --git a/Tests/Test.cs b/Tests/Test.cs index 395af24..6e0b911 100644 --- a/Tests/Test.cs +++ b/Tests/Test.cs @@ -11,6 +11,7 @@ public class Test public static byte[] byteArray; public static short[] shortArray; public static int[] intArray; + public static int?[] intNullArray; public static long[] longArray; public static float[] floatArray; public static double[] doubleArray; @@ -45,6 +46,7 @@ public void Setup() byteArray = new byte[TEST_SIZE]; shortArray = new short[TEST_SIZE]; intArray = new int[TEST_SIZE]; + intNullArray = new int?[TEST_SIZE]; floatArray = new float[TEST_SIZE]; intList = new List(TEST_SIZE); floatList = new List(TEST_SIZE); @@ -62,6 +64,7 @@ public void Setup() intArray[i] = rand.Next(-100, 100); byteArray[i] = (byte) intArray[i]; shortArray[i] = (short) intArray[i]; + intNullArray[i] = intArray[i]; intList.Add(intArray[i]); longArray[i] = intArray[i]; longList.Add(intArray[i]); diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 882b0eb..c0aee69 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -1770,7 +1770,159 @@ The sequence to add. The sum of the sequence. - + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + Adds the transformed sequence of elements. @@ -1778,7 +1930,29 @@ A transformation function. The sum of the transformed elements. - + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + Adds the transformed sequence of elements. @@ -1786,7 +1960,14 @@ A transformation function. The sum of the transformed elements. - + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + Adds the transformed sequence of elements. @@ -1794,7 +1975,14 @@ A transformation function. The sum of the transformed elements. - + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + Adds the transformed sequence of elements. @@ -1802,7 +1990,14 @@ A transformation function. The sum of the transformed elements. - + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + Adds the transformed sequence of elements. From 4eb6b167a808f530544806dc096ccca4b336bb96 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Wed, 31 Jul 2019 10:29:44 +0100 Subject: [PATCH 03/30] - Split the Sum types out - Apply template to Spans - Apply Template to List --- Benchmarks/Benchmarks.cs | 69 +++- LinqFaster/{Sum.cs => SumArrays.cs} | 499 +--------------------------- LinqFaster/SumList.cs | 213 ++++++++++++ LinqFaster/SumSpan.cs | 211 ++++++++++++ Tests/SumTests.cs | 11 +- Tests/Test.cs | 6 + docs/linqfaster.xml | 148 +++++---- 7 files changed, 595 insertions(+), 562 deletions(-) rename LinqFaster/{Sum.cs => SumArrays.cs} (57%) create mode 100644 LinqFaster/SumList.cs create mode 100644 LinqFaster/SumSpan.cs diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 2301c84..1721b15 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -24,10 +24,12 @@ public class Benchmarks public byte[] byteArray; public short[] shortArray; public int[] intArray; - public int?[] intNullArray; + private int?[] intNullArray; public int[] array2; public float[] floatArray; + private float?[] floatNullArray; public double[] doubleArray; + private double?[] doubleNullArray; public string[] strarray; @@ -48,7 +50,9 @@ public void Setup() intNullArray = new int?[TEST_SIZE]; array2 = new int[TEST_SIZE]; floatArray = new float[TEST_SIZE]; + floatNullArray = new float?[TEST_SIZE]; doubleArray = new double[TEST_SIZE]; + doubleNullArray = new double?[TEST_SIZE]; list = new List(TEST_SIZE); strarray = new string[TEST_SIZE]; @@ -62,7 +66,9 @@ public void Setup() list.Add(intArray[i]); strarray[i] = intArray[i].ToString(); floatArray[i] = intArray[i]; + floatNullArray[i] = floatArray[i]; doubleArray[i] = floatArray[i]; + doubleNullArray[i] = doubleArray[i]; } array2[TEST_SIZE / 2] = 0; } @@ -149,7 +155,7 @@ public int IntSumFastSelect() } [Benchmark] - public int? IntNullSumFastSelect() + public int IntNullSumFastSelect() { return intNullArray.SumF(x => x ?? 0); } @@ -166,6 +172,35 @@ public int IntSumFastSelect() // return floatArray.SumF(); //} + [Benchmark] + public float FloatSumLinqSelect() + { + return floatArray.Sum(x => x); + } + + [Benchmark] + public float FloatSumFastSelect() + { + return floatArray.SumF(x => x); + } + + [Benchmark] + public float ? FloatNullSumLinq() + { + return floatNullArray.Sum(); + } + + [Benchmark] + public float ? FloatNullSumFast() + { + return floatNullArray.SumF(); + } + + [Benchmark] + public float FloatNullSumFastSelect() + { + return floatNullArray.SumF(x => x ?? 0); + } //[Benchmark] //public double DoubleSumLinq() @@ -179,6 +214,36 @@ public int IntSumFastSelect() // return doubleArray.SumF(); //} + [Benchmark] + public double DoubleSumLinqSelect() + { + return doubleArray.Sum(x => x); + } + + [Benchmark] + public double DoubleSumFastSelect() + { + return doubleArray.SumF(x => x); + } + + [Benchmark] + public double ? DoubleNullSumLinq() + { + return doubleNullArray.Sum(); + } + + [Benchmark] + public double ? DoubleNullSumFast() + { + return doubleNullArray.SumF(); + } + + [Benchmark] + public double ? DoubleNullSumFastSelect() + { + return doubleNullArray.SumF(x => x ?? 0); + } + //[Benchmark] //public double AverageLinq() //{ diff --git a/LinqFaster/Sum.cs b/LinqFaster/SumArrays.cs similarity index 57% rename from LinqFaster/Sum.cs rename to LinqFaster/SumArrays.cs index b4d1156..2d145d7 100644 --- a/LinqFaster/Sum.cs +++ b/LinqFaster/SumArrays.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq.Expressions; using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; @@ -453,7 +451,7 @@ public static T2 SumF(this decimal?[] source, Func selector) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static T SumF(this P p, T[] source) + private static T SumF(this P p, T[] source) where P : INumericPolicy { if (source == null) @@ -543,500 +541,5 @@ public static T2 SumF(this decimal?[] source, Func selector) return a; } - - /*---- Spans ---*/ - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static int SumF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - int sum = 0; - checked - { - foreach (var v in source) - { - sum += v; - } - } - return sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static int SumF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - int sum = 0; - checked - { - foreach (var v in source) - { - sum += selector(v); - } - } - return sum; - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static long SumF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - long sum = 0; - checked - { - foreach (var v in source) - { - sum += v; - } - } - return sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static long SumF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - foreach (var v in source) - { - sum += selector(v); - } - } - return sum; - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static float SumF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - - foreach (var v in source) - { - sum += v; - } - - return (float)sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static float SumF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - foreach (var v in source) - { - sum += selector(v); - } - - return (float)sum; - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static double SumF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - foreach (var v in source) - { - sum += v; - } - - return sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static double SumF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - foreach (var v in source) - { - sum += selector(v); - } - - return sum; - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static decimal SumF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - decimal sum = 0; - - foreach (var v in source) - { - sum += v; - } - - return sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static decimal SumF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - decimal sum = 0; - foreach (var v in source) - { - sum += selector(v); - } - - return sum; - } - - // -------------------------- LISTS -------------------------------------------- - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static int SumF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - int sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - } - return sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static int SumF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - int sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - } - return sum; - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static long SumF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - long sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - } - return sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static long SumF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - } - return sum; - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static float SumF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - - return (float)sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static float SumF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - - return (float)sum; - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static double SumF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - - return sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static double SumF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - - return sum; - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. - public static decimal SumF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - decimal sum = 0; - - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - - return sum; - } - - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - public static decimal SumF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - decimal sum = 0; - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - - return sum; - } - } } diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs new file mode 100644 index 0000000..b757a11 --- /dev/null +++ b/LinqFaster/SumList.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +using JM.LinqFaster.Utils; + + +namespace JM.LinqFaster +{ + public static partial class LinqFaster + { + // -------------------------- Lists -------------------------------------------- + // TODO: Add the nullable types in + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float SumF(this List source) + { + return (float)NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal SumF(this List source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this List source, Func selector) + where T : struct, IConvertible + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + T2 a = default(T2); + checked + { + for (int index = 0; index < source.Count; index++) + { + a = GenericOperators.Add(a, selector(source[index])); + } + } + + return a; + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 SumF(this P p, List source) + where P : INumericPolicy + where T1 : IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + T2 a = p.Zero(); + checked + { + for (int index = 0; index < source.Count; index++) + { + a = p.Add(a, source[index]); + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T SumF(this P p, List source) + where P : INumericPolicy + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + T a = p.Zero(); + checked + { + for (int index = 0; index < source.Count; index++) + { + a = p.Add(a, source[index]); + } + } + + return a; + } + } +} diff --git a/LinqFaster/SumSpan.cs b/LinqFaster/SumSpan.cs new file mode 100644 index 0000000..9f39c30 --- /dev/null +++ b/LinqFaster/SumSpan.cs @@ -0,0 +1,211 @@ +using System; +using System.Runtime.CompilerServices; + +using JM.LinqFaster.Utils; + + +namespace JM.LinqFaster +{ + public static partial class LinqFaster + { + // -------------------------- SPANS -------------------------------------------- + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float SumF(this Span source) + { + return (float)NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal SumF(this Span source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this Span source, Func selector) + where T : struct, IConvertible + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + T2 a = default(T2); + checked + { + foreach (T b in source) + { + a = GenericOperators.Add(a, selector(b)); + } + } + + return a; + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 SumF(this P p, Span source) + where P : INumericPolicy + where T1 : IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + T2 a = p.Zero(); + checked + { + foreach (T1 b in source) + { + a = p.Add(a, b); + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T SumF(this P p, Span source) + where P : INumericPolicy + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + T a = p.Zero(); + checked + { + foreach (T b in source) + { + a = p.Add(a, b); + } + } + + return a; + } + } +} diff --git a/Tests/SumTests.cs b/Tests/SumTests.cs index 4a99e15..0cff5d3 100644 --- a/Tests/SumTests.cs +++ b/Tests/SumTests.cs @@ -19,13 +19,13 @@ public void SumArray() Assert.That(a, Is.EqualTo(b)); var an = intNullArray.SumF(); var bn = intNullArray.Sum(); - var cn = intNullArray.SumF(x => x ?? 0); Assert.That(an, Is.EqualTo(bn)); - Assert.That(an, Is.EqualTo(cn)); var c = floatArray.SumF(); var d = floatArray.Sum(); Assert.That(c, Is.EqualTo(d)); + var dn = floatNullArray.SumF(); + Assert.That(c, Is.EqualTo(dn)); var e = decimalArray.SumF(); var f = decimalArray.Sum(); @@ -39,6 +39,13 @@ public void SumArray() var j = shortArray.Aggregate(0, (current, s1) => current + s1); Assert.That(i, Is.EqualTo(j)); + var k = doubleArray.SumF(); + var l = doubleArray.Sum(); + Assert.That(k, Is.EqualTo(l)); + var ln = doubleNullArray.SumF(); + Assert.That(k, Is.EqualTo(ln)); + + } diff --git a/Tests/Test.cs b/Tests/Test.cs index 6e0b911..120f3f6 100644 --- a/Tests/Test.cs +++ b/Tests/Test.cs @@ -14,7 +14,9 @@ public class Test public static int?[] intNullArray; public static long[] longArray; public static float[] floatArray; + public static float?[] floatNullArray; public static double[] doubleArray; + public static double?[] doubleNullArray; public static decimal[] decimalArray; public static string[] stringArray; @@ -48,6 +50,7 @@ public void Setup() intArray = new int[TEST_SIZE]; intNullArray = new int?[TEST_SIZE]; floatArray = new float[TEST_SIZE]; + floatNullArray = new float?[TEST_SIZE]; intList = new List(TEST_SIZE); floatList = new List(TEST_SIZE); stringArray = new string[TEST_SIZE]; @@ -55,6 +58,7 @@ public void Setup() decimalArray = new decimal[TEST_SIZE]; decimalList = new List(TEST_SIZE); doubleArray = new double[TEST_SIZE]; + doubleNullArray = new double?[TEST_SIZE]; doubleList = new List(TEST_SIZE); longArray = new long[TEST_SIZE]; longList = new List(TEST_SIZE); @@ -69,12 +73,14 @@ public void Setup() longArray[i] = intArray[i]; longList.Add(intArray[i]); floatArray[i] = (float)rand.NextDouble() * 100.0f - 50f; + floatNullArray[i] = floatArray[i]; floatList.Add(intArray[i]); stringArray[i] = intArray[i].ToString(); stringList.Add(stringArray[i]); decimalArray[i] = (decimal)floatArray[i]; decimalList.Add(decimalArray[i]); doubleArray[i] = rand.NextDouble() * 10000.0 - 5000.0; + doubleNullArray[i] = doubleArray[i]; doubleList.Add(doubleArray[i]); } } diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index c0aee69..a40cec8 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -1840,6 +1840,14 @@ The sequence to add. The sum of the sequence. + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + Adds a sequence of values. @@ -2005,89 +2013,84 @@ A transformation function. The sum of the transformed elements. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds the transformed sequence of elements. @@ -2095,59 +2098,84 @@ A transformation function. The sum of the transformed elements. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. - + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds the transformed sequence of elements. From 71459b2cd7b389ed58de25d1c1d90c9c1c95c618 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Wed, 31 Jul 2019 11:33:46 +0100 Subject: [PATCH 04/30] - Fix float selector special case - Add List benchmarks --- Benchmarks/Benchmarks.cs | 162 +++++++++++++++++++++++++-------------- LinqFaster/SumArrays.cs | 37 +++++++++ LinqFaster/SumList.cs | 37 +++++++++ LinqFaster/SumSpan.cs | 37 +++++++++ docs/linqfaster.xml | 33 ++++++++ 5 files changed, 248 insertions(+), 58 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 1721b15..6293478 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -24,11 +24,14 @@ public class Benchmarks public byte[] byteArray; public short[] shortArray; public int[] intArray; + public List intList; private int?[] intNullArray; public int[] array2; public float[] floatArray; + public List floatList; private float?[] floatNullArray; public double[] doubleArray; + public List doubleList; private double?[] doubleNullArray; public string[] strarray; @@ -48,10 +51,13 @@ public void Setup() shortArray = new short[TEST_SIZE]; intArray = new int[TEST_SIZE]; intNullArray = new int?[TEST_SIZE]; + intList = new List(TEST_SIZE); array2 = new int[TEST_SIZE]; floatArray = new float[TEST_SIZE]; + floatList = new List(TEST_SIZE); floatNullArray = new float?[TEST_SIZE]; doubleArray = new double[TEST_SIZE]; + doubleList = new List(TEST_SIZE); doubleNullArray = new double?[TEST_SIZE]; list = new List(TEST_SIZE); strarray = new string[TEST_SIZE]; @@ -62,12 +68,15 @@ public void Setup() byteArray[i] = (byte)intArray[i]; shortArray[i] = (short)intArray[i]; intNullArray[i] = intArray[i]; + intList.Add(intArray[i]); array2[i] = i % 2; list.Add(intArray[i]); strarray[i] = intArray[i].ToString(); floatArray[i] = intArray[i]; + floatList.Add(floatArray[i]); floatNullArray[i] = floatArray[i]; doubleArray[i] = floatArray[i]; + doubleList.Add(doubleArray[i]); doubleNullArray[i] = doubleArray[i]; } array2[TEST_SIZE / 2] = 0; @@ -125,16 +134,28 @@ public int IntSumFast() } [Benchmark] - public int IntSumLinqSelect() + public int IntLSumLinq() { - return intArray.Sum(x=>x); + return intList.Sum(); } [Benchmark] - public int IntSumFastSelect() + public int IntLSumFast() { - return intArray.SumF(x=>x); + return intList.SumF(); } + + //[Benchmark] + //public int IntSumLinqSelect() + //{ + // return intArray.Sum(x=>x); + //} + + //[Benchmark] + //public int IntSumFastSelect() + //{ + // return intArray.SumF(x=>x); + //} //[Benchmark] //public int SumFastSIMD() @@ -142,108 +163,133 @@ public int IntSumFastSelect() // return intArray.SumS(); //} - [Benchmark] - public int? IntNullSumLinq() - { - return intNullArray.Sum(); - } - - [Benchmark] - public int? IntNullSumFast() - { - return intNullArray.SumF(); - } - - [Benchmark] - public int IntNullSumFastSelect() - { - return intNullArray.SumF(x => x ?? 0); - } + //[Benchmark] + //public int? IntNullSumLinq() + //{ + // return intNullArray.Sum(); + //} //[Benchmark] - //public float FloatSumLinq() + //public int? IntNullSumFast() //{ - // return floatArray.Sum(); + // return intNullArray.SumF(); //} //[Benchmark] - //public float FloatSumFast() + //public int IntNullSumFastSelect() //{ - // return floatArray.SumF(); + // return intNullArray.SumF(x => x ?? 0); //} [Benchmark] - public float FloatSumLinqSelect() + public float FloatSumLinq() { - return floatArray.Sum(x => x); + return floatArray.Sum(); } [Benchmark] - public float FloatSumFastSelect() + public float FloatSumFast() { - return floatArray.SumF(x => x); + return floatArray.SumF(); } [Benchmark] - public float ? FloatNullSumLinq() + public float FloatLSumLinq() { - return floatNullArray.Sum(); + return floatList.Sum(); } [Benchmark] - public float ? FloatNullSumFast() + public float FloatLSumFast() { - return floatNullArray.SumF(); + return floatList.SumF(); } - [Benchmark] - public float FloatNullSumFastSelect() - { - return floatNullArray.SumF(x => x ?? 0); - } + //[Benchmark] + //public float FloatSumLinqSelect() + //{ + // return floatArray.Sum(x => x); + //} //[Benchmark] - //public double DoubleSumLinq() + //public float FloatSumFastSelect() //{ - // return doubleArray.Sum(); + // return floatArray.SumF(x => x); //} //[Benchmark] - //public double DoubleSumFast() + //public float ? FloatNullSumLinq() //{ - // return doubleArray.SumF(); + // return floatNullArray.Sum(); + //} + + //[Benchmark] + //public float ? FloatNullSumFast() + //{ + // return floatNullArray.SumF(); + //} + + //[Benchmark] + //public float FloatNullSumFastSelect() + //{ + // return floatNullArray.SumF(x => x ?? 0); //} - [Benchmark] - public double DoubleSumLinqSelect() - { - return doubleArray.Sum(x => x); - } [Benchmark] - public double DoubleSumFastSelect() + public double DoubleSumLinq() { - return doubleArray.SumF(x => x); + return doubleArray.Sum(); } [Benchmark] - public double ? DoubleNullSumLinq() + public double DoubleSumFast() { - return doubleNullArray.Sum(); + return doubleArray.SumF(); } [Benchmark] - public double ? DoubleNullSumFast() + public double DoubleLSumLinq() { - return doubleNullArray.SumF(); + return doubleList.Sum(); } [Benchmark] - public double ? DoubleNullSumFastSelect() + public double DoubleLSumFast() { - return doubleNullArray.SumF(x => x ?? 0); + return doubleList.SumF(); } + //[Benchmark] + //public double DoubleSumLinqSelect() + //{ + // return doubleArray.Sum(x => x); + //} + + //[Benchmark] + //public double DoubleSumFastSelect() + //{ + // return doubleArray.SumF(x => x); + //} + + //[Benchmark] + //public double ? DoubleNullSumLinq() + //{ + // return doubleNullArray.Sum(); + //} + + //[Benchmark] + //public double ? DoubleNullSumFast() + //{ + // return doubleNullArray.SumF(); + //} + + //[Benchmark] + //public double ? DoubleNullSumFastSelect() + //{ + // return doubleNullArray.SumF(x => x ?? 0); + //} + //[Benchmark] //public double AverageLinq() //{ @@ -308,20 +354,20 @@ public double DoubleSumFastSelect() //} //[Benchmark] - //public int[] RepeastFast() + //public int[] RepeatFast() //{ // return LinqFaster.RepeatArrayF(5, TEST_SIZE); //} //[Benchmark] - //public int[] RepeastFastSIMD() + //public int[] RepeatFastSIMD() //{ // return LinqFasterSIMD.RepeatS(5, TEST_SIZE); //} //[Benchmark] - //public int[] RepeastFastSIMDB() + //public int[] RepeatFastSIMDB() //{ // return LinqFasterSIMD.RepeatSB(5, TEST_SIZE); //} diff --git a/LinqFaster/SumArrays.cs b/LinqFaster/SumArrays.cs index 2d145d7..21f7d69 100644 --- a/LinqFaster/SumArrays.cs +++ b/LinqFaster/SumArrays.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; @@ -109,6 +110,42 @@ public static float SumF(this float[] source) return (float)NumericPolicies.Instance.SumF(source); } + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this float[] source, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + foreach (float b in source) + { + a = p.Add(a, selector(b).ToDouble(CultureInfo.InvariantCulture)); + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + /// /// Adds a sequence of values. /// diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index b757a11..2630332 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; @@ -111,6 +112,42 @@ public static float SumF(this List source) return (float)NumericPolicies.Instance.SumF(source); } + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this List source, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + foreach (float b in source) + { + a = p.Add(a, selector(b).ToDouble(CultureInfo.InvariantCulture)); + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + /// /// Adds a sequence of values. /// diff --git a/LinqFaster/SumSpan.cs b/LinqFaster/SumSpan.cs index 9f39c30..febe1e3 100644 --- a/LinqFaster/SumSpan.cs +++ b/LinqFaster/SumSpan.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; @@ -109,6 +110,42 @@ public static float SumF(this Span source) return (float)NumericPolicies.Instance.SumF(source); } + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this Span source, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + foreach (float b in source) + { + a = p.Add(a, selector(b).ToDouble(CultureInfo.InvariantCulture)); + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + /// /// Adds a sequence of values. /// diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index a40cec8..64d4b63 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -1826,6 +1826,17 @@ The sequence to add. The sum of the sequence. + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + Adds a sequence of values. @@ -2076,6 +2087,17 @@ The sequence to add. The sum of the sequence. + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + Adds a sequence of values. @@ -2161,6 +2183,17 @@ The sequence to add. The sum of the sequence. + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + Adds a sequence of values. From 8ee38496cf21e5e0cfd2748e62b461091e032641 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Wed, 31 Jul 2019 13:15:49 +0100 Subject: [PATCH 05/30] [Enhancement] Can these API's also work on IList #15 - Add SumF API's to redirect IList's to their base types --- Benchmarks/Benchmarks.cs | 147 ++++++++++++++++-------------- LinqFaster/SumList.cs | 187 ++++++++++++++++++++++++++++++++++++++- Tests/SumTests.cs | 2 +- docs/linqfaster.xml | 77 ++++++++++++++++ 4 files changed, 342 insertions(+), 71 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 6293478..1c9844b 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -83,209 +83,222 @@ public void Setup() } //[Benchmark] - //public int OrderByLinq() + //public int IntArrayOrderByLinq() //{ // return intArray.OrderBy((x => x -1)).Sum(); //} //[Benchmark] - //public int OrderByFast() + //public int IntArrayOrderByFast() //{ // return intArray.OrderByF((x => x - 1)).Sum(); //} //[Benchmark] - //public int ByteSumLinq() + //public int ByteArraySumLinq() //{ // return byteArray.Aggregate(0, (current, b1) => current + b1); //} //[Benchmark] - //public uint ByteSumFast() + //public uint ByteArraySumFast() //{ // return byteArray.SumF(); //} //[Benchmark] - //public int ShortSumLinq() + //public int ShortArraySumLinq() //{ // return shortArray.Aggregate(0, (current, s1) => current + s1); //} //[Benchmark] - //public int ShortSumFast() + //public int ShortArraySumFast() //{ // return shortArray.SumF(); //} [Benchmark] - public int IntSumLinq() + public int IntArraySumLinq() { return intArray.Sum(); } [Benchmark] - public int IntSumFast() + public int IntArraySumFast() { return intArray.SumF(); } [Benchmark] - public int IntLSumLinq() + public int IntListSumLinq() { return intList.Sum(); } [Benchmark] - public int IntLSumFast() + public int IntListSumFast() { return intList.SumF(); } - + + [Benchmark] + public int IntIListSumLinq() + { + return ((IList)intList).Sum(); + } + + [Benchmark] + public int IntIListSumFast() + { + return ((IList)intList).SumF(); + } + + //[Benchmark] - //public int IntSumLinqSelect() + //public int IntArraySumLinqSelect() //{ // return intArray.Sum(x=>x); //} //[Benchmark] - //public int IntSumFastSelect() + //public int IntArraySumFastSelect() //{ // return intArray.SumF(x=>x); //} //[Benchmark] - //public int SumFastSIMD() + //public int IntArraySumFastSIMD() //{ // return intArray.SumS(); //} //[Benchmark] - //public int? IntNullSumLinq() + //public int? IntNullArraySumLinq() //{ // return intNullArray.Sum(); //} //[Benchmark] - //public int? IntNullSumFast() + //public int? IntNullArraySumFast() //{ // return intNullArray.SumF(); //} //[Benchmark] - //public int IntNullSumFastSelect() + //public int IntNullArraySumFastSelect() //{ // return intNullArray.SumF(x => x ?? 0); //} - [Benchmark] - public float FloatSumLinq() - { - return floatArray.Sum(); - } + //[Benchmark] + //public float FloatArraySumLinq() + //{ + // return floatArray.Sum(); + //} - [Benchmark] - public float FloatSumFast() - { - return floatArray.SumF(); - } + //[Benchmark] + //public float FloatArraySumFast() + //{ + // return floatArray.SumF(); + //} - [Benchmark] - public float FloatLSumLinq() - { - return floatList.Sum(); - } + //[Benchmark] + //public float FloatListSumLinq() + //{ + // return floatList.Sum(); + //} - [Benchmark] - public float FloatLSumFast() - { - return floatList.SumF(); - } + //[Benchmark] + //public float FloatListSumFast() + //{ + // return floatList.SumF(); + //} //[Benchmark] - //public float FloatSumLinqSelect() + //public float FloatArraySumLinqSelect() //{ // return floatArray.Sum(x => x); //} //[Benchmark] - //public float FloatSumFastSelect() + //public float FloatArraySumFastSelect() //{ // return floatArray.SumF(x => x); //} //[Benchmark] - //public float ? FloatNullSumLinq() + //public float ? FloatNullArraySumLinq() //{ // return floatNullArray.Sum(); //} //[Benchmark] - //public float ? FloatNullSumFast() + //public float ? FloatNullArraySumFast() //{ // return floatNullArray.SumF(); //} //[Benchmark] - //public float FloatNullSumFastSelect() + //public float FloatNullArraySumFastSelect() //{ // return floatNullArray.SumF(x => x ?? 0); //} - [Benchmark] - public double DoubleSumLinq() - { - return doubleArray.Sum(); - } + //[Benchmark] + //public double DoubleArraySumLinq() + //{ + // return doubleArray.Sum(); + //} - [Benchmark] - public double DoubleSumFast() - { - return doubleArray.SumF(); - } + //[Benchmark] + //public double DoubleArraySumFast() + //{ + // return doubleArray.SumF(); + //} - [Benchmark] - public double DoubleLSumLinq() - { - return doubleList.Sum(); - } + //[Benchmark] + //public double DoubleListSumLinq() + //{ + // return doubleList.Sum(); + //} - [Benchmark] - public double DoubleLSumFast() - { - return doubleList.SumF(); - } + //[Benchmark] + //public double DoubleListSumFast() + //{ + // return doubleList.SumF(); + //} //[Benchmark] - //public double DoubleSumLinqSelect() + //public double DoubleArraySumLinqSelect() //{ // return doubleArray.Sum(x => x); //} //[Benchmark] - //public double DoubleSumFastSelect() + //public double DoubleArraySumFastSelect() //{ // return doubleArray.SumF(x => x); //} //[Benchmark] - //public double ? DoubleNullSumLinq() + //public double ? DoubleNullArraySumLinq() //{ // return doubleNullArray.Sum(); //} //[Benchmark] - //public double ? DoubleNullSumFast() + //public double ? DoubleNullArraySumFast() //{ // return doubleNullArray.SumF(); //} //[Benchmark] - //public double ? DoubleNullSumFastSelect() + //public double ? DoubleNullArraySumFastSelect() //{ // return doubleNullArray.SumF(x => x ?? 0); //} diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index 2630332..fe28d64 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; @@ -24,6 +25,22 @@ public static uint SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static uint SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is byte[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Aggregate(0U, (current, s1) => current + s1); + } + /// /// Adds a sequence of values. /// @@ -35,6 +52,22 @@ public static int SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static int SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is sbyte[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Aggregate(0, (current, s1) => current + s1); + } + /// /// Adds a sequence of values. /// @@ -46,6 +79,22 @@ public static uint SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static uint SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is ushort[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Aggregate(0U, (current, s1) => current + s1); + } + /// /// Adds a sequence of values. /// @@ -57,6 +106,22 @@ public static int SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static int SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is short[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Aggregate(0, (current, s1) => current + s1); + } + /// /// Adds a sequence of values. /// @@ -68,6 +133,22 @@ public static uint SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static uint SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is uint[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return (uint) source.Aggregate(0UL, (current, s1) => (current + s1)); + } + /// /// Adds a sequence of values. /// @@ -79,6 +160,22 @@ public static int SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static int SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is int[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Sum(); + } + /// /// Adds a sequence of values. /// @@ -90,6 +187,22 @@ public static ulong SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static ulong SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is ulong[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Aggregate(0UL, (current, s1) => (current + s1)); + } + /// /// Adds a sequence of values. /// @@ -101,6 +214,22 @@ public static long SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static long SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is long[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Sum(); + } + /// /// Adds a sequence of values. /// @@ -112,6 +241,22 @@ public static float SumF(this List source) return (float)NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static float SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is float[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Sum(); + } + /// /// Adds the transformed sequence of elements. /// @@ -159,6 +304,22 @@ public static double SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static double SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is double[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Sum(); + } + /// /// Adds a sequence of values. /// @@ -170,6 +331,22 @@ public static decimal SumF(this List source) return NumericPolicies.Instance.SumF(source); } + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static decimal SumF(this IList source) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (source is decimal[] sa) + return sa.SumF(); + if (source is List sl) + return sl.SumF(); + return source.Sum(); + } + /// /// Adds the transformed sequence of elements. /// @@ -191,10 +368,11 @@ public static decimal SumF(this List source) throw Error.ArgumentNull("selector"); } + int sourceCount = source.Count; T2 a = default(T2); checked { - for (int index = 0; index < source.Count; index++) + for (int index = 0; index < sourceCount; index++) { a = GenericOperators.Add(a, selector(source[index])); } @@ -214,10 +392,11 @@ public static decimal SumF(this List source) throw Error.ArgumentNull(nameof(source)); } + int sourceCount = source.Count; T2 a = p.Zero(); checked { - for (int index = 0; index < source.Count; index++) + for (int index = 0; index < sourceCount; index++) { a = p.Add(a, source[index]); } @@ -235,10 +414,11 @@ public static decimal SumF(this List source) throw Error.ArgumentNull(nameof(source)); } + int sourceCount = source.Count; T a = p.Zero(); checked { - for (int index = 0; index < source.Count; index++) + for (int index = 0; index < sourceCount; index++) { a = p.Add(a, source[index]); } @@ -246,5 +426,6 @@ public static decimal SumF(this List source) return a; } + } } diff --git a/Tests/SumTests.cs b/Tests/SumTests.cs index 0cff5d3..2cd4562 100644 --- a/Tests/SumTests.cs +++ b/Tests/SumTests.cs @@ -32,7 +32,7 @@ public void SumArray() Assert.That(e, Is.EqualTo(f)); var g = byteArray.SumF(); - var h = byteArray.Aggregate(0, (current, b1) => current + b1); + var h = byteArray.Aggregate(0U, (current, b1) => current + b1); Assert.That(g, Is.EqualTo(h)); var i = shortArray.SumF(); diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 64d4b63..7560a00 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -2031,6 +2031,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. @@ -2038,6 +2045,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. @@ -2045,6 +2059,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. @@ -2052,6 +2073,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. @@ -2059,6 +2087,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. @@ -2066,6 +2101,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. @@ -2073,6 +2115,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. @@ -2080,6 +2129,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. @@ -2087,6 +2143,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds the transformed sequence of elements. @@ -2105,6 +2168,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. @@ -2112,6 +2182,13 @@ The sequence to add. The sum of the sequence. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds the transformed sequence of elements. From cb6ce9dbcaa01061f896a561077e2a4fbf4924f1 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Wed, 31 Jul 2019 14:09:47 +0100 Subject: [PATCH 06/30] - Add Nullable types for List and IList --- Benchmarks/Benchmarks.cs | 6 + LinqFaster/SumArrays.cs | 186 +----------- LinqFaster/SumList.cs | 630 ++++++++++++++++++++++++++++++++++----- LinqFaster/SumSpan.cs | 3 +- Tests/SumTests.cs | 8 +- docs/linqfaster.xml | 253 ++++++++++------ 6 files changed, 738 insertions(+), 348 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 1c9844b..6e4b0c9 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -133,6 +133,12 @@ public int IntArraySumFast() return intArray.SumF(); } + [Benchmark] + public int IntIArraySumFast() + { + return ((IList)intArray).SumF(); + } + [Benchmark] public int IntListSumLinq() { diff --git a/LinqFaster/SumArrays.cs b/LinqFaster/SumArrays.cs index 21f7d69..b0529f6 100644 --- a/LinqFaster/SumArrays.cs +++ b/LinqFaster/SumArrays.cs @@ -3,6 +3,8 @@ using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global namespace JM.LinqFaster @@ -175,8 +177,7 @@ public static decimal SumF(this decimal[] source) /// A transformation function. /// The sum of the transformed elements. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this T[] source, Func selector) - where T : struct, IConvertible + public static T2 SumF(this T[] source, Func selector) where T2 : struct, IConvertible // Make sure these are not nullable { if (source == null) @@ -194,13 +195,15 @@ public static decimal SumF(this decimal[] source) { foreach (T b in source) { - a = GenericOperators.Add(a, selector(b)); + a = GenericOperators.Add(a, selector(b)); } } return a; } + #region Nullable types + /// /// Adds a sequence of values. /// @@ -212,19 +215,6 @@ public static decimal SumF(this decimal[] source) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this byte?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -236,19 +226,6 @@ public static T2 SumF(this byte?[] source, Func selector) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this sbyte?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -260,19 +237,6 @@ public static T2 SumF(this sbyte?[] source, Func selector) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this ushort?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -284,19 +248,6 @@ public static T2 SumF(this ushort?[] source, Func selector) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this short?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -308,19 +259,6 @@ public static T2 SumF(this short?[] source, Func selector) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this uint?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -332,19 +270,6 @@ public static T2 SumF(this uint?[] source, Func selector) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this int?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -356,19 +281,6 @@ public static T2 SumF(this int?[] source, Func selector) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this ulong?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -380,19 +292,6 @@ public static T2 SumF(this ulong?[] source, Func selector) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this long?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -404,19 +303,6 @@ public static T2 SumF(this long?[] source, Func selector) return (float)NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this float?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -428,19 +314,6 @@ public static T2 SumF(this float?[] source, Func selector) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this double?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - /// /// Adds a sequence of values. /// @@ -452,19 +325,6 @@ public static T2 SumF(this double?[] source, Func selector) return NumericPolicies.Instance.SumFNullable(source); } - /// - /// Adds the transformed sequence of elements. - /// - /// The sequence of values to transform then sum. - /// A transformation function. - /// The sum of the transformed elements. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this decimal?[] source, Func selector) - where T2 : struct, IConvertible - { - return SumFNullableSelector(source, selector); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static T2 SumF(this P p, T1[] source) where P : INumericPolicy @@ -521,9 +381,9 @@ public static T2 SumF(this decimal?[] source, Func selector) T2 a = p.Zero(); checked { - for (int index = 0; index < source.Length; index++) + foreach (T1? b in source) { - a = p.Add(a, source[index]); + a = p.Add(a, b); } } @@ -542,41 +402,17 @@ public static T2 SumF(this decimal?[] source, Func selector) T a = p.Zero(); checked - { - for (int index = 0; index < source.Length; index++) - { - a = p.Add(a, source[index]); - } - } - - return a; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static T2 SumFNullableSelector(T?[] source, Func selector) - where T : struct - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - T2 a = default(T2); - checked { foreach (T? b in source) { - a = GenericOperators.Add(a, selector(b)); + a = p.Add(a, b); } } return a; } + #endregion Nullable types + } } diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index fe28d64..2a56280 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -5,6 +5,8 @@ using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global namespace JM.LinqFaster @@ -12,7 +14,6 @@ namespace JM.LinqFaster public static partial class LinqFaster { // -------------------------- Lists -------------------------------------------- - // TODO: Add the nullable types in /// /// Adds a sequence of values. @@ -32,13 +33,17 @@ public static uint SumF(this List source) /// The sum of the sequence. public static uint SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is byte[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Aggregate(0U, (current, s1) => current + s1); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case byte[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0U, (current, s1) => current + s1); + } } /// @@ -59,13 +64,17 @@ public static int SumF(this List source) /// The sum of the sequence. public static int SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is sbyte[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Aggregate(0, (current, s1) => current + s1); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case sbyte[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0, (current, s1) => current + s1); + } } /// @@ -86,13 +95,17 @@ public static uint SumF(this List source) /// The sum of the sequence. public static uint SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is ushort[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Aggregate(0U, (current, s1) => current + s1); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case ushort[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0U, (current, s1) => current + s1); + } } /// @@ -113,13 +126,17 @@ public static int SumF(this List source) /// The sum of the sequence. public static int SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is short[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Aggregate(0, (current, s1) => current + s1); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case short[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0, (current, s1) => current + s1); + } } /// @@ -140,13 +157,17 @@ public static uint SumF(this List source) /// The sum of the sequence. public static uint SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is uint[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return (uint) source.Aggregate(0UL, (current, s1) => (current + s1)); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case uint[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return (uint) source.Aggregate(0UL, (current, s1) => (current + s1)); + } } /// @@ -167,13 +188,17 @@ public static int SumF(this List source) /// The sum of the sequence. public static int SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is int[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Sum(); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case int[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } } /// @@ -194,13 +219,17 @@ public static ulong SumF(this List source) /// The sum of the sequence. public static ulong SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is ulong[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Aggregate(0UL, (current, s1) => (current + s1)); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case ulong[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0UL, (current, s1) => (current + s1)); + } } /// @@ -221,13 +250,17 @@ public static long SumF(this List source) /// The sum of the sequence. public static long SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is long[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Sum(); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case long[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } } /// @@ -248,13 +281,17 @@ public static float SumF(this List source) /// The sum of the sequence. public static float SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is float[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Sum(); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case float[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } } /// @@ -311,13 +348,17 @@ public static double SumF(this List source) /// The sum of the sequence. public static double SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is double[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Sum(); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case double[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } } /// @@ -338,13 +379,17 @@ public static decimal SumF(this List source) /// The sum of the sequence. public static decimal SumF(this IList source) { - if (source == null) - throw Error.ArgumentNull(nameof(source)); - if (source is decimal[] sa) - return sa.SumF(); - if (source is List sl) - return sl.SumF(); - return source.Sum(); + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case decimal[] sa: + return sa.SumF(); + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } } /// @@ -355,7 +400,6 @@ public static decimal SumF(this IList source) /// The sum of the transformed elements. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T2 SumF(this List source, Func selector) - where T : struct, IConvertible where T2 : struct, IConvertible // Make sure these are not nullable { if (source == null) @@ -374,7 +418,7 @@ public static decimal SumF(this IList source) { for (int index = 0; index < sourceCount; index++) { - a = GenericOperators.Add(a, selector(source[index])); + a = GenericOperators.Add(a, selector(source[index])); } } @@ -427,5 +471,431 @@ public static decimal SumF(this IList source) return a; } + #region Nullable types + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static uint? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case byte?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0U, (current, s1) => current + s1??0U); + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static int? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case sbyte?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0, (current, s1) => current + s1??0); + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static uint? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case ushort?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0U, (current, s1) => current + s1??0U); + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static int? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case short?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0, (current, s1) => current + s1??0); + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static uint? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case uint?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return (uint)source.Aggregate(0UL, (current, s1) => current + s1??0UL); + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static int? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case int?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static ulong? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case ulong?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Aggregate(0UL, (current, s1) => (current + s1??0UL)); + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static long? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case long?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float? SumF(this List source) + { + return (float?) NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static float? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case float?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this List source, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + int sourceCount = source.Count; + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + for (int index = 0; index < sourceCount; index++) + { + a = p.Add(a, selector(source[index]).ToDouble(CultureInfo.InvariantCulture)); + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static double? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case double?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal? SumF(this List source) + { + return NumericPolicies.Instance.SumFNullable(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + public static decimal? SumF(this IList source) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case decimal?[] sa: + return SumF(sa); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return sl.SumF(); + default: + return source.Sum(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 SumFNullable(this P p, List source) + where P : INullableNumericPolicy + where T : struct, IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + T2 a = p.Zero(); + checked + { + for (int index = 0; index < sourceCount; index++) + { + a = p.Add(a, source[index]); + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T SumFNullable(this P p, List source) + where P : INullableNumericPolicy + where T : struct, IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + T a = p.Zero(); + checked + { + for (int index = 0; index < sourceCount; index++) + { + a = p.Add(a, source[index]); + } + } + + return a; + } + + #endregion Nullable Types } } diff --git a/LinqFaster/SumSpan.cs b/LinqFaster/SumSpan.cs index febe1e3..49f85be 100644 --- a/LinqFaster/SumSpan.cs +++ b/LinqFaster/SumSpan.cs @@ -176,7 +176,6 @@ public static decimal SumF(this Span source) /// The sum of the transformed elements. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T2 SumF(this Span source, Func selector) - where T : struct, IConvertible where T2 : struct, IConvertible // Make sure these are not nullable { if (source == null) @@ -194,7 +193,7 @@ public static decimal SumF(this Span source) { foreach (T b in source) { - a = GenericOperators.Add(a, selector(b)); + a = GenericOperators.Add(a, selector(b)); } } diff --git a/Tests/SumTests.cs b/Tests/SumTests.cs index 2cd4562..29369ba 100644 --- a/Tests/SumTests.cs +++ b/Tests/SumTests.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using JM.LinqFaster; @@ -14,10 +15,11 @@ internal class SumTests [Test] public void SumArray() { - var a = intArray.SumF(); + var a = ((IList)intArray).SumF(); + var b = intArray.Sum(); Assert.That(a, Is.EqualTo(b)); - var an = intNullArray.SumF(); + var an = ((IList)intNullArray).SumF(); var bn = intNullArray.Sum(); Assert.That(an, Is.EqualTo(bn)); diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 7560a00..7fb4158 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -1866,14 +1866,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -1881,14 +1873,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -1896,14 +1880,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -1911,14 +1887,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -1926,14 +1894,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -1941,14 +1901,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -1956,14 +1908,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -1971,14 +1915,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -1986,14 +1922,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -2001,14 +1929,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -2016,14 +1936,6 @@ The sequence to add. The sum of the sequence. - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Adds a sequence of values. @@ -2197,6 +2109,171 @@ A transformation function. The sum of the transformed elements. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + Adds a sequence of values. From d6a2542bfa8685596e2280b027c01fef1271248b Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Wed, 31 Jul 2019 15:19:38 +0100 Subject: [PATCH 07/30] - Use "IList fast redirect" to implement all average Base and Nullable types --- Benchmarks/Benchmarks.cs | 100 ++-- LinqFaster/Average.cs | 946 ------------------------------------- LinqFaster/AverageIList.cs | 377 +++++++++++++++ LinqFaster/AverageSpan.cs | 321 +++++++++++++ LinqFaster/SumArrays.cs | 1 - LinqFaster/SumList.cs | 40 +- docs/linqfaster.xml | 190 ++++---- 7 files changed, 898 insertions(+), 1077 deletions(-) delete mode 100644 LinqFaster/Average.cs create mode 100644 LinqFaster/AverageIList.cs create mode 100644 LinqFaster/AverageSpan.cs diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 6e4b0c9..15eeaff 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -121,47 +121,47 @@ public void Setup() //} - [Benchmark] - public int IntArraySumLinq() - { - return intArray.Sum(); - } + //[Benchmark] + //public int IntArraySumLinq() + //{ + // return intArray.Sum(); + //} - [Benchmark] - public int IntArraySumFast() - { - return intArray.SumF(); - } + //[Benchmark] + //public int IntArraySumFast() + //{ + // return intArray.SumF(); + //} - [Benchmark] - public int IntIArraySumFast() - { - return ((IList)intArray).SumF(); - } + //[Benchmark] + //public int IntIArraySumFast() + //{ + // return ((IList)intArray).SumF(); + //} - [Benchmark] - public int IntListSumLinq() - { - return intList.Sum(); - } + //[Benchmark] + //public int IntListSumLinq() + //{ + // return intList.Sum(); + //} - [Benchmark] - public int IntListSumFast() - { - return intList.SumF(); - } + //[Benchmark] + //public int IntListSumFast() + //{ + // return intList.SumF(); + //} - [Benchmark] - public int IntIListSumLinq() - { - return ((IList)intList).Sum(); - } + //[Benchmark] + //public int IntIListSumLinq() + //{ + // return ((IList)intList).Sum(); + //} - [Benchmark] - public int IntIListSumFast() - { - return ((IList)intList).SumF(); - } + //[Benchmark] + //public int IntIListSumFast() + //{ + // return ((IList)intList).SumF(); + //} //[Benchmark] @@ -309,23 +309,23 @@ public int IntIListSumFast() // return doubleNullArray.SumF(x => x ?? 0); //} - //[Benchmark] - //public double AverageLinq() - //{ - // return intArray.Average(); - //} + [Benchmark] + public double IntArrayAverageLinq() + { + return intArray.Average(); + } - //[Benchmark] - //public double AverageFast() - //{ - // return intArray.AverageF(); - //} + [Benchmark] + public double IntArrayAverageFast() + { + return intArray.AverageF(); + } - //[Benchmark] - //public double AverageFastSIMD() - //{ - // return intArray.AverageS(); - //} + [Benchmark] + public double IntArrayAverageFastSIMD() + { + return intArray.AverageS(); + } //[Benchmark] //public int SumWithSelectLinq() diff --git a/LinqFaster/Average.cs b/LinqFaster/Average.cs deleted file mode 100644 index 793627e..0000000 --- a/LinqFaster/Average.cs +++ /dev/null @@ -1,946 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace JM.LinqFaster -{ - public static partial class LinqFaster - { - // -------------------------- ARRAYS -------------------------------------------- - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static double AverageF(this int[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - } - return (double)sum / source.Length; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static double AverageF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - } - return (double)sum / source.Length; - } - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static double AverageF(this long[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - } - return (double)sum / source.Length; - } - - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static double AverageF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - } - return (double)sum / source.Length; - } - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static float AverageF(this float[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - - return (float)(sum / source.Length); - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static float AverageF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - - return (float)(sum / source.Length); - } - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static double AverageF(this double[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - - return sum / source.Length; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static double AverageF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - - return sum / source.Length; - } - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static decimal AverageF(this decimal[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - decimal sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - - return sum / source.Length; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static decimal AverageF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - - decimal sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - - return sum / source.Length; - } - - // -------------------------- this SpanS -------------------------------------------- - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static double AverageF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - } - return (double)sum / source.Length; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static double AverageF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - } - return (double)sum / source.Length; - } - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static double AverageF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - } - return (double)sum / source.Length; - } - - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static double AverageF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - } - return (double)sum / source.Length; - } - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static float AverageF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - - return (float)(sum / source.Length); - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static float AverageF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - - return (float)(sum / source.Length); - } - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static double AverageF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - - return sum / source.Length; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static double AverageF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - - return sum / source.Length; - } - - /// - /// Computes the average of an array - /// - /// The array to calculate the average of. - /// The average of the array. - public static decimal AverageF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - decimal sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - - return sum / source.Length; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static decimal AverageF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - - decimal sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - - return sum / source.Length; - } - - // -------------------------- Lists -------------------------------------------- - - /// - /// Computes the average of a list. - /// - /// The list to calculate the average of. - /// The average of the list. - public static double AverageF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - } - return (double)sum / source.Count; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static double AverageF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - } - return (double)sum / source.Count; - } - - /// - /// Computes the average of a list. - /// - /// The list to calculate the average of. - /// The average of the list. - public static double AverageF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - } - return (double)sum / source.Count; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static double AverageF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - } - return (double)sum / source.Count; - } - - /// - /// Computes the average of a list. - /// - /// The list to calculate the average of. - /// The average of the list. - public static float AverageF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - double sum = 0; - - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - - return (float)(sum / source.Count); - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static float AverageF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - - return (float)(sum / source.Count); - } - - /// - /// Computes the average of a list. - /// - /// The list to calculate the average of. - /// The average of the list. - public static double AverageF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - double sum = 0; - - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - - return sum / source.Count; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static double AverageF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - - return sum / source.Count; - } - - /// - /// Computes the average of a list. - /// - /// The list to calculate the average of. - /// The average of the list. - public static decimal AverageF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - decimal sum = 0; - - for (int i = 0; i < source.Count; i++) - { - sum += source[i]; - } - - return sum / source.Count; - } - - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. - /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. - /// The average of the array. - public static decimal AverageF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - - decimal sum = 0; - - for (int i = 0; i < source.Count; i++) - { - sum += selector(source[i]); - } - - return sum / source.Count; - } - } -} diff --git a/LinqFaster/AverageIList.cs b/LinqFaster/AverageIList.cs new file mode 100644 index 0000000..1173b92 --- /dev/null +++ b/LinqFaster/AverageIList.cs @@ -0,0 +1,377 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +// ReSharper disable UnusedMember.Global +// ReSharper disable PossibleInvalidOperationException + +namespace JM.LinqFaster +{ + public static partial class LinqFaster + { + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + /// + /// Special case for floats to be equivalent to IEnumerable ! + /// + public static float AverageF(this IList source, Func selector) + { + if (source.Count == 0) + { + return 0; + } + + return source.SumF(selector) / source.Count; + } + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + public static double AverageF(this IList source, Func selector) + where T2 : IConvertible + { + if (source.Count == 0) + { + return 0; + } + + return source.SumF(selector).ToDouble(CultureInfo.InvariantCulture) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return (double)SumF(source) / source.Count; + } + + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static float AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return (float)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return source.SumF() / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static decimal AverageF(this IList source) + { + if (source.Count == 0) + { + return 0; + } + return source.SumF() / source.Count; + } + + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + public static decimal AverageF(this IList source, Func selector) + { + if (source.Count == 0) + { + return 0; + } + + return SumF(source, selector) / source.Count; + } + + #region Nullable types + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return (double)SumF(source) / source.Count; + } + + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return (double)SumF(source) / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double? AverageF(this IList source) + { + if (source.Count == 0) + { + return new double?(); + } + return source.SumF() / source.Count; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static decimal? AverageF(this IList source) + { + if (source.Count == 0) + { + return new decimal?(); + } + return source.SumF() / source.Count; + } + #endregion Nullable Types + } +} diff --git a/LinqFaster/AverageSpan.cs b/LinqFaster/AverageSpan.cs new file mode 100644 index 0000000..38fe77b --- /dev/null +++ b/LinqFaster/AverageSpan.cs @@ -0,0 +1,321 @@ +using System; + +namespace JM.LinqFaster +{ + public static partial class LinqFaster + { + // -------------------------- this SpanS -------------------------------------------- + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + long sum = 0; + checked + { + for (int i = 0; i < source.Length; i++) + { + sum += source[i]; + } + } + return (double)sum / source.Length; + } + + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + public static double AverageF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + long sum = 0; + checked + { + for (int i = 0; i < source.Length; i++) + { + sum += selector(source[i]); + } + } + return (double)sum / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + long sum = 0; + checked + { + for (int i = 0; i < source.Length; i++) + { + sum += source[i]; + } + } + return (double)sum / source.Length; + } + + + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + public static double AverageF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + long sum = 0; + checked + { + for (int i = 0; i < source.Length; i++) + { + sum += selector(source[i]); + } + } + return (double)sum / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static float AverageF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + double sum = 0; + + for (int i = 0; i < source.Length; i++) + { + sum += source[i]; + } + + return (float)(sum / source.Length); + } + + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + public static float AverageF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + double sum = 0; + + for (int i = 0; i < source.Length; i++) + { + sum += selector(source[i]); + } + + return (float)(sum / source.Length); + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static double AverageF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + double sum = 0; + + for (int i = 0; i < source.Length; i++) + { + sum += source[i]; + } + + return sum / source.Length; + } + + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + public static double AverageF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + double sum = 0; + + for (int i = 0; i < source.Length; i++) + { + sum += selector(source[i]); + } + + return sum / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + public static decimal AverageF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + decimal sum = 0; + + for (int i = 0; i < source.Length; i++) + { + sum += source[i]; + } + + return sum / source.Length; + } + + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + public static decimal AverageF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull("source"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + + decimal sum = 0; + + for (int i = 0; i < source.Length; i++) + { + sum += selector(source[i]); + } + + return sum / source.Length; + } + + } +} diff --git a/LinqFaster/SumArrays.cs b/LinqFaster/SumArrays.cs index b0529f6..e09b27b 100644 --- a/LinqFaster/SumArrays.cs +++ b/LinqFaster/SumArrays.cs @@ -178,7 +178,6 @@ public static decimal SumF(this decimal[] source) /// The sum of the transformed elements. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T2 SumF(this T[] source, Func selector) - where T2 : struct, IConvertible // Make sure these are not nullable { if (source == null) { diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index 2a56280..251f7b6 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -400,7 +400,6 @@ public static decimal SumF(this IList source) /// The sum of the transformed elements. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T2 SumF(this List source, Func selector) - where T2 : struct, IConvertible // Make sure these are not nullable { if (source == null) { @@ -425,6 +424,45 @@ public static decimal SumF(this IList source) return a; } + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this IList source, Func selector) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case T[] sa: + return sa.SumF(selector); + case List sl: + return sl.SumF(selector); + default: + { + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + int sourceCount = source.Count; + T2 a = default(T2); + checked + { + for (int index = 0; index < sourceCount; index++) + { + a = GenericOperators.Add(a, selector(source[index])); + } + } + + return a; + } + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static T2 SumF(this P p, List source) diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 7fb4158..3e75cc2 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -173,14 +173,19 @@ true if every element of the source array passes the test in the specified predicate, or if the list is empty; otherwise, false - + - Computes the average of an array + Computes the average of values obtained by invoking a transform function on + each element of the input array. - The array to calculate the average of. + The array to calculate the transformed average of. + A transform function to apply to each element. The average of the array. + + Special case for floats to be equivalent to IEnumerable ! + - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -189,94 +194,84 @@ A transform function to apply to each element. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -285,62 +280,91 @@ A transform function to apply to each element. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. The average of the array. - + - Computes the average of a list. + Computes the average of an array - The list to calculate the average of. - The average of the list. + The array to calculate the average of. + The average of the array. - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -349,14 +373,14 @@ A transform function to apply to each element. The average of the array. - + - Computes the average of a list. + Computes the average of an array - The list to calculate the average of. - The average of the list. + The array to calculate the average of. + The average of the array. - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -365,14 +389,14 @@ A transform function to apply to each element. The average of the array. - + - Computes the average of a list. + Computes the average of an array - The list to calculate the average of. - The average of the list. + The array to calculate the average of. + The average of the array. - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -381,14 +405,14 @@ A transform function to apply to each element. The average of the array. - + - Computes the average of a list. + Computes the average of an array - The list to calculate the average of. - The average of the list. + The array to calculate the average of. + The average of the array. - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -397,14 +421,14 @@ A transform function to apply to each element. The average of the array. - + - Computes the average of a list. + Computes the average of an array - The list to calculate the average of. - The average of the list. + The array to calculate the average of. + The average of the array. - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -2109,6 +2133,14 @@ A transformation function. The sum of the transformed elements. + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + Adds a sequence of values. From 3ecde38eed5c855abca754e423e3e91990f70184 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Wed, 31 Jul 2019 15:49:07 +0100 Subject: [PATCH 08/30] - Complete base types applicable to Span - Add inlining hint to AverageIList --- Benchmarks/Benchmarks.cs | 92 +++++++----- LinqFaster/AverageIList.cs | 27 ++++ LinqFaster/AverageSpan.cs | 294 ++++++++++++------------------------- LinqFaster/SumSpan.cs | 1 - docs/linqfaster.xml | 74 ++++++---- 5 files changed, 225 insertions(+), 263 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 15eeaff..51ac695 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -309,57 +309,81 @@ public void Setup() // return doubleNullArray.SumF(x => x ?? 0); //} - [Benchmark] - public double IntArrayAverageLinq() - { - return intArray.Average(); - } + //[Benchmark] + //public double IntArrayAverageLinq() + //{ + // return intArray.Average(); + //} - [Benchmark] - public double IntArrayAverageFast() - { - return intArray.AverageF(); - } + //[Benchmark] + //public double IntArrayAverageFast() + //{ + // return intArray.AverageF(); + //} - [Benchmark] - public double IntArrayAverageFastSIMD() - { - return intArray.AverageS(); - } + //[Benchmark] + //public double IntArrayAverageFastSIMD() + //{ + // return intArray.AverageS(); + //} //[Benchmark] - //public int SumWithSelectLinq() + //public int IntArraySumWithSelectLinq() //{ // return intArray.Sum(x => x / 2); //} //[Benchmark] - //public int SumWithSelectFast() + //public int IntArraySumWithSelectFast() //{ // return intArray.SumF(x => x/2); //} + [Benchmark] + public double IntArrayAggregateLinq() + { + return intArray.Aggregate(0.0, (acc, x) => acc += x * x); + } + + [Benchmark] + public double IntArrayAggregateFast() + { + return intArray.AggregateF(0.0, (acc, x) => acc += x * x); + } + + [Benchmark] + public double IntArrayAggregateLinqSelector() + { + return intArray.Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); + } + + [Benchmark] + public double IntArrayAggregateFastSelector() + { + return intArray.AggregateF(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); + } + //[Benchmark] - //public double WhereAggregateLinq() + //public double IntArrayWhereAggregateLinq() //{ // return intArray.Where(x => x % 2 == 0).Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); //} //[Benchmark] - //public double WhereAggregateFast() + //public double IntArrayWhereAggregateFast() //{ - // return intArray.WhereAggregateF(x => x % 2 == 0,0.0,(acc,x)=> acc += x*x,acc => acc/array.Length); + // return intArray.WhereAggregateF(x => x % 2 == 0,0.0,(acc,x)=> acc += x*x,acc => acc/intArray.Length); //} //[Benchmark] - //public int[] SelectFast() + //public int[] IntArraySelectFast() //{ // return intArray.SelectF(x => x * x); //} //[Benchmark] - //public int[] SelectFastSIMD() + //public int[] IntArraySelectFastSIMD() //{ // return intArray.SelectS(x => x * x, x=>x*x); //} @@ -367,75 +391,75 @@ public double IntArrayAverageFastSIMD() //[Benchmark] - //public int[] RepeatLinq() + //public int[] IntArrayRepeatLinq() //{ // return Enumerable.Repeat(5, TEST_SIZE).ToArray(); //} //[Benchmark] - //public int[] RepeatFast() + //public int[] IntArrayRepeatFast() //{ // return LinqFaster.RepeatArrayF(5, TEST_SIZE); //} //[Benchmark] - //public int[] RepeatFastSIMD() + //public int[] IntArrayRepeatFastSIMD() //{ // return LinqFasterSIMD.RepeatS(5, TEST_SIZE); //} //[Benchmark] - //public int[] RepeatFastSIMDB() + //public int[] IntArrayRepeatFastSIMDB() //{ // return LinqFasterSIMD.RepeatSB(5, TEST_SIZE); //} //[Benchmark] - //public int MinLinq() + //public int IntArrayMinLinq() //{ // return intArray.Min(); //} //[Benchmark] - //public int MinFast() + //public int IntArrayMinFast() //{ // return intArray.MinF(); //} //[Benchmark] - //public int MinFastSIMD() + //public int IntArrayMinFastSIMD() //{ // return intArray.MinS(); //} //[Benchmark] - //public bool SequenceEqual() + //public bool IntArraySequenceEqual() //{ // return intArray.SequenceEqual(array2); //} //[Benchmark] - //public bool SequenceEqualF() + //public bool IntArraySequenceEqualF() //{ // return intArray.SequenceEqualF(array2); //} //[Benchmark] - //public bool SequenceEqualP() + //public bool IntArraySequenceEqualP() //{ // return intArray.SequenceEqualP(array2); //} //[Benchmark] - //public bool SequenceEqualS() + //public bool IntArraySequenceEqualS() //{ // return intArray.SequenceEqualS(array2); //} //[Benchmark] - //public bool SequenceEqualSP() + //public bool IntArraySequenceEqualSP() //{ // return intArray.SequenceEqualSP(array2); //} diff --git a/LinqFaster/AverageIList.cs b/LinqFaster/AverageIList.cs index 1173b92..908876d 100644 --- a/LinqFaster/AverageIList.cs +++ b/LinqFaster/AverageIList.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Runtime.CompilerServices; + // ReSharper disable UnusedMember.Global // ReSharper disable PossibleInvalidOperationException @@ -18,6 +20,7 @@ public static partial class LinqFaster /// /// Special case for floats to be equivalent to IEnumerable ! /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float AverageF(this IList source, Func selector) { if (source.Count == 0) @@ -34,6 +37,7 @@ public static float AverageF(this IList source, Func selector) /// The array to calculate the transformed average of. /// A transform function to apply to each element. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source, Func selector) where T2 : IConvertible { @@ -50,6 +54,7 @@ public static float AverageF(this IList source, Func selector) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source) { if (source.Count == 0) @@ -64,6 +69,7 @@ public static double AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source) { if (source.Count == 0) @@ -78,6 +84,7 @@ public static double AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source) { if (source.Count == 0) @@ -92,6 +99,7 @@ public static double AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source) { if (source.Count == 0) @@ -106,6 +114,7 @@ public static double AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source) { if (source.Count == 0) @@ -120,6 +129,7 @@ public static double AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source) { if (source.Count == 0) @@ -134,6 +144,7 @@ public static double AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source) { if (source.Count == 0) @@ -148,6 +159,7 @@ public static double AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source) { if (source.Count == 0) @@ -163,6 +175,7 @@ public static double AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float AverageF(this IList source) { if (source.Count == 0) @@ -177,6 +190,7 @@ public static float AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AverageF(this IList source) { if (source.Count == 0) @@ -191,6 +205,7 @@ public static double AverageF(this IList source) /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal AverageF(this IList source) { if (source.Count == 0) @@ -207,6 +222,7 @@ public static decimal AverageF(this IList source) /// The array to calculate the transformed average of. /// A transform function to apply to each element. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal AverageF(this IList source, Func selector) { if (source.Count == 0) @@ -223,6 +239,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -237,6 +254,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -251,6 +269,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -265,6 +284,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -279,6 +299,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -293,6 +314,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -307,6 +329,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -321,6 +344,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -336,6 +360,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -350,6 +375,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double? AverageF(this IList source) { if (source.Count == 0) @@ -364,6 +390,7 @@ public static decimal AverageF(this IList source, Func selecto /// /// The array to calculate the average of. /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal? AverageF(this IList source) { if (source.Count == 0) diff --git a/LinqFaster/AverageSpan.cs b/LinqFaster/AverageSpan.cs index 38fe77b..203bb23 100644 --- a/LinqFaster/AverageSpan.cs +++ b/LinqFaster/AverageSpan.cs @@ -1,39 +1,31 @@ using System; +using System.Globalization; +using System.Runtime.CompilerServices; namespace JM.LinqFaster { public static partial class LinqFaster { - // -------------------------- this SpanS -------------------------------------------- - /// - /// Computes the average of an array + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. /// - /// The array to calculate the average of. + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. /// The average of the array. - public static double AverageF(this Span source) + /// + /// Special case for floats to be equivalent to IEnumerable ! + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float AverageF(this Span source, Func selector) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) { - throw Error.NoElements(); + return 0; } - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - } - return (double)sum / source.Length; + return SumF(source, selector) / source.Length; } - /// /// Computes the average of values obtained by invoking a transform function on /// each element of the input array. @@ -41,32 +33,16 @@ public static double AverageF(this Span source) /// The array to calculate the transformed average of. /// A transform function to apply to each element. /// The average of the array. - public static double AverageF(this Span source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source, Func selector) + where T2 : IConvertible { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) { - throw Error.NoElements(); + return 0; } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - } - return (double)sum / source.Length; + return SumF(source, selector).ToDouble(CultureInfo.InvariantCulture) / source.Length; } /// @@ -74,63 +50,29 @@ public static double AverageF(this Span source, Func selector) /// /// The array to calculate the average of. /// The average of the array. - public static double AverageF(this Span source) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) { - throw Error.NoElements(); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } + return 0; } - return (double)sum / source.Length; + return (double)SumF(source) / source.Length; } - /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. + /// Computes the average of an array /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. + /// The array to calculate the average of. /// The average of the array. - public static double AverageF(this Span source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) { - throw Error.NoElements(); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } + return 0; } - return (double)sum / source.Length; + return (double)SumF(source) / source.Length; } /// @@ -138,60 +80,29 @@ public static double AverageF(this Span source, Func selector) /// /// The array to calculate the average of. /// The average of the array. - public static float AverageF(this Span source) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) { - throw Error.NoElements(); + return 0; } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - - return (float)(sum / source.Length); + return (double)SumF(source) / source.Length; } /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. + /// Computes the average of an array /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. + /// The array to calculate the average of. /// The average of the array. - public static float AverageF(this Span source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) { - throw Error.NoElements(); + return 0; } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - - return (float)(sum / source.Length); + return (double)SumF(source) / source.Length; } /// @@ -199,60 +110,29 @@ public static float AverageF(this Span source, Func selector) /// /// The array to calculate the average of. /// The average of the array. - public static double AverageF(this Span source) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) { - throw Error.NoElements(); + return 0; } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += source[i]; - } - - return sum / source.Length; + return (double)SumF(source) / source.Length; } /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. + /// Computes the average of an array /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. + /// The array to calculate the average of. /// The average of the array. - public static double AverageF(this Span source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) { - throw Error.NoElements(); + return 0; } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double sum = 0; - - for (int i = 0; i < source.Length; i++) - { - sum += selector(source[i]); - } - - return sum / source.Length; + return (double)SumF(source) / source.Length; } /// @@ -260,61 +140,75 @@ public static double AverageF(this Span source, Func selector) /// /// The array to calculate the average of. /// The average of the array. - public static decimal AverageF(this Span source) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source) { - if (source == null) + if (source.Length == 0) { - throw Error.ArgumentNull("source"); + return 0; } + return (double)SumF(source) / source.Length; + } + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source) + { if (source.Length == 0) { - throw Error.NoElements(); + return 0; } + return (double)SumF(source) / source.Length; + } - decimal sum = 0; - for (int i = 0; i < source.Length; i++) + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float AverageF(this Span source) + { + if (source.Length == 0) { - sum += source[i]; + return 0; } - - return sum / source.Length; + return SumF(source) / source.Length; } /// - /// Computes the average of values obtained by invoking a transform function on - /// each element of the input array. + /// Computes the average of an array /// - /// The array to calculate the transformed average of. - /// A transform function to apply to each element. + /// The array to calculate the average of. /// The average of the array. - public static decimal AverageF(this Span source, Func selector) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this Span source) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) { - throw Error.NoElements(); + return 0; } + return source.SumF() / source.Length; + } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - - decimal sum = 0; - - for (int i = 0; i < source.Length; i++) + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal AverageF(this Span source) + { + if (source.Length == 0) { - sum += selector(source[i]); + return 0; } - - return sum / source.Length; + return SumF(source) / source.Length; } } diff --git a/LinqFaster/SumSpan.cs b/LinqFaster/SumSpan.cs index 49f85be..42a51a5 100644 --- a/LinqFaster/SumSpan.cs +++ b/LinqFaster/SumSpan.cs @@ -176,7 +176,6 @@ public static decimal SumF(this Span source) /// The sum of the transformed elements. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T2 SumF(this Span source, Func selector) - where T2 : struct, IConvertible // Make sure these are not nullable { if (source == null) { diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 3e75cc2..0ec1272 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -357,14 +357,19 @@ The array to calculate the average of. The average of the array. - + - Computes the average of an array + Computes the average of values obtained by invoking a transform function on + each element of the input array. - The array to calculate the average of. + The array to calculate the transformed average of. + A transform function to apply to each element. The average of the array. + + Special case for floats to be equivalent to IEnumerable ! + - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -373,68 +378,81 @@ A transform function to apply to each element. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + - Computes the average of values obtained by invoking a transform function on - each element of the input array. + Computes the average of an array - The array to calculate the transformed average of. - A transform function to apply to each element. + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. The average of the array. From e93f3734115a16f402f9bad303596f82186b78e1 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Thu, 1 Aug 2019 10:08:04 +0100 Subject: [PATCH 09/30] Fix #21: [Bug] `Span SumF` is slower than a for loop over a span - Fix code to make it appear "As fast" Via the use of the "Coming out faster" acum = accum + nextVal method - Add ReadOnlySpan to `SumF` api's --- Benchmarks/Benchmarks.cs | 71 +++++++---- LinqFaster/SumSpan.cs | 253 +++++++++++++++++++++++++++++++++++++-- docs/linqfaster.xml | 96 +++++++++++++++ 3 files changed, 391 insertions(+), 29 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 51ac695..394da97 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -133,6 +133,25 @@ public void Setup() // return intArray.SumF(); //} + [Benchmark] + public int IntSpanSumFor() + { + int val = 0; + Span span = intArray.AsSpan(); + for (int index = 0; index < span.Length; index++) + { + val += span[index]; + } + + return val; + } + + [Benchmark] + public int IntSpanSumFast() + { + return intArray.AsSpan().SumF(); + } + //[Benchmark] //public int IntIArraySumFast() //{ @@ -339,29 +358,41 @@ public void Setup() // return intArray.SumF(x => x/2); //} - [Benchmark] - public double IntArrayAggregateLinq() - { - return intArray.Aggregate(0.0, (acc, x) => acc += x * x); - } + //[Benchmark] + //public double IntArrayAggregateLinq() + //{ + // return intArray.Aggregate(0.0, (acc, x) => acc += x * x); + //} - [Benchmark] - public double IntArrayAggregateFast() - { - return intArray.AggregateF(0.0, (acc, x) => acc += x * x); - } + //[Benchmark] + //public double IntArrayAggregateFast() + //{ + // return intArray.AggregateF(0.0, (acc, x) => acc += x * x); + //} - [Benchmark] - public double IntArrayAggregateLinqSelector() - { - return intArray.Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); - } + //[Benchmark] + //public double IntArrayAggregateLinqSelector() + //{ + // return intArray.Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); + //} - [Benchmark] - public double IntArrayAggregateFastSelector() - { - return intArray.AggregateF(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); - } + //[Benchmark] + //public double IntArrayAggregateFastSelector() + //{ + // return intArray.AggregateF(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); + //} + + //[Benchmark] + //public double IntListAggregateLinq() + //{ + // return intList.Aggregate(0.0, (acc, x) => acc += x * x); + //} + + //[Benchmark] + //public double IntListAggregateFast() + //{ + // return intList.AggregateF(0.0, (acc, x) => acc += x * x); + //} //[Benchmark] diff --git a/LinqFaster/SumSpan.cs b/LinqFaster/SumSpan.cs index 42a51a5..11b0bef 100644 --- a/LinqFaster/SumSpan.cs +++ b/LinqFaster/SumSpan.cs @@ -3,14 +3,14 @@ using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; - +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable MemberCanBePrivate.Global namespace JM.LinqFaster { public static partial class LinqFaster { - // -------------------------- SPANS -------------------------------------------- - + #region Normal Span /// /// Adds a sequence of values. /// @@ -190,9 +190,9 @@ public static decimal SumF(this Span source) T2 a = default(T2); checked { - foreach (T b in source) + for (int index = 0; index < source.Length; index++) { - a = GenericOperators.Add(a, selector(b)); + a = GenericOperators.Add(a, selector(source[index])); } } @@ -213,9 +213,9 @@ public static decimal SumF(this Span source) T2 a = p.Zero(); checked { - foreach (T1 b in source) + for (int index = 0; index < source.Length; index++) { - a = p.Add(a, b); + a = p.Add(a, source[index]); } } @@ -234,13 +234,248 @@ public static decimal SumF(this Span source) T a = p.Zero(); checked { - foreach (T b in source) + for (int index = 0; index < source.Length; index++) + { + a = p.Add(a, source[index]); + } + } + + return a; + } + #endregion Normal Span + + #region ReadOnlySpan + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float SumF(this ReadOnlySpan source) + { + return (float)NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this ReadOnlySpan source, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + foreach (float b in source) + { + a = p.Add(a, selector(b).ToDouble(CultureInfo.InvariantCulture)); + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal SumF(this ReadOnlySpan source) + { + return NumericPolicies.Instance.SumF(source); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 SumF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + T2 a = default(T2); + checked + { + for (int index = 0; index < source.Length; index++) + { + a = GenericOperators.Add(a, selector(source[index])); + } + } + + return a; + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 SumF(this P p, ReadOnlySpan source) + where P : INumericPolicy + where T1 : IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + T2 a = p.Zero(); + checked + { + for (int index = 0; index < source.Length; index++) + { + a = p.Add(a, source[index]); + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T SumF(this P p, ReadOnlySpan source) + where P : INumericPolicy + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + T a = p.Zero(); + checked + { + for (int index = 0; index < source.Length; index++) { - a = p.Add(a, b); + a = p.Add(a, source[index]); } } return a; } + #endregion ReadOnlySpan } } diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 0ec1272..e408bf9 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -2420,6 +2420,102 @@ A transformation function. The sum of the transformed elements. + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + Returns a specified number of contiguous elements from the start of a sequence. From fed5794a432382ff9a7ed32eb339944c9c3728fa Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Thu, 1 Aug 2019 12:27:58 +0100 Subject: [PATCH 10/30] [Enhancement] Can these API's also work on IList #15 - Done for Aggregate - Add All Span types - Add ReadOnlySpan - Reduce code in SumList --- Benchmarks/Benchmarks.cs | 156 +++++++++----- LinqFaster/Aggregate.cs | 157 ++++++++++---- LinqFaster/AverageSpan.cs | 219 ++++++++++++++++++- LinqFaster/SumList.cs | 440 +++++++++++++++----------------------- LinqFaster/SumSpan.cs | 6 + docs/linqfaster.xml | 279 ++++++++++-------------- 6 files changed, 727 insertions(+), 530 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 394da97..7e17a74 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -1,40 +1,37 @@ using System; -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Running; -using JM.LinqFaster; -using JM.LinqFaster.Parallel; -using JM.LinqFaster.SIMD.Parallel; -using JM.LinqFaster.SIMD; - -using System.Linq; using System.Collections.Generic; +using System.Linq; + +using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Running; + +using JM.LinqFaster; namespace Tests { [MemoryDiagnoser] public class Benchmarks { - - const int LARGE_TEST_SIZE = 1000000; - const int SMALL_TEST_SIZE = 100; - - public List list; - public byte[] byteArray; - public short[] shortArray; - public int[] intArray; - public List intList; + private const int LARGE_TEST_SIZE = 1000000; + private const int SMALL_TEST_SIZE = 100; + + private List list; + private byte[] byteArray; + private short[] shortArray; + private int[] intArray; + private List intList; private int?[] intNullArray; - public int[] array2; - public float[] floatArray; - public List floatList; + private int[] array2; + private float[] floatArray; + private List floatList; private float?[] floatNullArray; - public double[] doubleArray; - public List doubleList; + private double[] doubleArray; + private List doubleList; private double?[] doubleNullArray; - public string[] strarray; - + private string[] strarray; + [Params(1000000)] public int TEST_SIZE { get; set; } @@ -61,7 +58,7 @@ public void Setup() doubleNullArray = new double?[TEST_SIZE]; list = new List(TEST_SIZE); strarray = new string[TEST_SIZE]; - + for (int i = 0; i < TEST_SIZE; i++) { intArray[i] = i % 2; @@ -133,24 +130,24 @@ public void Setup() // return intArray.SumF(); //} - [Benchmark] - public int IntSpanSumFor() - { - int val = 0; - Span span = intArray.AsSpan(); - for (int index = 0; index < span.Length; index++) - { - val += span[index]; - } + //[Benchmark] + //public int IntSpanSumFor() + //{ + // int val = 0; + // Span span = intArray.AsSpan(); + // for (int index = 0; index < span.Length; index++) + // { + // val += span[index]; + // } - return val; - } + // return val; + //} - [Benchmark] - public int IntSpanSumFast() - { - return intArray.AsSpan().SumF(); - } + //[Benchmark] + //public int IntSpanSumFast() + //{ + // return intArray.AsSpan().SumF(); + //} //[Benchmark] //public int IntIArraySumFast() @@ -358,41 +355,86 @@ public int IntSpanSumFast() // return intArray.SumF(x => x/2); //} + private static readonly Func mulXInts = (acc, x) => acc += x * x; + + [Benchmark] + public double IntArrayAggregateLinq() + { + return intArray.Aggregate(0.0D, mulXInts); + } + + [Benchmark] + public double IntArrayAggregateFast() + { + return intArray.AggregateF(0.0D, mulXInts); + } + + [Benchmark] + public double IntReadOnlyArrayAggregateLinq() + { + return Array.AsReadOnly(intArray).Aggregate(0.0D, mulXInts); + } + + [Benchmark] + public double IntReadOnlyArrayAggregateFast() + { + return Array.AsReadOnly(intArray).AggregateF(0.0D, mulXInts); + } + //[Benchmark] - //public double IntArrayAggregateLinq() + //public double IntSpanAggregateForEach() //{ - // return intArray.Aggregate(0.0, (acc, x) => acc += x * x); + // //return intArray.AsSpan().Aggregate(0.0, mulXInts); + // double result = 0.0D; + // foreach (var v in intArray.AsSpan()) + // { + // result = mulXInts(result, v); + // } + // return result; + //} //[Benchmark] - //public double IntArrayAggregateFast() + //public double IntSpanAggregateFast() //{ - // return intArray.AggregateF(0.0, (acc, x) => acc += x * x); + // return intArray.AsSpan().AggregateF(0.0, mulXInts); //} //[Benchmark] //public double IntArrayAggregateLinqSelector() //{ - // return intArray.Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); + // return intArray.Aggregate(0.0, mulXInts, acc => acc / intArray.Length); //} //[Benchmark] //public double IntArrayAggregateFastSelector() //{ - // return intArray.AggregateF(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); + // return intArray.AggregateF(0.0, mulXInts, acc => acc / intArray.Length); //} - //[Benchmark] - //public double IntListAggregateLinq() - //{ - // return intList.Aggregate(0.0, (acc, x) => acc += x * x); - //} + [Benchmark] + public double IntListAggregateLinq() + { + return intList.Aggregate(0.0, mulXInts); + } - //[Benchmark] - //public double IntListAggregateFast() - //{ - // return intList.AggregateF(0.0, (acc, x) => acc += x * x); - //} + [Benchmark] + public double IntListAggregateFast() + { + return intList.AggregateF(0.0, mulXInts); + } + + [Benchmark] + public double IntReadOnlyListAggregateLinq() + { + return intList.AsReadOnly().Aggregate(0.0, mulXInts); + } + + [Benchmark] + public double IntReadOnlyListAggregateFast() + { + return intList.AsReadOnly().AggregateF(0.0, mulXInts); + } //[Benchmark] diff --git a/LinqFaster/Aggregate.cs b/LinqFaster/Aggregate.cs index 8879f34..cb0f65c 100644 --- a/LinqFaster/Aggregate.cs +++ b/LinqFaster/Aggregate.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global namespace JM.LinqFaster { @@ -18,7 +20,8 @@ public static partial class LinqFaster /// An array to aggregate over. /// An accumulator function to be invoked on each element /// The final accumulator value - public static TSource AggregateF(this TSource[] source, Func func) + public static TSource AggregateF(this IList source, + Func func) { if (source == null) { @@ -30,16 +33,35 @@ public static TSource AggregateF(this TSource[] source, Func sl: + for (int i = 1; i < sl.Count; i++) + { + result = func(result, sl[i]); + } + break; + default: + int sourceCount = source.Count; + for (int i = 1; i < sourceCount; i++) + { + result = func(result, source[i]); + } + break; } + return result; } @@ -51,7 +73,8 @@ public static TSource AggregateF(this TSource[] source, FuncThe initial accumulator value. /// An accumulator function to be invoked on each element /// The final accumulator value - public static TAccumulate AggregateF(this TSource[] source, TAccumulate seed, Func func) + public static TAccumulate AggregateF(this IList source, TAccumulate seed, + Func func) { if (source == null) { @@ -64,10 +87,29 @@ public static TSource AggregateF(this TSource[] source, Func sl: + for (int i = 1; i < sl.Count; i++) + { + result = func(result, sl[i]); + } + break; + default: + int sourceCount = source.Count; + for (int i = 1; i < sourceCount; i++) + { + result = func(result, source[i]); + } + break; } + return result; } @@ -81,7 +123,9 @@ public static TSource AggregateF(this TSource[] source, FuncAn accumulator function to be invoked on each element /// A function to transform the final accumulator value into the result value. /// The transformed final accumulator value - public static TResult AggregateF(this TSource[] source, TAccumulate seed, Func func, Func resultSelector) + public static TResult AggregateF(this IList source, TAccumulate seed, + Func func, + Func resultSelector) { if (source == null) { @@ -99,22 +143,42 @@ public static TSource AggregateF(this TSource[] source, Func sl: + for (int i = 1; i < sl.Count; i++) + { + result = func(result, sl[i]); + } + break; + default: + int sourceCount = source.Count; + for (int i = 1; i < sourceCount; i++) + { + result = func(result, source[i]); + } + break; } + return resultSelector(result); } // ------------------------------ this Spans -------------------------- - + #region Normal Span /// /// Applies an accumulator function over an array. /// /// An array to aggregate over. /// An accumulator function to be invoked on each element /// The final accumulator value - public static TSource AggregateF(this Span source, Func func) + public static TSource AggregateF(this Span source, + Func func) { if (source == null) { @@ -147,7 +211,8 @@ public static TSource AggregateF(this Span source, FuncThe initial accumulator value. /// An accumulator function to be invoked on each element /// The final accumulator value - public static TAccumulate AggregateF(this Span source, TAccumulate seed, Func func) + public static TAccumulate AggregateF(this Span source, TAccumulate seed, + Func func) { if (source == null) { @@ -160,10 +225,11 @@ public static TSource AggregateF(this Span source, Func(this Span source, FuncAn accumulator function to be invoked on each element /// A function to transform the final accumulator value into the result value. /// The transformed final accumulator value - public static TResult AggregateF(this Span source, TAccumulate seed, Func func, Func resultSelector) + public static TResult AggregateF(this Span source, TAccumulate seed, + Func func, + Func resultSelector) { if (source == null) { @@ -195,23 +263,25 @@ public static TSource AggregateF(this Span source, Func - // ------------------------------ Lists -------------------------- - + // ------------------------------ this ReadOnlySpans -------------------------- + #region ReadOnlySpan /// - /// Applies an accumulator function over a List. - /// - /// - /// A List to aggregate over. + /// Applies an accumulator function over an array. + /// + /// An array to aggregate over. /// An accumulator function to be invoked on each element /// The final accumulator value - public static TSource AggregateF(this List source, Func func) + public static TSource AggregateF(this ReadOnlySpan source, + Func func) { if (source == null) { @@ -223,13 +293,13 @@ public static TSource AggregateF(this List source, Func(this List source, Func - /// Applies an accumulator function over a List. The specified seed + /// Applies an accumulator function over an array. The specified seed /// value is used as the initial accumulator value. /// - /// A List to aggregate over. + /// An array to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// The final accumulator value - public static TAccumulate AggregateF(this List source, TAccumulate seed, Func func) + public static TAccumulate AggregateF(this ReadOnlySpan source, TAccumulate seed, + Func func) { if (source == null) { @@ -257,24 +328,27 @@ public static TSource AggregateF(this List source, Func - /// Applies an accumulator function over a List. The specified seed + /// Applies an accumulator function over an array. The specified seed /// value is used as the initial accumulator value, and the specified /// function is used to select the result value. /// - /// A List to aggregate over. + /// An array to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// A function to transform the final accumulator value into the result value. /// The transformed final accumulator value - public static TResult AggregateF(this List source, TAccumulate seed, Func func, Func resultSelector) + public static TResult AggregateF(this ReadOnlySpan source, TAccumulate seed, + Func func, + Func resultSelector) { if (source == null) { @@ -292,12 +366,15 @@ public static TSource AggregateF(this List source, Func + } } \ No newline at end of file diff --git a/LinqFaster/AverageSpan.cs b/LinqFaster/AverageSpan.cs index 203bb23..845a4fa 100644 --- a/LinqFaster/AverageSpan.cs +++ b/LinqFaster/AverageSpan.cs @@ -6,6 +6,14 @@ namespace JM.LinqFaster { public static partial class LinqFaster { + /* + * Since ReadOnlySpan is actually a struct and it does not inherit from IEnumerable, + * we can’t use LINQ against it. + * This is a big minus when compared to C# collections. + */ + + #region Normal Span + /// /// Computes the average of values obtained by invoking a transform function on /// each element of the input array. @@ -23,9 +31,9 @@ public static float AverageF(this Span source, Func selector) { return 0; } - return SumF(source, selector) / source.Length; } + /// /// Computes the average of values obtained by invoking a transform function on /// each element of the input array. @@ -210,6 +218,215 @@ public static decimal AverageF(this Span source) } return SumF(source) / source.Length; } + #endregion Normal Span + + #region ReadOnlySpan + + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + /// + /// Special case for floats to be equivalent to IEnumerable ! + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float AverageF(this ReadOnlySpan source, Func selector) + { + if (source.Length == 0) + { + return 0; + } + return SumF(source, selector) / source.Length; + } + + /// + /// Computes the average of values obtained by invoking a transform function on + /// each element of the input array. + /// + /// The array to calculate the transformed average of. + /// A transform function to apply to each element. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source, Func selector) + where T2 : IConvertible + { + if (source.Length == 0) + { + return 0; + } + + return SumF(source, selector).ToDouble(CultureInfo.InvariantCulture) / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return (double)SumF(source) / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return (double)SumF(source) / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return (double)SumF(source) / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return (double)SumF(source) / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return (double)SumF(source) / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return (double)SumF(source) / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return (double)SumF(source) / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return (double)SumF(source) / source.Length; + } + + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return SumF(source) / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return source.SumF() / source.Length; + } + + /// + /// Computes the average of an array + /// + /// The array to calculate the average of. + /// The average of the array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal AverageF(this ReadOnlySpan source) + { + if (source.Length == 0) + { + return 0; + } + return SumF(source) / source.Length; + } + #endregion ReadOnlySpan } } diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index 251f7b6..cda7020 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -21,16 +21,6 @@ public static partial class LinqFaster /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static uint SumF(this IList source) { switch (source) @@ -40,9 +30,15 @@ public static uint SumF(this IList source) case byte[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return source.Aggregate(0U, (current, s1) => current + s1); + int sourceCount = source.Count; + uint sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -52,16 +48,6 @@ public static uint SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static int SumF(this IList source) { switch (source) @@ -71,9 +57,15 @@ public static int SumF(this IList source) case sbyte[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return source.Aggregate(0, (current, s1) => current + s1); + int sourceCount = source.Count; + int sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -83,16 +75,6 @@ public static int SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static uint SumF(this IList source) { switch (source) @@ -102,9 +84,15 @@ public static uint SumF(this IList source) case ushort[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return source.Aggregate(0U, (current, s1) => current + s1); + int sourceCount = source.Count; + uint sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -114,16 +102,6 @@ public static uint SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static int SumF(this IList source) { switch (source) @@ -133,9 +111,15 @@ public static int SumF(this IList source) case short[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return source.Aggregate(0, (current, s1) => current + s1); + int sourceCount = source.Count; + int sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -145,16 +129,6 @@ public static int SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static uint SumF(this IList source) { switch (source) @@ -164,9 +138,15 @@ public static uint SumF(this IList source) case uint[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return (uint) source.Aggregate(0UL, (current, s1) => (current + s1)); + int sourceCount = source.Count; + uint sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -176,16 +156,6 @@ public static uint SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static int SumF(this IList source) { switch (source) @@ -195,9 +165,15 @@ public static int SumF(this IList source) case int[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return source.Sum(); + int sourceCount = source.Count; + int sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -207,16 +183,6 @@ public static int SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static ulong SumF(this IList source) { switch (source) @@ -226,9 +192,15 @@ public static ulong SumF(this IList source) case ulong[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return source.Aggregate(0UL, (current, s1) => (current + s1)); + int sourceCount = source.Count; + ulong sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -238,16 +210,6 @@ public static ulong SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static long SumF(this IList source) { switch (source) @@ -257,9 +219,15 @@ public static long SumF(this IList source) case long[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return source.Sum(); + int sourceCount = source.Count; + long sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -269,16 +237,6 @@ public static long SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float SumF(this List source) - { - return (float)NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static float SumF(this IList source) { switch (source) @@ -288,9 +246,15 @@ public static float SumF(this IList source) case float[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return (float)NumericPolicies.Instance.SumF(sl); default: - return source.Sum(); + int sourceCount = source.Count; + double sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return (float) sum; } } @@ -336,16 +300,6 @@ public static T2 SumF(this List source, Func selector) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static double SumF(this IList source) { switch (source) @@ -355,9 +309,15 @@ public static double SumF(this IList source) case double[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return source.Sum(); + int sourceCount = source.Count; + double sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -367,16 +327,6 @@ public static double SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal SumF(this List source) - { - return NumericPolicies.Instance.SumF(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static decimal SumF(this IList source) { switch (source) @@ -386,9 +336,15 @@ public static decimal SumF(this IList source) case decimal[] sa: return sa.SumF(); case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumF(sl); default: - return source.Sum(); + int sourceCount = source.Count; + decimal sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i]; + } + return sum; } } @@ -516,16 +472,6 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static uint? SumF(this IList source) { switch (source) @@ -535,9 +481,15 @@ public static decimal SumF(this IList source) case byte?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return source.Aggregate(0U, (current, s1) => current + s1??0U); + int sourceCount = source.Count; + uint sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } @@ -547,16 +499,6 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static int? SumF(this IList source) { switch (source) @@ -566,9 +508,15 @@ public static decimal SumF(this IList source) case sbyte?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return source.Aggregate(0, (current, s1) => current + s1??0); + int sourceCount = source.Count; + int sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } @@ -578,16 +526,6 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static uint? SumF(this IList source) { switch (source) @@ -597,9 +535,15 @@ public static decimal SumF(this IList source) case ushort?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return source.Aggregate(0U, (current, s1) => current + s1??0U); + int sourceCount = source.Count; + uint sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } @@ -609,16 +553,6 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static int? SumF(this IList source) { switch (source) @@ -628,9 +562,15 @@ public static decimal SumF(this IList source) case short?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return source.Aggregate(0, (current, s1) => current + s1??0); + int sourceCount = source.Count; + int sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } @@ -640,16 +580,6 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static uint? SumF(this IList source) { switch (source) @@ -659,9 +589,15 @@ public static decimal SumF(this IList source) case uint?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return (uint)source.Aggregate(0UL, (current, s1) => current + s1??0UL); + int sourceCount = source.Count; + uint sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } @@ -671,16 +607,6 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static int? SumF(this IList source) { switch (source) @@ -690,9 +616,15 @@ public static decimal SumF(this IList source) case int?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return source.Sum(); + int sourceCount = source.Count; + int sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } @@ -702,16 +634,6 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static ulong? SumF(this IList source) { switch (source) @@ -721,9 +643,15 @@ public static decimal SumF(this IList source) case ulong?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return source.Aggregate(0UL, (current, s1) => (current + s1??0UL)); + int sourceCount = source.Count; + ulong sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } @@ -733,16 +661,6 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static long? SumF(this IList source) { switch (source) @@ -752,9 +670,15 @@ public static decimal SumF(this IList source) case long?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return source.Sum(); + int sourceCount = source.Count; + long sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } @@ -764,16 +688,6 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float? SumF(this List source) - { - return (float?) NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static float? SumF(this IList source) { switch (source) @@ -783,9 +697,15 @@ public static decimal SumF(this IList source) case float?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return (float?)NumericPolicies.Instance.SumFNullable(sl); default: - return source.Sum(); + int sourceCount = source.Count; + double sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return (float?) sum; } } @@ -832,16 +752,6 @@ public static T2 SumF(this List source, Func selector) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static double? SumF(this IList source) { switch (source) @@ -851,9 +761,15 @@ public static T2 SumF(this List source, Func selector) case double?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return source.Sum(); + int sourceCount = source.Count; + double sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } @@ -863,16 +779,6 @@ public static T2 SumF(this List source, Func selector) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal? SumF(this List source) - { - return NumericPolicies.Instance.SumFNullable(source); - } - - /// - /// Adds a sequence of values. - /// - /// The sequence to add. - /// The sum of the sequence. public static decimal? SumF(this IList source) { switch (source) @@ -882,9 +788,15 @@ public static T2 SumF(this List source, Func selector) case decimal?[] sa: return SumF(sa); // Do this to prevent compiler causing recursion in to this same function case List sl: - return sl.SumF(); + return NumericPolicies.Instance.SumFNullable(sl); default: - return source.Sum(); + int sourceCount = source.Count; + decimal sum = 0; + for (int i = 1; i < sourceCount; i++) + { + sum = sum + source[i] ?? 0; + } + return sum; } } diff --git a/LinqFaster/SumSpan.cs b/LinqFaster/SumSpan.cs index 11b0bef..0608787 100644 --- a/LinqFaster/SumSpan.cs +++ b/LinqFaster/SumSpan.cs @@ -10,6 +10,12 @@ namespace JM.LinqFaster { public static partial class LinqFaster { + /* + * Since Span is actually a struct and it does not inherit from IEnumerable, + * we can’t use LINQ against it. + * This is a big minus when compared to C# collections. + */ + #region Normal Span /// /// Adds a sequence of values. diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index e408bf9..771b21e 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -10,7 +10,7 @@ the same semantics as the Linq extensions methods. - + Applies an accumulator function over an array. @@ -18,7 +18,7 @@ An accumulator function to be invoked on each element The final accumulator value - + Applies an accumulator function over an array. The specified seed value is used as the initial accumulator value. @@ -28,7 +28,7 @@ An accumulator function to be invoked on each element The final accumulator value - + Applies an accumulator function over an array. The specified seed value is used as the initial accumulator value, and the specified @@ -70,32 +70,31 @@ A function to transform the final accumulator value into the result value. The transformed final accumulator value - + - Applies an accumulator function over a List. - - - A List to aggregate over. + Applies an accumulator function over an array. + + An array to aggregate over. An accumulator function to be invoked on each element The final accumulator value - + - Applies an accumulator function over a List. The specified seed + Applies an accumulator function over an array. The specified seed value is used as the initial accumulator value. - A List to aggregate over. + An array to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element The final accumulator value - + - Applies an accumulator function over a List. The specified seed + Applies an accumulator function over an array. The specified seed value is used as the initial accumulator value, and the specified function is used to select the result value. - A List to aggregate over. + An array to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element A function to transform the final accumulator value into the result value. @@ -455,6 +454,104 @@ The array to calculate the average of. The average of the array. + + + Computes the average of values obtained by invoking a transform function on + each element of the input array. + + The array to calculate the transformed average of. + A transform function to apply to each element. + The average of the array. + + Special case for floats to be equivalent to IEnumerable ! + + + + + Computes the average of values obtained by invoking a transform function on + each element of the input array. + + The array to calculate the transformed average of. + A transform function to apply to each element. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + Determines whether an array contains a specified element by using the @@ -1978,13 +2075,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -1992,13 +2082,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2006,13 +2089,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2020,13 +2096,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2034,13 +2103,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2048,13 +2110,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2062,13 +2117,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2076,13 +2124,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2090,13 +2131,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2115,13 +2149,6 @@ Special case for floats, as IEnumerable does the sums on doubles before returning the type. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2129,13 +2156,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2159,13 +2179,6 @@ A transformation function. The sum of the transformed elements. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2173,13 +2186,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2187,13 +2193,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2201,13 +2200,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2215,13 +2207,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2229,13 +2214,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2243,13 +2221,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2257,13 +2228,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2271,13 +2235,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2296,13 +2253,6 @@ Special case for floats, as IEnumerable does the sums on doubles before returning the type. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. @@ -2310,13 +2260,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - Adds a sequence of values. From d3b706e8b7faab5aad11dadf52ec6e42d4bd798a Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Thu, 1 Aug 2019 12:54:38 +0100 Subject: [PATCH 11/30] [Enhancement] Can these API's also work on IList #15 - Fix copy paste error - Add better intellisense text --- LinqFaster/Aggregate.cs | 71 +++++++++++++++++++++++------------------ LinqFaster/AnyAll.cs | 15 ++++++--- LinqFaster/SumList.cs | 44 ++++++++++++------------- Tests/AggregateTests.cs | 20 ++++++------ docs/linqfaster.xml | 44 ++++++++++++------------- 5 files changed, 105 insertions(+), 89 deletions(-) diff --git a/LinqFaster/Aggregate.cs b/LinqFaster/Aggregate.cs index cb0f65c..30d3bcb 100644 --- a/LinqFaster/Aggregate.cs +++ b/LinqFaster/Aggregate.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; + // ReSharper disable ForCanBeConvertedToForeach // ReSharper disable UnusedMember.Global @@ -12,14 +14,13 @@ namespace JM.LinqFaster public static partial class LinqFaster { - // ------------------------------ Arrays -------------------------- - /// - /// Applies an accumulator function over an array. + /// Applies an accumulator function over an array[T] / List{T} / or IList{T}. /// - /// An array to aggregate over. + /// An IList to aggregate over. /// An accumulator function to be invoked on each element /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TSource AggregateF(this IList source, Func func) { @@ -66,13 +67,14 @@ public static partial class LinqFaster } /// - /// Applies an accumulator function over an array. The specified seed - /// value is used as the initial accumulator value. + /// The specified seed value is used as the initial accumulator value. + /// Applies an accumulator function over an array[T] / List{T} / or IList{T}. /// - /// An array to aggregate over. + /// An IList to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TAccumulate AggregateF(this IList source, TAccumulate seed, Func func) { @@ -90,20 +92,20 @@ public static partial class LinqFaster switch (source) { case TSource[] sa: - for (int i = 1; i < sa.Length; i++) + for (int i = 0; i < sa.Length; i++) { result = func(result, sa[i]); } break; case List sl: - for (int i = 1; i < sl.Count; i++) + for (int i = 0; i < sl.Count; i++) { result = func(result, sl[i]); } break; default: int sourceCount = source.Count; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { result = func(result, source[i]); } @@ -114,15 +116,16 @@ public static partial class LinqFaster } /// - /// Applies an accumulator function over an array. The specified seed - /// value is used as the initial accumulator value, and the specified - /// function is used to select the result value. + /// The specified seed value is used as the initial accumulator value, + /// and the specified function is used to select the result value. + /// Applies an accumulator function over an array[T] / List{T} / or IList{T}. /// - /// An array to aggregate over. + /// An IList to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// A function to transform the final accumulator value into the result value. /// The transformed final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TResult AggregateF(this IList source, TAccumulate seed, Func func, Func resultSelector) @@ -146,20 +149,20 @@ public static partial class LinqFaster switch (source) { case TSource[] sa: - for (int i = 1; i < sa.Length; i++) + for (int i = 0; i < sa.Length; i++) { result = func(result, sa[i]); } break; case List sl: - for (int i = 1; i < sl.Count; i++) + for (int i = 0; i < sl.Count; i++) { result = func(result, sl[i]); } break; default: int sourceCount = source.Count; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { result = func(result, source[i]); } @@ -169,14 +172,15 @@ public static partial class LinqFaster return resultSelector(result); } - // ------------------------------ this Spans -------------------------- + // ------------------------------ Spans -------------------------- #region Normal Span /// - /// Applies an accumulator function over an array. + /// Applies an accumulator function over a Span{T}. /// - /// An array to aggregate over. + /// A Span{T} to aggregate over. /// An accumulator function to be invoked on each element /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TSource AggregateF(this Span source, Func func) { @@ -204,13 +208,14 @@ public static partial class LinqFaster } /// - /// Applies an accumulator function over an array. The specified seed + /// Applies an accumulator function over a Span{T}. The specified seed /// value is used as the initial accumulator value. /// - /// An array to aggregate over. + /// A Span{T} to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TAccumulate AggregateF(this Span source, TAccumulate seed, Func func) { @@ -234,15 +239,16 @@ public static partial class LinqFaster } /// - /// Applies an accumulator function over an array. The specified seed + /// Applies an accumulator function over a Span{T}. The specified seed /// value is used as the initial accumulator value, and the specified /// function is used to select the result value. /// - /// An array to aggregate over. + /// A Span{T} to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// A function to transform the final accumulator value into the result value. /// The transformed final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TResult AggregateF(this Span source, TAccumulate seed, Func func, Func resultSelector) @@ -272,14 +278,15 @@ public static partial class LinqFaster } #endregion Normal Span - // ------------------------------ this ReadOnlySpans -------------------------- + // ------------------------------ ReadOnlySpans -------------------------- #region ReadOnlySpan /// - /// Applies an accumulator function over an array. + /// Applies an accumulator function over a ReadOnlySpan{T}. /// - /// An array to aggregate over. + /// A ReadOnlySpan{T} to aggregate over. /// An accumulator function to be invoked on each element /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TSource AggregateF(this ReadOnlySpan source, Func func) { @@ -307,13 +314,14 @@ public static partial class LinqFaster } /// - /// Applies an accumulator function over an array. The specified seed + /// Applies an accumulator function over a ReadOnlySpan{T}. The specified seed /// value is used as the initial accumulator value. /// - /// An array to aggregate over. + /// A ReadOnlySpan{T} to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TAccumulate AggregateF(this ReadOnlySpan source, TAccumulate seed, Func func) { @@ -337,15 +345,16 @@ public static partial class LinqFaster } /// - /// Applies an accumulator function over an array. The specified seed + /// Applies an accumulator function over a ReadOnlySpan{T}. The specified seed /// value is used as the initial accumulator value, and the specified /// function is used to select the result value. /// - /// An array to aggregate over. + /// A ReadOnlySpan{T} to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// A function to transform the final accumulator value into the result value. /// The transformed final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TResult AggregateF(this ReadOnlySpan source, TAccumulate seed, Func func, Func resultSelector) diff --git a/LinqFaster/AnyAll.cs b/LinqFaster/AnyAll.cs index 8c83c76..629db7b 100644 --- a/LinqFaster/AnyAll.cs +++ b/LinqFaster/AnyAll.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace JM.LinqFaster { @@ -13,16 +14,17 @@ public static partial class LinqFaster /// /// The array to check for emptiness /// true if the source array contains any elements, otherwise, false/ - public static bool AnyF(this T[] source) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyF(this IList source) { if (source == null) { throw Error.ArgumentNull("source"); } - return source.Length > 0; + return source.Count > 0; } - + /// /// Determines whether any element of an array satisfies a condition. @@ -30,6 +32,7 @@ public static bool AnyF(this T[] source) /// An array whose elements to apply the predicate to. /// A function to test each element for a condition. /// true if any elements in the source array pass the test in the specified predicate; otherwise, false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool AnyF(this TSource[] source, Predicate predicate) { if (source == null) @@ -45,7 +48,7 @@ public static bool AnyF(this TSource[] source, Predicate predi return Array.Exists(source, predicate); } - + /// /// Determines whether all elements of an array satisfy a condition. /// @@ -53,6 +56,7 @@ public static bool AnyF(this TSource[] source, Predicate predi /// A function to test each element for a condition. /// true if every element of the source array passes the test in the specified /// predicate, or if the array is empty; otherwise, false + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool AllF(this TSource[] source, Predicate predicate) { if (source == null) @@ -75,6 +79,7 @@ public static bool AllF(this TSource[] source, Predicate predi /// /// The array to check for emptiness /// true if the source array contains any elements, otherwise, false/ + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool AnyF(this Span source) { if (source == null) @@ -92,6 +97,7 @@ public static bool AnyF(this Span source) /// An array whose elements to apply the predicate to. /// A function to test each element for a condition. /// true if any elements in the source array pass the test in the specified predicate; otherwise, false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool AnyF(this Span source, Predicate predicate) { if (source == null) @@ -119,6 +125,7 @@ public static bool AnyF(this Span source, Predicate p /// A function to test each element for a condition. /// true if every element of the source array passes the test in the specified /// predicate, or if the array is empty; otherwise, false + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool AllF(this Span source, Predicate predicate) { if (source == null) diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index cda7020..7e0c867 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -34,7 +34,7 @@ public static uint SumF(this IList source) default: int sourceCount = source.Count; uint sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -61,7 +61,7 @@ public static int SumF(this IList source) default: int sourceCount = source.Count; int sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -88,7 +88,7 @@ public static uint SumF(this IList source) default: int sourceCount = source.Count; uint sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -115,7 +115,7 @@ public static int SumF(this IList source) default: int sourceCount = source.Count; int sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -142,7 +142,7 @@ public static uint SumF(this IList source) default: int sourceCount = source.Count; uint sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -169,7 +169,7 @@ public static int SumF(this IList source) default: int sourceCount = source.Count; int sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -196,7 +196,7 @@ public static ulong SumF(this IList source) default: int sourceCount = source.Count; ulong sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -223,7 +223,7 @@ public static long SumF(this IList source) default: int sourceCount = source.Count; long sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -250,7 +250,7 @@ public static float SumF(this IList source) default: int sourceCount = source.Count; double sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -313,7 +313,7 @@ public static double SumF(this IList source) default: int sourceCount = source.Count; double sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -340,7 +340,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; decimal sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i]; } @@ -485,7 +485,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; uint sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -512,7 +512,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; int sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -539,7 +539,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; uint sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -566,7 +566,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; int sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -593,7 +593,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; uint sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -620,7 +620,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; int sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -647,7 +647,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; ulong sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -674,7 +674,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; long sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -701,7 +701,7 @@ public static decimal SumF(this IList source) default: int sourceCount = source.Count; double sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -765,7 +765,7 @@ public static T2 SumF(this List source, Func selector) default: int sourceCount = source.Count; double sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } @@ -792,7 +792,7 @@ public static T2 SumF(this List source, Func selector) default: int sourceCount = source.Count; decimal sum = 0; - for (int i = 1; i < sourceCount; i++) + for (int i = 0; i < sourceCount; i++) { sum = sum + source[i] ?? 0; } diff --git a/Tests/AggregateTests.cs b/Tests/AggregateTests.cs index 3d39069..295afb8 100644 --- a/Tests/AggregateTests.cs +++ b/Tests/AggregateTests.cs @@ -1,18 +1,18 @@ -using NUnit.Framework; -using JM.LinqFaster; +using System; using System.Linq; -using System; +using JM.LinqFaster; +using NUnit.Framework; using static Tests.Test; namespace Tests { [TestFixture] - class AggregateTests + internal class AggregateTests { [Test, Category("TEST")] public void AggregateArray() { - + var a = intArray.AggregateF(addXInts); var aSpan = intArray.AsSpan().AggregateF(addXInts); var b = intArray.Aggregate(addXInts); @@ -23,11 +23,11 @@ public void AggregateArray() Func lambda2 = (acc, x) => acc += x; var seed = "seed"; - var c = intArray.AggregateF(seed,lambda2); - var cSpan = intArray.AsSpan().AggregateF(seed, lambda2); - var d = intArray.Aggregate(seed,lambda2); - + var c = intArray.AggregateF(seed, lambda2); + var d = intArray.Aggregate(seed, lambda2); Assert.That(c, Is.EqualTo(d)); + + var cSpan = intArray.AsSpan().AggregateF(seed, lambda2); Assert.That(cSpan, Is.EqualTo(d)); var e = intArray.AggregateF(seed, lambda2, (x => "")); @@ -40,7 +40,7 @@ public void AggregateArray() [Test] public void AggregateList() { - + var a = intList.AggregateF(addXInts); var b = intList.Aggregate(addXInts); Assert.That(a, Is.EqualTo(b)); diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 771b21e..1aa21b0 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -12,29 +12,29 @@ - Applies an accumulator function over an array. + Applies an accumulator function over an array[T] / List{T} / or IList{T}. - An array to aggregate over. + An IList to aggregate over. An accumulator function to be invoked on each element The final accumulator value - Applies an accumulator function over an array. The specified seed - value is used as the initial accumulator value. + The specified seed value is used as the initial accumulator value. + Applies an accumulator function over an array[T] / List{T} / or IList{T}. - An array to aggregate over. + An IList to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element The final accumulator value - Applies an accumulator function over an array. The specified seed - value is used as the initial accumulator value, and the specified - function is used to select the result value. + The specified seed value is used as the initial accumulator value, + and the specified function is used to select the result value. + Applies an accumulator function over an array[T] / List{T} / or IList{T}. - An array to aggregate over. + An IList to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element A function to transform the final accumulator value into the result value. @@ -42,29 +42,29 @@ - Applies an accumulator function over an array. + Applies an accumulator function over a Span{T}. - An array to aggregate over. + A Span{T} to aggregate over. An accumulator function to be invoked on each element The final accumulator value - Applies an accumulator function over an array. The specified seed + Applies an accumulator function over a Span{T}. The specified seed value is used as the initial accumulator value. - An array to aggregate over. + A Span{T} to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element The final accumulator value - Applies an accumulator function over an array. The specified seed + Applies an accumulator function over a Span{T}. The specified seed value is used as the initial accumulator value, and the specified function is used to select the result value. - An array to aggregate over. + A Span{T} to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element A function to transform the final accumulator value into the result value. @@ -72,35 +72,35 @@ - Applies an accumulator function over an array. + Applies an accumulator function over a ReadOnlySpan{T}. - An array to aggregate over. + A ReadOnlySpan{T} to aggregate over. An accumulator function to be invoked on each element The final accumulator value - Applies an accumulator function over an array. The specified seed + Applies an accumulator function over a ReadOnlySpan{T}. The specified seed value is used as the initial accumulator value. - An array to aggregate over. + A ReadOnlySpan{T} to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element The final accumulator value - Applies an accumulator function over an array. The specified seed + Applies an accumulator function over a ReadOnlySpan{T}. The specified seed value is used as the initial accumulator value, and the specified function is used to select the result value. - An array to aggregate over. + A ReadOnlySpan{T} to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element A function to transform the final accumulator value into the result value. The transformed final accumulator value - + Determines whether an array contains any elements From 1e464b9324de0fea247a9e3c8ff19894b9c93654 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Fri, 2 Aug 2019 12:33:31 +0100 Subject: [PATCH 12/30] Investigate #22: [Question] Span_FirstF and List_First are slower than just calling foreach -> Why? --- Benchmarks/Benchmarks.cs | 187 +++++++++++--- LinqFaster/First.cs | 375 +++++++++++++++++++++++----- LinqFaster/Utils/CustomPartition.cs | 2 +- LinqFaster/Utils/Error.cs | 10 +- LinqFaster/Utils/SliceHelper.cs | 7 +- docs/linqfaster.xml | 88 ++++++- 6 files changed, 557 insertions(+), 112 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 7e17a74..4392a39 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -355,31 +355,31 @@ public void Setup() // return intArray.SumF(x => x/2); //} - private static readonly Func mulXInts = (acc, x) => acc += x * x; + //private static readonly Func mulXInts = (acc, x) => acc += x * x; - [Benchmark] - public double IntArrayAggregateLinq() - { - return intArray.Aggregate(0.0D, mulXInts); - } + //[Benchmark] + //public double IntArrayAggregateLinq() + //{ + // return intArray.Aggregate(0.0D, mulXInts); + //} - [Benchmark] - public double IntArrayAggregateFast() - { - return intArray.AggregateF(0.0D, mulXInts); - } + //[Benchmark] + //public double IntArrayAggregateFast() + //{ + // return intArray.AggregateF(0.0D, mulXInts); + //} - [Benchmark] - public double IntReadOnlyArrayAggregateLinq() - { - return Array.AsReadOnly(intArray).Aggregate(0.0D, mulXInts); - } + //[Benchmark] + //public double IntReadOnlyArrayAggregateLinq() + //{ + // return Array.AsReadOnly(intArray).Aggregate(0.0D, mulXInts); + //} - [Benchmark] - public double IntReadOnlyArrayAggregateFast() - { - return Array.AsReadOnly(intArray).AggregateF(0.0D, mulXInts); - } + //[Benchmark] + //public double IntReadOnlyArrayAggregateFast() + //{ + // return Array.AsReadOnly(intArray).AggregateF(0.0D, mulXInts); + //} //[Benchmark] //public double IntSpanAggregateForEach() @@ -412,30 +412,159 @@ public double IntReadOnlyArrayAggregateFast() // return intArray.AggregateF(0.0, mulXInts, acc => acc / intArray.Length); //} + //[Benchmark] + //public double IntListAggregateLinq() + //{ + // return intList.Aggregate(0.0, mulXInts); + //} + + //[Benchmark] + //public double IntListAggregateFast() + //{ + // return intList.AggregateF(0.0, mulXInts); + //} + + //[Benchmark] + //public double IntReadOnlyListAggregateLinq() + //{ + // return intList.AsReadOnly().Aggregate(0.0, mulXInts); + //} + + //[Benchmark] + //public double IntReadOnlyListAggregateFast() + //{ + // return intList.AsReadOnly().AggregateF(0.0, mulXInts); + //} + + private static readonly Func firstInts = (x) => x > 0; + + [Benchmark] + public double IntArrayFirstLinq() + { + return intArray.First(firstInts); + } + + [Benchmark] + public double IntArrayFirstFast() + { + return intArray.FirstF(firstInts); + } + + [Benchmark] + public double IntArrayFirstFast1() + { + Predicate predicate = new Predicate(firstInts); + return Array.Find(intArray, predicate); + } + + [Benchmark] + public double IntSpanFirstForEach() + { + Span asSpan = intArray.AsSpan(); + foreach (int i in asSpan) + { + if (firstInts(i)) + { + return i; + } + } + + return 0; + } + + [Benchmark] + public double IntSpanFirstFast() + { + return intArray.AsSpan().FirstF(firstInts); + } + [Benchmark] - public double IntListAggregateLinq() + public double IntListFirstLinq() { - return intList.Aggregate(0.0, mulXInts); + return intList.First(firstInts); } [Benchmark] - public double IntListAggregateFast() + public double IntListFirstFast() { - return intList.AggregateF(0.0, mulXInts); + return intList.FirstF(firstInts); } [Benchmark] - public double IntReadOnlyListAggregateLinq() + public double IntListFirstFast1() { - return intList.AsReadOnly().Aggregate(0.0, mulXInts); + Predicate predicate = new Predicate(firstInts); + int sourceCount = intList.Count; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(intList[i])) + { + return intList[i]; + } + } + + return 0; + } + + [Benchmark] + public double IntAsListReadOnlyFirstLinq() + { + return intList.AsReadOnly().First(firstInts); } [Benchmark] - public double IntReadOnlyListAggregateFast() + public double IntAsListReadOnlyFirstFast() { - return intList.AsReadOnly().AggregateF(0.0, mulXInts); + return intList.AsReadOnly().FirstF(firstInts); } + [Benchmark] + public double IntArrayAsReadOnlyFirstLinq() + { + return Array.AsReadOnly(intArray).First(firstInts); + } + + [Benchmark] + public double IntArrayAsReadOnlyFirstFast() + { + return Array.AsReadOnly(intArray).FirstF(firstInts); + } + + //[Benchmark] + //public double IntReadOnlyArrayFirstLinq() + //{ + // return Array.AsReadOnly(intArray).First(firstInts); + //} + + //[Benchmark] + //public double IntReadOnlyArrayFirstFast() + //{ + // return Array.AsReadOnly(intArray).FirstF(firstInts); + //} + + //[Benchmark] + //public double IntListFirstLinq() + //{ + // return intList.First(firstInts); + //} + + //[Benchmark] + //public double IntListFirstFast() + //{ + // return intList.FirstF(firstInts); + //} + + //[Benchmark] + //public double IntReadOnlyListFirstLinq() + //{ + // return intList.AsReadOnly().First(firstInts); + //} + + //[Benchmark] + //public double IntReadOnlyListFirstFast() + //{ + // return intList.AsReadOnly().FirstF(firstInts); + //} //[Benchmark] //public double IntArrayWhereAggregateLinq() diff --git a/LinqFaster/First.cs b/LinqFaster/First.cs index 4c82a73..e7edddd 100644 --- a/LinqFaster/First.cs +++ b/LinqFaster/First.cs @@ -1,5 +1,8 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global namespace JM.LinqFaster { @@ -13,11 +16,12 @@ public static partial class LinqFaster /// /// The array to return the first element of. /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T FirstF(this T[] source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -30,18 +34,19 @@ public static T FirstF(this T[] source) /// Returns the first element in an array that satisfies a specified condition. /// /// An array to return an element from. - /// A function to teast each element for a condition. + /// A function to test each element for a condition. /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T FirstF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); } for (int i = 0; i < source.Length; i++) @@ -55,9 +60,6 @@ public static T FirstF(this T[] source, Func predicate) throw Error.NoMatch(); } - - - /// /// Returns the first element of an array, or a default value if the /// array contains no elements. @@ -69,7 +71,7 @@ public static T FirstOrDefaultF(this T[] source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -85,16 +87,17 @@ public static T FirstOrDefaultF(this T[] source) /// An IEnumerable to return an element from. /// A function to test each element for a condition. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T FirstOrDefaultF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); } for (int i = 0; i < source.Length; i++) @@ -107,20 +110,20 @@ public static T FirstOrDefaultF(this T[] source, Func predicate) return default(T); } - // -------------------------- this Span -------------------------------------------- /// - /// Returns the first element of an array. + /// Returns the first element of an Array / List / IList. /// /// The array to return the first element of. /// The first element in the specified array. - public static T FirstF(this Span source) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this IList source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } - if (source.Length == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -128,37 +131,43 @@ public static T FirstF(this Span source) } /// - /// Returns the first element in an array that satisfies a specified condition. + /// Returns the first element in an array / List / IList that satisfies a specified condition. /// - /// An array to return an element from. - /// A function to teast each element for a condition. + /// An IList to return an element from. + /// A function to test each element for a condition. /// The first element that satisfies the condition. - public static T FirstF(this Span source, Func predicate) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this IList source, Func func) { - if (source == null) + if (func == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(func)); } - if (predicate == null) + switch (source) { - throw Error.ArgumentNull("predicate"); - } - - for (int i = 0; i < source.Length; i++) - { - if (predicate(source[i])) - { - return source[i]; - } + case null: + throw Error.ArgumentNull(nameof(source)); + case T[] sa: + return sa.FirstF(func); + default: + { + int sourceCount = source.Count; + for (int i = 0; i < sourceCount; i++) + { + if (func(source[i])) + { + return source[i]; + } + } + + break; + } } throw Error.NoMatch(); } - - - /// /// Returns the first element of an array, or a default value if the /// array contains no elements. @@ -166,13 +175,14 @@ public static T FirstF(this Span source, Func predicate) /// The array to return the first element of. /// default value if source is empty, otherwise, the first element /// in source. - public static T FirstOrDefaultF(this Span source) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this IList source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } - if (source.Length == 0) + if (source.Count == 0) { return default(T); } @@ -184,26 +194,35 @@ public static T FirstOrDefaultF(this Span source) /// default value if no such element is found. /// /// An IEnumerable to return an element from. - /// A function to test each element for a condition. + /// A function to test each element for a condition. /// - public static T FirstOrDefaultF(this Span source, Func predicate) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this IList source, Func func) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (predicate == null) + if (func == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(func)); } - for (int i = 0; i < source.Length; i++) + switch (source) { - if (predicate(source[i])) - { - return source[i]; - } + case null: + throw Error.ArgumentNull(nameof(source)); + case T[] sa: + return sa.FirstOrDefaultF(func); + default: + { + int sourceCount = source.Count; + for (int i = 0; i < sourceCount; i++) + { + if (func(source[i])) + { + return source[i]; + } + } + + break; + } } return default(T); @@ -216,11 +235,12 @@ public static T FirstOrDefaultF(this Span source, Func predicate) /// /// The list to return the first element of. /// The first element in the specified list. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T FirstF(this List source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -233,25 +253,31 @@ public static T FirstF(this List source) /// Returns the first element in a list that satisfies a specified condition. /// /// An list to return an element from. - /// A function to teast each element for a condition. + /// A function to test each element for a condition. /// The first element in the list that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T FirstF(this List source, Predicate predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); } - var firstIndex = source.FindIndex(predicate); - if (firstIndex == -1) - throw Error.NoMatch(); - else - return source[firstIndex]; + int sourceCount = source.Count; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + return source[i]; + } + } + + throw Error.NoMatch(); } /// @@ -261,11 +287,12 @@ public static T FirstF(this List source, Predicate predicate) /// The array to return the first element of. /// default value if source is empty, otherwise, the first element /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T FirstOrDefaultF(this List source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -281,23 +308,237 @@ public static T FirstOrDefaultF(this List source) /// An IEnumerable to return an element from. /// A function to test each element for a condition. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T FirstOrDefaultF(this List source, Predicate predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); + } + + int sourceCount = source.Count; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + return source[i]; + } + } + return default(T); + } + + // -------------------------- Span -------------------------------------------- + #region Normal Span + /// + /// Returns the first element of an Span. + /// + /// The Span to return the first element of. + /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); } + return source[0]; + } - var firstIndex = source.FindIndex(predicate); - if (firstIndex == -1) + /// + /// Returns the first element in an Span that satisfies a specified condition. + /// + /// An Span to return an element from. + /// A function to test each element for a condition. + /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this Span source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + int sourceCount = source.Length; + for (int i = 0; i < sourceCount; i++) + { + if (func(source[i])) + { + return source[i]; + } + } + + throw Error.NoMatch(); + } + + /// + /// Returns the first element of an Span, or a default value if the + /// array contains no elements. + /// + /// The Span to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { return default(T); - else - return source[firstIndex]; + } + return source[0]; } + + /// + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. + /// + /// An Span to return an element from. + /// A function to test each element for a condition. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this Span source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + foreach (T a in source) + { + if (func(a)) + { + return a; + } + } + + return default(T); + } + #endregion Normal Span + + #region ReadOnlySpan + /// + /// Returns the first element of an ReadOnlySpan. + /// + /// The ReadOnlySpan to return the first element of. + /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + return source[0]; + } + + /// + /// Returns the first element in an ReadOnlySpan that satisfies a specified condition. + /// + /// An ReadOnlySpan to return an element from. + /// A function to test each element for a condition. + /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this ReadOnlySpan source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + foreach (T a in source) + { + if (func(a)) + { + return a; + } + } + + throw Error.NoMatch(); + } + + /// + /// Returns the first element of an ReadOnlySpan, or a default value if the + /// array contains no elements. + /// + /// The ReadOnlySpan to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + return default(T); + } + return source[0]; + } + + /// + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. + /// + /// An ReadOnlySpan to return an element from. + /// A function to test each element for a condition. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this ReadOnlySpan source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + foreach (T a in source) + { + if (func(a)) + { + return a; + } + } + + return default(T); + } + #endregion ReadOnlySpan + } } diff --git a/LinqFaster/Utils/CustomPartition.cs b/LinqFaster/Utils/CustomPartition.cs index 8f929ed..7e9dedc 100644 --- a/LinqFaster/Utils/CustomPartition.cs +++ b/LinqFaster/Utils/CustomPartition.cs @@ -5,7 +5,7 @@ namespace JM.LinqFaster.Utils { - public class EmptyOrderablePartitioner : OrderablePartitioner + internal class EmptyOrderablePartitioner : OrderablePartitioner { // Constructor just grabs the collection to wrap public EmptyOrderablePartitioner() diff --git a/LinqFaster/Utils/Error.cs b/LinqFaster/Utils/Error.cs index 8955bd4..27b8205 100644 --- a/LinqFaster/Utils/Error.cs +++ b/LinqFaster/Utils/Error.cs @@ -1,18 +1,26 @@ using System; +using System.Runtime.CompilerServices; internal static class Error { + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Exception ArgumentNull(string s) { return new ArgumentNullException(s); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Exception ArgumentOutOfRange(string s) { return new ArgumentOutOfRangeException(s); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Exception MoreThanOneElement() { return new InvalidOperationException("Sequence contains more than one element"); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Exception MoreThanOneMatch() { return new InvalidOperationException("Sequence contains more than one matching element"); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Exception NoElements() { return new InvalidOperationException("Sequence contains no elements"); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Exception NoMatch() { return new InvalidOperationException("Sequence contains no matching element"); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Exception NotSupported() { return new NotSupportedException(); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/LinqFaster/Utils/SliceHelper.cs b/LinqFaster/Utils/SliceHelper.cs index 9a75a1a..06c82dd 100644 --- a/LinqFaster/Utils/SliceHelper.cs +++ b/LinqFaster/Utils/SliceHelper.cs @@ -1,12 +1,13 @@ using System; -using System.Collections.Generic; -using System.Text; +using System.Runtime.CompilerServices; namespace JM.LinqFaster { public static class SliceHelper { - public static Span Slice(this T[] array,int start, int len) { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span Slice(this T[] array, int start, int len) + { return array.AsSpan().Slice(start, len); } } diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 1aa21b0..52a6884 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -633,7 +633,7 @@ Returns the first element in an array that satisfies a specified condition. An array to return an element from. - A function to teast each element for a condition. + A function to test each element for a condition. The first element that satisfies the condition. @@ -654,22 +654,22 @@ A function to test each element for a condition. - + - Returns the first element of an array. + Returns the first element of an Array / List / IList. The array to return the first element of. The first element in the specified array. - + - Returns the first element in an array that satisfies a specified condition. + Returns the first element in an array / List / IList that satisfies a specified condition. - An array to return an element from. - A function to teast each element for a condition. + An IList to return an element from. + A function to test each element for a condition. The first element that satisfies the condition. - + Returns the first element of an array, or a default value if the array contains no elements. @@ -678,13 +678,13 @@ default value if source is empty, otherwise, the first element in source. - + Returns the first element of the sequence that satisfies a condition or a default value if no such element is found. An IEnumerable to return an element from. - A function to test each element for a condition. + A function to test each element for a condition. @@ -699,7 +699,7 @@ Returns the first element in a list that satisfies a specified condition. An list to return an element from. - A function to teast each element for a condition. + A function to test each element for a condition. The first element in the list that satisfies the condition. @@ -720,6 +720,72 @@ A function to test each element for a condition. + + + Returns the first element of an Span. + + The Span to return the first element of. + The first element in the specified array. + + + + Returns the first element in an Span that satisfies a specified condition. + + An Span to return an element from. + A function to test each element for a condition. + The first element that satisfies the condition. + + + + Returns the first element of an Span, or a default value if the + array contains no elements. + + The Span to return the first element of. + default value if source is empty, otherwise, the first element + in source. + + + + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. + + An Span to return an element from. + A function to test each element for a condition. + + + + + Returns the first element of an ReadOnlySpan. + + The ReadOnlySpan to return the first element of. + The first element in the specified array. + + + + Returns the first element in an ReadOnlySpan that satisfies a specified condition. + + An ReadOnlySpan to return an element from. + A function to test each element for a condition. + The first element that satisfies the condition. + + + + Returns the first element of an ReadOnlySpan, or a default value if the + array contains no elements. + + The ReadOnlySpan to return the first element of. + default value if source is empty, otherwise, the first element + in source. + + + + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. + + An ReadOnlySpan to return an element from. + A function to test each element for a condition. + + Returns the last element of a sequence. From 81c2a40bc47100a8b19067ee114313a2ec28c383 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Fri, 2 Aug 2019 15:46:35 +0100 Subject: [PATCH 13/30] Investigate #22: [Question] Span_FirstF and List_FirstF are slower than just calling foreach -> Why? --- Benchmarks/Benchmarks.cs | 159 ++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 77 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 4392a39..d39cc42 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -8,6 +8,7 @@ using BenchmarkDotNet.Running; using JM.LinqFaster; +using JM.LinqFaster.SIMD; namespace Tests { @@ -152,7 +153,7 @@ public void Setup() //[Benchmark] //public int IntIArraySumFast() //{ - // return ((IList)intArray).SumF(); + // return ((IReadOnlyList)intArray).SumF(); //} //[Benchmark] @@ -168,28 +169,28 @@ public void Setup() //} //[Benchmark] - //public int IntIListSumLinq() + //public int IntIReadOnlyListSumLinq() //{ - // return ((IList)intList).Sum(); + // return ((IReadOnlyList)intList).Sum(); //} //[Benchmark] - //public int IntIListSumFast() + //public int IntIReadOnlyListSumFast() //{ - // return ((IList)intList).SumF(); + // return ((IReadOnlyList)intList).SumF(); //} //[Benchmark] //public int IntArraySumLinqSelect() //{ - // return intArray.Sum(x=>x); + // return intArray.Sum(x => x); //} //[Benchmark] //public int IntArraySumFastSelect() //{ - // return intArray.SumF(x=>x); + // return intArray.SumF(x => x); //} //[Benchmark] @@ -253,13 +254,13 @@ public void Setup() //} //[Benchmark] - //public float ? FloatNullArraySumLinq() + //public float? FloatNullArraySumLinq() //{ // return floatNullArray.Sum(); //} //[Benchmark] - //public float ? FloatNullArraySumFast() + //public float? FloatNullArraySumFast() //{ // return floatNullArray.SumF(); //} @@ -308,19 +309,19 @@ public void Setup() //} //[Benchmark] - //public double ? DoubleNullArraySumLinq() + //public double? DoubleNullArraySumLinq() //{ // return doubleNullArray.Sum(); //} //[Benchmark] - //public double ? DoubleNullArraySumFast() + //public double? DoubleNullArraySumFast() //{ // return doubleNullArray.SumF(); //} //[Benchmark] - //public double ? DoubleNullArraySumFastSelect() + //public double? DoubleNullArraySumFastSelect() //{ // return doubleNullArray.SumF(x => x ?? 0); //} @@ -352,7 +353,7 @@ public void Setup() //[Benchmark] //public int IntArraySumWithSelectFast() //{ - // return intArray.SumF(x => x/2); + // return intArray.SumF(x => x / 2); //} //private static readonly Func mulXInts = (acc, x) => acc += x * x; @@ -438,29 +439,39 @@ public void Setup() private static readonly Func firstInts = (x) => x > 0; - [Benchmark] - public double IntArrayFirstLinq() - { - return intArray.First(firstInts); - } + //[Benchmark] + //public double IntArrayFirstLinq() + //{ + // return intArray.First(firstInts); + //} + + //[Benchmark] + //public double IntArrayFirstFast() + //{ + // return intArray.FirstF(firstInts); + //} + + //[Benchmark] + //public double IntArrayFirstFast1() + //{ + // Predicate predicate = new Predicate(firstInts); + // return Array.Find(intArray, predicate); + //} - [Benchmark] - public double IntArrayFirstFast() - { - return intArray.FirstF(firstInts); - } [Benchmark] - public double IntArrayFirstFast1() + public double IntSpanFirstFast() { - Predicate predicate = new Predicate(firstInts); - return Array.Find(intArray, predicate); + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.FirstF(firstInts); } [Benchmark] public double IntSpanFirstForEach() { - Span asSpan = intArray.AsSpan(); + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); foreach (int i in asSpan) { if (firstInts(i)) @@ -472,63 +483,57 @@ public double IntSpanFirstForEach() return 0; } - [Benchmark] - public double IntSpanFirstFast() - { - return intArray.AsSpan().FirstF(firstInts); - } - - [Benchmark] - public double IntListFirstLinq() - { - return intList.First(firstInts); - } + //[Benchmark] + //public double IntListFirstLinq() + //{ + // return intList.First(firstInts); + //} - [Benchmark] - public double IntListFirstFast() - { - return intList.FirstF(firstInts); - } + //[Benchmark] + //public double IntListFirstFast() + //{ + // return intList.FirstF(firstInts); + //} - [Benchmark] - public double IntListFirstFast1() - { - Predicate predicate = new Predicate(firstInts); - int sourceCount = intList.Count; - for (int i = 0; i < sourceCount; i++) - { - if (predicate(intList[i])) - { - return intList[i]; - } - } + //[Benchmark] + //public double IntListFirstFast1() + //{ + // Predicate predicate = new Predicate(firstInts); + // int sourceCount = intList.Count; + // for (int i = 0; i < sourceCount; i++) + // { + // if (predicate(intList[i])) + // { + // return intList[i]; + // } + // } - return 0; - } + // return 0; + //} - [Benchmark] - public double IntAsListReadOnlyFirstLinq() - { - return intList.AsReadOnly().First(firstInts); - } + //[Benchmark] + //public double IntAsListReadOnlyFirstLinq() + //{ + // return intList.AsReadOnly().First(firstInts); + //} - [Benchmark] - public double IntAsListReadOnlyFirstFast() - { - return intList.AsReadOnly().FirstF(firstInts); - } + //[Benchmark] + //public double IntAsListReadOnlyFirstFast() + //{ + // return intList.AsReadOnly().FirstF(firstInts); + //} - [Benchmark] - public double IntArrayAsReadOnlyFirstLinq() - { - return Array.AsReadOnly(intArray).First(firstInts); - } + //[Benchmark] + //public double IntArrayAsReadOnlyFirstLinq() + //{ + // return Array.AsReadOnly(intArray).First(firstInts); + //} - [Benchmark] - public double IntArrayAsReadOnlyFirstFast() - { - return Array.AsReadOnly(intArray).FirstF(firstInts); - } + //[Benchmark] + //public double IntArrayAsReadOnlyFirstFast() + //{ + // return Array.AsReadOnly(intArray).FirstF(firstInts); + //} //[Benchmark] //public double IntReadOnlyArrayFirstLinq() From b762eff6b298fc4c50c92eca813ce438c9d11b18 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Mon, 5 Aug 2019 09:27:27 +0100 Subject: [PATCH 14/30] Investigate #15: [Enhancement] Can these API's also work on IReadOnlyList - Change over to IReadOnlyList --- Benchmarks/Benchmarks.cs | 308 +++++++++++++++++++------------------ LinqFaster/Aggregate.cs | 18 +-- LinqFaster/AnyAll.cs | 2 +- LinqFaster/AverageIList.cs | 50 +++--- LinqFaster/First.cs | 16 +- LinqFaster/SumList.cs | 46 +++--- Tests/SelectTEsts.cs | 19 ++- Tests/SumTests.cs | 18 ++- docs/linqfaster.xml | 130 ++++++++-------- 9 files changed, 323 insertions(+), 284 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index d39cc42..e915aca 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -83,7 +83,7 @@ public void Setup() //[Benchmark] //public int IntArrayOrderByLinq() //{ - // return intArray.OrderBy((x => x -1)).Sum(); + // return intArray.OrderBy((x => x - 1)).Sum(); //} //[Benchmark] @@ -184,38 +184,56 @@ public void Setup() //[Benchmark] //public int IntArraySumLinqSelect() //{ - // return intArray.Sum(x => x); + // return intArray.Sum(x => x / 2); //} //[Benchmark] //public int IntArraySumFastSelect() //{ - // return intArray.SumF(x => x); + // return intArray.SumF(x => x / 2); //} + [Benchmark] + public double IntReadOnlyArraySumWithSelectLinq() + { + return Array.AsReadOnly(intArray).Sum(x => x / 2); + } + + [Benchmark] + public double IntReadOnlyArraySumWithSelectFast() + { + return Array.AsReadOnly(intArray).SumF(x => x / 2); + } + //[Benchmark] //public int IntArraySumFastSIMD() //{ // return intArray.SumS(); //} - //[Benchmark] - //public int? IntNullArraySumLinq() - //{ - // return intNullArray.Sum(); - //} + [Benchmark] + public int? IntNullArraySumLinq() + { + return intNullArray.Sum(); + } - //[Benchmark] - //public int? IntNullArraySumFast() - //{ - // return intNullArray.SumF(); - //} + [Benchmark] + public int? IntNullArraySumFast() + { + return intNullArray.SumF(); + } - //[Benchmark] - //public int IntNullArraySumFastSelect() - //{ - // return intNullArray.SumF(x => x ?? 0); - //} + [Benchmark] + public int IntNullArraySumLinqSelect() + { + return intNullArray.Sum(x => x/2 ?? 0); + } + + [Benchmark] + public int IntNullArraySumFastSelect() + { + return intNullArray.SumF(x => x/2 ?? 0); + } //[Benchmark] //public float FloatArraySumLinq() @@ -244,32 +262,38 @@ public void Setup() //[Benchmark] //public float FloatArraySumLinqSelect() //{ - // return floatArray.Sum(x => x); + // return floatArray.Sum(x => x / 2); //} //[Benchmark] //public float FloatArraySumFastSelect() //{ - // return floatArray.SumF(x => x); + // return floatArray.SumF(x => x / 2); //} - //[Benchmark] - //public float? FloatNullArraySumLinq() - //{ - // return floatNullArray.Sum(); - //} + [Benchmark] + public float? FloatNullArraySumLinq() + { + return floatNullArray.Sum(); + } - //[Benchmark] - //public float? FloatNullArraySumFast() - //{ - // return floatNullArray.SumF(); - //} + [Benchmark] + public float? FloatNullArraySumFast() + { + return floatNullArray.SumF(); + } - //[Benchmark] - //public float FloatNullArraySumFastSelect() - //{ - // return floatNullArray.SumF(x => x ?? 0); - //} + [Benchmark] + public float FloatNullArraySumLinqSelect() + { + return floatNullArray.Sum(x => x / 2 ?? 0); + } + + [Benchmark] + public float FloatNullArraySumFastSelect() + { + return floatNullArray.SumF(x => x / 2 ?? 0); + } //[Benchmark] @@ -299,44 +323,50 @@ public void Setup() //[Benchmark] //public double DoubleArraySumLinqSelect() //{ - // return doubleArray.Sum(x => x); + // return doubleArray.Sum(x => x / 2); //} //[Benchmark] //public double DoubleArraySumFastSelect() //{ - // return doubleArray.SumF(x => x); + // return doubleArray.SumF(x => x / 2); //} - //[Benchmark] - //public double? DoubleNullArraySumLinq() - //{ - // return doubleNullArray.Sum(); - //} + [Benchmark] + public double? DoubleNullArraySumLinq() + { + return doubleNullArray.Sum(); + } - //[Benchmark] - //public double? DoubleNullArraySumFast() - //{ - // return doubleNullArray.SumF(); - //} + [Benchmark] + public double? DoubleNullArraySumFast() + { + return doubleNullArray.SumF(); + } - //[Benchmark] - //public double? DoubleNullArraySumFastSelect() - //{ - // return doubleNullArray.SumF(x => x ?? 0); - //} + [Benchmark] + public double? DoubleNullArraySumLinqSelect() + { + return doubleNullArray.Sum(x => x / 2 ?? 0); + } - //[Benchmark] - //public double IntArrayAverageLinq() - //{ - // return intArray.Average(); - //} + [Benchmark] + public double? DoubleNullArraySumFastSelect() + { + return doubleNullArray.SumF(x => x / 2 ?? 0); + } - //[Benchmark] - //public double IntArrayAverageFast() - //{ - // return intArray.AverageF(); - //} + [Benchmark] + public double IntArrayAverageLinq() + { + return intArray.Average(); + } + + [Benchmark] + public double IntArrayAverageFast() + { + return intArray.AverageF(); + } //[Benchmark] //public double IntArrayAverageFastSIMD() @@ -344,18 +374,50 @@ public void Setup() // return intArray.AverageS(); //} - //[Benchmark] - //public int IntArraySumWithSelectLinq() - //{ - // return intArray.Sum(x => x / 2); - //} + + [Benchmark] + public double IntListAverageLinq() + { + return intList.Average(); + } + + [Benchmark] + public double IntListAverageFast() + { + return intList.AverageF(); + } //[Benchmark] - //public int IntArraySumWithSelectFast() + //public double IntListAverageFastSIMD() //{ - // return intArray.SumF(x => x / 2); + // return intList.AverageS(); //} + [Benchmark] + public int IntListSumWithSelectLinq() + { + return intList.Sum(x => x / 2); + } + + [Benchmark] + public int IntListSumWithSelectFast() + { + return intList.SumF(x => x / 2); + } + + [Benchmark] + public double IntReadOnlyListSumWithSelectLinq() + { + return intList.AsReadOnly().Sum(x => x / 2); + } + + [Benchmark] + public double IntReadOnlyListSumWithSelectFast() + { + return intList.AsReadOnly().SumF(x => x / 2); + } + + //private static readonly Func mulXInts = (acc, x) => acc += x * x; //[Benchmark] @@ -437,7 +499,7 @@ public void Setup() // return intList.AsReadOnly().AggregateF(0.0, mulXInts); //} - private static readonly Func firstInts = (x) => x > 0; + //private static readonly Func firstInts = (x) => x > 0; //[Benchmark] //public double IntArrayFirstLinq() @@ -459,29 +521,29 @@ public void Setup() //} - [Benchmark] - public double IntSpanFirstFast() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - return asSpan.FirstF(firstInts); - } + //[Benchmark] + //public double IntSpanFirstForEach() + //{ + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // foreach (int i in asSpan) + // { + // if (firstInts(i)) + // { + // return i; + // } + // } - [Benchmark] - public double IntSpanFirstForEach() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - foreach (int i in asSpan) - { - if (firstInts(i)) - { - return i; - } - } + // return 0; + //} - return 0; - } + //[Benchmark] + //public double IntSpanFirstFast() + //{ + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // return asSpan.FirstF(firstInts); + //} //[Benchmark] //public double IntListFirstLinq() @@ -495,22 +557,6 @@ public double IntSpanFirstForEach() // return intList.FirstF(firstInts); //} - //[Benchmark] - //public double IntListFirstFast1() - //{ - // Predicate predicate = new Predicate(firstInts); - // int sourceCount = intList.Count; - // for (int i = 0; i < sourceCount; i++) - // { - // if (predicate(intList[i])) - // { - // return intList[i]; - // } - // } - - // return 0; - //} - //[Benchmark] //public double IntAsListReadOnlyFirstLinq() //{ @@ -536,51 +582,21 @@ public double IntSpanFirstForEach() //} //[Benchmark] - //public double IntReadOnlyArrayFirstLinq() - //{ - // return Array.AsReadOnly(intArray).First(firstInts); - //} - - //[Benchmark] - //public double IntReadOnlyArrayFirstFast() - //{ - // return Array.AsReadOnly(intArray).FirstF(firstInts); - //} - - //[Benchmark] - //public double IntListFirstLinq() - //{ - // return intList.First(firstInts); - //} - - //[Benchmark] - //public double IntListFirstFast() - //{ - // return intList.FirstF(firstInts); - //} - - //[Benchmark] - //public double IntReadOnlyListFirstLinq() + //public double IntArrayWhereAggregateLinq() //{ - // return intList.AsReadOnly().First(firstInts); + // return intArray.Where(x => x % 2 == 0).Aggregate(0.0, mulXInts, acc => acc / intArray.Length); //} //[Benchmark] - //public double IntReadOnlyListFirstFast() + //public double IntArrayWhereAggregateFast() //{ - // return intList.AsReadOnly().FirstF(firstInts); + // return intArray.WhereAggregateF(x => x % 2 == 0, 0.0, mulXInts, acc => acc / intArray.Length); //} //[Benchmark] - //public double IntArrayWhereAggregateLinq() - //{ - // return intArray.Where(x => x % 2 == 0).Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / intArray.Length); - //} - - //[Benchmark] - //public double IntArrayWhereAggregateFast() + //public int[] IntArraySelectLinq() //{ - // return intArray.WhereAggregateF(x => x % 2 == 0,0.0,(acc,x)=> acc += x*x,acc => acc/intArray.Length); + // return intArray.Select(x => x * x); //} //[Benchmark] @@ -592,7 +608,7 @@ public double IntSpanFirstForEach() //[Benchmark] //public int[] IntArraySelectFastSIMD() //{ - // return intArray.SelectS(x => x * x, x=>x*x); + // return intArray.SelectS(x => x * x, x => x * x); //} @@ -636,7 +652,7 @@ public double IntSpanFirstForEach() //[Benchmark] //public int IntArrayMinFastSIMD() - //{ + //{ // return intArray.MinS(); //} @@ -648,7 +664,7 @@ public double IntSpanFirstForEach() //[Benchmark] //public bool IntArraySequenceEqualF() - //{ + //{ // return intArray.SequenceEqualF(array2); //} diff --git a/LinqFaster/Aggregate.cs b/LinqFaster/Aggregate.cs index 30d3bcb..eac5b48 100644 --- a/LinqFaster/Aggregate.cs +++ b/LinqFaster/Aggregate.cs @@ -15,13 +15,13 @@ public static partial class LinqFaster { /// - /// Applies an accumulator function over an array[T] / List{T} / or IList{T}. + /// Applies an accumulator function over an array[T] / List{T} / or IReadOnlyList{T}. /// - /// An IList to aggregate over. + /// An IReadOnlyList to aggregate over. /// An accumulator function to be invoked on each element /// The final accumulator value [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TSource AggregateF(this IList source, + public static TSource AggregateF(this IReadOnlyList source, Func func) { if (source == null) @@ -68,14 +68,14 @@ public static partial class LinqFaster /// /// The specified seed value is used as the initial accumulator value. - /// Applies an accumulator function over an array[T] / List{T} / or IList{T}. + /// Applies an accumulator function over an array[T] / List{T} / or IReadOnlyList{T}. /// - /// An IList to aggregate over. + /// An IReadOnlyList to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// The final accumulator value [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TAccumulate AggregateF(this IList source, TAccumulate seed, + public static TAccumulate AggregateF(this IReadOnlyList source, TAccumulate seed, Func func) { if (source == null) @@ -118,15 +118,15 @@ public static partial class LinqFaster /// /// The specified seed value is used as the initial accumulator value, /// and the specified function is used to select the result value. - /// Applies an accumulator function over an array[T] / List{T} / or IList{T}. + /// Applies an accumulator function over an array[T] / List{T} / or IReadOnlyList{T}. /// - /// An IList to aggregate over. + /// An IReadOnlyList to aggregate over. /// The initial accumulator value. /// An accumulator function to be invoked on each element /// A function to transform the final accumulator value into the result value. /// The transformed final accumulator value [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TResult AggregateF(this IList source, TAccumulate seed, + public static TResult AggregateF(this IReadOnlyList source, TAccumulate seed, Func func, Func resultSelector) { diff --git a/LinqFaster/AnyAll.cs b/LinqFaster/AnyAll.cs index 629db7b..56363c2 100644 --- a/LinqFaster/AnyAll.cs +++ b/LinqFaster/AnyAll.cs @@ -15,7 +15,7 @@ public static partial class LinqFaster /// The array to check for emptiness /// true if the source array contains any elements, otherwise, false/ [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AnyF(this IList source) + public static bool AnyF(this IReadOnlyList source) { if (source == null) { diff --git a/LinqFaster/AverageIList.cs b/LinqFaster/AverageIList.cs index 908876d..3ce0bf7 100644 --- a/LinqFaster/AverageIList.cs +++ b/LinqFaster/AverageIList.cs @@ -21,7 +21,7 @@ public static partial class LinqFaster /// Special case for floats to be equivalent to IEnumerable ! /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float AverageF(this IList source, Func selector) + public static float AverageF(this IReadOnlyList source, Func selector) { if (source.Count == 0) { @@ -38,7 +38,7 @@ public static float AverageF(this IList source, Func selector) /// A transform function to apply to each element. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source, Func selector) + public static double AverageF(this IReadOnlyList source, Func selector) where T2 : IConvertible { if (source.Count == 0) @@ -55,7 +55,7 @@ public static float AverageF(this IList source, Func selector) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source) + public static double AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -70,7 +70,7 @@ public static double AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source) + public static double AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -85,7 +85,7 @@ public static double AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source) + public static double AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -100,7 +100,7 @@ public static double AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source) + public static double AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -115,7 +115,7 @@ public static double AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source) + public static double AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -130,7 +130,7 @@ public static double AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source) + public static double AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -145,7 +145,7 @@ public static double AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source) + public static double AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -160,7 +160,7 @@ public static double AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source) + public static double AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -176,7 +176,7 @@ public static double AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float AverageF(this IList source) + public static float AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -191,7 +191,7 @@ public static float AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double AverageF(this IList source) + public static double AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -206,7 +206,7 @@ public static double AverageF(this IList source) /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal AverageF(this IList source) + public static decimal AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -223,7 +223,7 @@ public static decimal AverageF(this IList source) /// A transform function to apply to each element. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal AverageF(this IList source, Func selector) + public static decimal AverageF(this IReadOnlyList source, Func selector) { if (source.Count == 0) { @@ -240,7 +240,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -255,7 +255,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -270,7 +270,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -285,7 +285,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -300,7 +300,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -315,7 +315,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -330,7 +330,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -345,7 +345,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -361,7 +361,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -376,7 +376,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? AverageF(this IList source) + public static double? AverageF(this IReadOnlyList source) { if (source.Count == 0) { @@ -391,7 +391,7 @@ public static decimal AverageF(this IList source, Func selecto /// The array to calculate the average of. /// The average of the array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal? AverageF(this IList source) + public static decimal? AverageF(this IReadOnlyList source) { if (source.Count == 0) { diff --git a/LinqFaster/First.cs b/LinqFaster/First.cs index e7edddd..9153d37 100644 --- a/LinqFaster/First.cs +++ b/LinqFaster/First.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; // ReSharper disable ForCanBeConvertedToForeach // ReSharper disable UnusedMember.Global @@ -112,12 +113,12 @@ public static T FirstOrDefaultF(this T[] source, Func predicate) } /// - /// Returns the first element of an Array / List / IList. + /// Returns the first element of an Array / List / IReadOnlyList. /// /// The array to return the first element of. /// The first element in the specified array. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstF(this IList source) + public static T FirstF(this IReadOnlyList source) { if (source == null) { @@ -131,13 +132,13 @@ public static T FirstF(this IList source) } /// - /// Returns the first element in an array / List / IList that satisfies a specified condition. + /// Returns the first element in an array / List / IReadOnlyList that satisfies a specified condition. /// - /// An IList to return an element from. + /// An IReadOnlyList to return an element from. /// A function to test each element for a condition. /// The first element that satisfies the condition. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstF(this IList source, Func func) + public static T FirstF(this IReadOnlyList source, Func func) { if (func == null) { @@ -176,7 +177,7 @@ public static T FirstF(this IList source, Func func) /// default value if source is empty, otherwise, the first element /// in source. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstOrDefaultF(this IList source) + public static T FirstOrDefaultF(this IReadOnlyList source) { if (source == null) { @@ -197,7 +198,8 @@ public static T FirstOrDefaultF(this IList source) /// A function to test each element for a condition. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstOrDefaultF(this IList source, Func func) + [Pure] + public static T FirstOrDefaultF(this IReadOnlyList source, Func func) { if (func == null) { diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index 7e0c867..4de9bb9 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -21,7 +21,7 @@ public static partial class LinqFaster /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint SumF(this IList source) + public static uint SumF(this IReadOnlyList source) { switch (source) { @@ -48,7 +48,7 @@ public static uint SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int SumF(this IList source) + public static int SumF(this IReadOnlyList source) { switch (source) { @@ -75,7 +75,7 @@ public static int SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint SumF(this IList source) + public static uint SumF(this IReadOnlyList source) { switch (source) { @@ -102,7 +102,7 @@ public static uint SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int SumF(this IList source) + public static int SumF(this IReadOnlyList source) { switch (source) { @@ -129,7 +129,7 @@ public static int SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint SumF(this IList source) + public static uint SumF(this IReadOnlyList source) { switch (source) { @@ -156,7 +156,7 @@ public static uint SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int SumF(this IList source) + public static int SumF(this IReadOnlyList source) { switch (source) { @@ -183,7 +183,7 @@ public static int SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong SumF(this IList source) + public static ulong SumF(this IReadOnlyList source) { switch (source) { @@ -210,7 +210,7 @@ public static ulong SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long SumF(this IList source) + public static long SumF(this IReadOnlyList source) { switch (source) { @@ -237,7 +237,7 @@ public static long SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float SumF(this IList source) + public static float SumF(this IReadOnlyList source) { switch (source) { @@ -300,7 +300,7 @@ public static T2 SumF(this List source, Func selector) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double SumF(this IList source) + public static double SumF(this IReadOnlyList source) { switch (source) { @@ -327,7 +327,7 @@ public static double SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal SumF(this IList source) + public static decimal SumF(this IReadOnlyList source) { switch (source) { @@ -387,7 +387,7 @@ public static decimal SumF(this IList source) /// A transformation function. /// The sum of the transformed elements. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T2 SumF(this IList source, Func selector) + public static T2 SumF(this IReadOnlyList source, Func selector) { switch (source) { @@ -472,7 +472,7 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint? SumF(this IList source) + public static uint? SumF(this IReadOnlyList source) { switch (source) { @@ -499,7 +499,7 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int? SumF(this IList source) + public static int? SumF(this IReadOnlyList source) { switch (source) { @@ -526,7 +526,7 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint? SumF(this IList source) + public static uint? SumF(this IReadOnlyList source) { switch (source) { @@ -553,7 +553,7 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int? SumF(this IList source) + public static int? SumF(this IReadOnlyList source) { switch (source) { @@ -580,7 +580,7 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint? SumF(this IList source) + public static uint? SumF(this IReadOnlyList source) { switch (source) { @@ -607,7 +607,7 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int? SumF(this IList source) + public static int? SumF(this IReadOnlyList source) { switch (source) { @@ -634,7 +634,7 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong? SumF(this IList source) + public static ulong? SumF(this IReadOnlyList source) { switch (source) { @@ -661,7 +661,7 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long? SumF(this IList source) + public static long? SumF(this IReadOnlyList source) { switch (source) { @@ -688,7 +688,7 @@ public static decimal SumF(this IList source) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float? SumF(this IList source) + public static float? SumF(this IReadOnlyList source) { switch (source) { @@ -752,7 +752,7 @@ public static T2 SumF(this List source, Func selector) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double? SumF(this IList source) + public static double? SumF(this IReadOnlyList source) { switch (source) { @@ -779,7 +779,7 @@ public static T2 SumF(this List source, Func selector) /// The sequence to add. /// The sum of the sequence. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal? SumF(this IList source) + public static decimal? SumF(this IReadOnlyList source) { switch (source) { diff --git a/Tests/SelectTEsts.cs b/Tests/SelectTEsts.cs index 7a31b89..50fe770 100644 --- a/Tests/SelectTEsts.cs +++ b/Tests/SelectTEsts.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System; +using NUnit.Framework; using JM.LinqFaster; using System.Linq; using static Tests.Test; @@ -15,6 +16,22 @@ public void SelectArray() var b = intArray.Select(x => x * x); Assert.That(a, Is.EqualTo(b)); + var b1 = Array.AsReadOnly(intArray).SumF(x => x * x); + + a = intArray.SelectF((x, i) => x + i); + b = intArray.Select((x, i) => x + i); + + Assert.That(a, Is.EqualTo(b)); + } + + [Test] + public void SelectSumArray() + { + var a = intArray.SelectF(x => x * x); + var b = intArray.Select(x => x * x); + + Assert.That(a, Is.EqualTo(b)); + var b1 = Array.AsReadOnly(intArray).SumF(x => x * x); a = intArray.SelectF((x, i) => x + i); b = intArray.Select((x, i) => x + i); diff --git a/Tests/SumTests.cs b/Tests/SumTests.cs index 29369ba..da29164 100644 --- a/Tests/SumTests.cs +++ b/Tests/SumTests.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using JM.LinqFaster; @@ -15,11 +16,11 @@ internal class SumTests [Test] public void SumArray() { - var a = ((IList)intArray).SumF(); + var a = ((IReadOnlyList)intArray).SumF(); var b = intArray.Sum(); Assert.That(a, Is.EqualTo(b)); - var an = ((IList)intNullArray).SumF(); + var an = ((IReadOnlyList)intNullArray).SumF(); var bn = intNullArray.Sum(); Assert.That(an, Is.EqualTo(bn)); @@ -56,13 +57,15 @@ public void SumArraySelector() { var a = intArray.SumF(x => x + 1); var b = intArray.Sum(x => x + 1); + Assert.That(a, Is.EqualTo(b)); + + var br = Array.AsReadOnly(intArray).SumF(x => x + 1); + Assert.That(a, Is.EqualTo(br)); var an = intNullArray.SumF(x => x ?? 0); var bn = intNullArray.Sum(x => x ?? 0); Assert.That(an, Is.EqualTo(bn)); - Assert.That(a, Is.EqualTo(b)); - var c = floatArray.SumF(squaredFloats); var d = floatArray.Sum(squaredFloats); @@ -93,12 +96,13 @@ public void SumListSelector() { var a = intList.SumF(x => x + 1); var b = intList.Sum(x => x + 1); - Assert.That(a, Is.EqualTo(b)); + var br = intList.AsReadOnly().SumF(x => x + 1); + Assert.That(a, Is.EqualTo(br)); + var c = floatList.SumF(squaredFloats); var d = floatList.Sum(squaredFloats); - Assert.That(c, Is.EqualTo(d)); } diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 52a6884..1cb17f9 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -10,31 +10,31 @@ the same semantics as the Linq extensions methods. - + - Applies an accumulator function over an array[T] / List{T} / or IList{T}. + Applies an accumulator function over an array[T] / List{T} / or IReadOnlyList{T}. - An IList to aggregate over. + An IReadOnlyList to aggregate over. An accumulator function to be invoked on each element The final accumulator value - + The specified seed value is used as the initial accumulator value. - Applies an accumulator function over an array[T] / List{T} / or IList{T}. + Applies an accumulator function over an array[T] / List{T} / or IReadOnlyList{T}. - An IList to aggregate over. + An IReadOnlyList to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element The final accumulator value - + The specified seed value is used as the initial accumulator value, and the specified function is used to select the result value. - Applies an accumulator function over an array[T] / List{T} / or IList{T}. + Applies an accumulator function over an array[T] / List{T} / or IReadOnlyList{T}. - An IList to aggregate over. + An IReadOnlyList to aggregate over. The initial accumulator value. An accumulator function to be invoked on each element A function to transform the final accumulator value into the result value. @@ -100,7 +100,7 @@ A function to transform the final accumulator value into the result value. The transformed final accumulator value - + Determines whether an array contains any elements @@ -172,7 +172,7 @@ true if every element of the source array passes the test in the specified predicate, or if the list is empty; otherwise, false - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -184,7 +184,7 @@ Special case for floats to be equivalent to IEnumerable ! - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -193,84 +193,84 @@ A transform function to apply to each element. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of values obtained by invoking a transform function on each element of the input array. @@ -279,77 +279,77 @@ A transform function to apply to each element. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array The array to calculate the average of. The average of the array. - + Computes the average of an array @@ -654,22 +654,22 @@ A function to test each element for a condition. - + - Returns the first element of an Array / List / IList. + Returns the first element of an Array / List / IReadOnlyList. The array to return the first element of. The first element in the specified array. - + - Returns the first element in an array / List / IList that satisfies a specified condition. + Returns the first element in an array / List / IReadOnlyList that satisfies a specified condition. - An IList to return an element from. + An IReadOnlyList to return an element from. A function to test each element for a condition. The first element that satisfies the condition. - + Returns the first element of an array, or a default value if the array contains no elements. @@ -678,7 +678,7 @@ default value if source is empty, otherwise, the first element in source. - + Returns the first element of the sequence that satisfies a condition or a default value if no such element is found. @@ -2141,63 +2141,63 @@ The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. @@ -2215,14 +2215,14 @@ Special case for floats, as IEnumerable does the sums on doubles before returning the type. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. @@ -2237,7 +2237,7 @@ A transformation function. The sum of the transformed elements. - + Adds the transformed sequence of elements. @@ -2245,63 +2245,63 @@ A transformation function. The sum of the transformed elements. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. @@ -2319,14 +2319,14 @@ Special case for floats, as IEnumerable does the sums on doubles before returning the type. - + Adds a sequence of values. The sequence to add. The sum of the sequence. - + Adds a sequence of values. From ac388010630081e80f1674439d1ad1a545f9235f Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Mon, 5 Aug 2019 10:47:38 +0100 Subject: [PATCH 15/30] More for #15: [Enhancement] Can these API's also work on IReadOnlyList - Implement LastF's the same way as FirstF's --- Benchmarks/Benchmarks.cs | 303 ++++++++++++++++---------- LinqFaster/First.cs | 2 +- LinqFaster/Last.cs | 444 ++++++++++++++++++++++++++++++--------- docs/linqfaster.xml | 142 +++++++++---- 4 files changed, 643 insertions(+), 248 deletions(-) diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index e915aca..d179406 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -193,17 +193,17 @@ public void Setup() // return intArray.SumF(x => x / 2); //} - [Benchmark] - public double IntReadOnlyArraySumWithSelectLinq() - { - return Array.AsReadOnly(intArray).Sum(x => x / 2); - } + //[Benchmark] + //public double IntReadOnlyArraySumWithSelectLinq() + //{ + // return Array.AsReadOnly(intArray).Sum(x => x / 2); + //} - [Benchmark] - public double IntReadOnlyArraySumWithSelectFast() - { - return Array.AsReadOnly(intArray).SumF(x => x / 2); - } + //[Benchmark] + //public double IntReadOnlyArraySumWithSelectFast() + //{ + // return Array.AsReadOnly(intArray).SumF(x => x / 2); + //} //[Benchmark] //public int IntArraySumFastSIMD() @@ -211,29 +211,29 @@ public double IntReadOnlyArraySumWithSelectFast() // return intArray.SumS(); //} - [Benchmark] - public int? IntNullArraySumLinq() - { - return intNullArray.Sum(); - } + //[Benchmark] + //public int? IntNullArraySumLinq() + //{ + // return intNullArray.Sum(); + //} - [Benchmark] - public int? IntNullArraySumFast() - { - return intNullArray.SumF(); - } + //[Benchmark] + //public int? IntNullArraySumFast() + //{ + // return intNullArray.SumF(); + //} - [Benchmark] - public int IntNullArraySumLinqSelect() - { - return intNullArray.Sum(x => x/2 ?? 0); - } + //[Benchmark] + //public int IntNullArraySumLinqSelect() + //{ + // return intNullArray.Sum(x => x/2 ?? 0); + //} - [Benchmark] - public int IntNullArraySumFastSelect() - { - return intNullArray.SumF(x => x/2 ?? 0); - } + //[Benchmark] + //public int IntNullArraySumFastSelect() + //{ + // return intNullArray.SumF(x => x/2 ?? 0); + //} //[Benchmark] //public float FloatArraySumLinq() @@ -271,29 +271,29 @@ public int IntNullArraySumFastSelect() // return floatArray.SumF(x => x / 2); //} - [Benchmark] - public float? FloatNullArraySumLinq() - { - return floatNullArray.Sum(); - } + //[Benchmark] + //public float? FloatNullArraySumLinq() + //{ + // return floatNullArray.Sum(); + //} - [Benchmark] - public float? FloatNullArraySumFast() - { - return floatNullArray.SumF(); - } + //[Benchmark] + //public float? FloatNullArraySumFast() + //{ + // return floatNullArray.SumF(); + //} - [Benchmark] - public float FloatNullArraySumLinqSelect() - { - return floatNullArray.Sum(x => x / 2 ?? 0); - } + //[Benchmark] + //public float FloatNullArraySumLinqSelect() + //{ + // return floatNullArray.Sum(x => x / 2 ?? 0); + //} - [Benchmark] - public float FloatNullArraySumFastSelect() - { - return floatNullArray.SumF(x => x / 2 ?? 0); - } + //[Benchmark] + //public float FloatNullArraySumFastSelect() + //{ + // return floatNullArray.SumF(x => x / 2 ?? 0); + //} //[Benchmark] @@ -332,41 +332,41 @@ public float FloatNullArraySumFastSelect() // return doubleArray.SumF(x => x / 2); //} - [Benchmark] - public double? DoubleNullArraySumLinq() - { - return doubleNullArray.Sum(); - } + //[Benchmark] + //public double? DoubleNullArraySumLinq() + //{ + // return doubleNullArray.Sum(); + //} - [Benchmark] - public double? DoubleNullArraySumFast() - { - return doubleNullArray.SumF(); - } + //[Benchmark] + //public double? DoubleNullArraySumFast() + //{ + // return doubleNullArray.SumF(); + //} - [Benchmark] - public double? DoubleNullArraySumLinqSelect() - { - return doubleNullArray.Sum(x => x / 2 ?? 0); - } + //[Benchmark] + //public double? DoubleNullArraySumLinqSelect() + //{ + // return doubleNullArray.Sum(x => x / 2 ?? 0); + //} - [Benchmark] - public double? DoubleNullArraySumFastSelect() - { - return doubleNullArray.SumF(x => x / 2 ?? 0); - } + //[Benchmark] + //public double? DoubleNullArraySumFastSelect() + //{ + // return doubleNullArray.SumF(x => x / 2 ?? 0); + //} - [Benchmark] - public double IntArrayAverageLinq() - { - return intArray.Average(); - } + //[Benchmark] + //public double IntArrayAverageLinq() + //{ + // return intArray.Average(); + //} - [Benchmark] - public double IntArrayAverageFast() - { - return intArray.AverageF(); - } + //[Benchmark] + //public double IntArrayAverageFast() + //{ + // return intArray.AverageF(); + //} //[Benchmark] //public double IntArrayAverageFastSIMD() @@ -375,17 +375,17 @@ public double IntArrayAverageFast() //} - [Benchmark] - public double IntListAverageLinq() - { - return intList.Average(); - } + //[Benchmark] + //public double IntListAverageLinq() + //{ + // return intList.Average(); + //} - [Benchmark] - public double IntListAverageFast() - { - return intList.AverageF(); - } + //[Benchmark] + //public double IntListAverageFast() + //{ + // return intList.AverageF(); + //} //[Benchmark] //public double IntListAverageFastSIMD() @@ -393,29 +393,29 @@ public double IntListAverageFast() // return intList.AverageS(); //} - [Benchmark] - public int IntListSumWithSelectLinq() - { - return intList.Sum(x => x / 2); - } + //[Benchmark] + //public int IntListSumWithSelectLinq() + //{ + // return intList.Sum(x => x / 2); + //} - [Benchmark] - public int IntListSumWithSelectFast() - { - return intList.SumF(x => x / 2); - } + //[Benchmark] + //public int IntListSumWithSelectFast() + //{ + // return intList.SumF(x => x / 2); + //} - [Benchmark] - public double IntReadOnlyListSumWithSelectLinq() - { - return intList.AsReadOnly().Sum(x => x / 2); - } + //[Benchmark] + //public double IntReadOnlyListSumWithSelectLinq() + //{ + // return intList.AsReadOnly().Sum(x => x / 2); + //} - [Benchmark] - public double IntReadOnlyListSumWithSelectFast() - { - return intList.AsReadOnly().SumF(x => x / 2); - } + //[Benchmark] + //public double IntReadOnlyListSumWithSelectFast() + //{ + // return intList.AsReadOnly().SumF(x => x / 2); + //} //private static readonly Func mulXInts = (acc, x) => acc += x * x; @@ -581,6 +581,89 @@ public double IntReadOnlyListSumWithSelectFast() // return Array.AsReadOnly(intArray).FirstF(firstInts); //} + private static readonly Func LastInts = (x) => x > 0; + + [Benchmark] + public double IntArrayLastLinq() + { + return intArray.Last(LastInts); + } + + [Benchmark] + public double IntArrayLastFast() + { + return intArray.LastF(LastInts); + } + + [Benchmark] + public double IntArrayLastFast1() + { + Predicate predicate = new Predicate(LastInts); + return Array.Find(intArray, predicate); + } + + + [Benchmark] + public double IntSpanLastForEach() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + foreach (int i in asSpan) + { + if (LastInts(i)) + { + return i; + } + } + + return 0; + } + + [Benchmark] + public double IntSpanLastFast() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.LastF(LastInts); + } + + [Benchmark] + public double IntListLastLinq() + { + return intList.Last(LastInts); + } + + [Benchmark] + public double IntListLastFast() + { + return intList.LastF(LastInts); + } + + [Benchmark] + public double IntAsListReadOnlyLastLinq() + { + return intList.AsReadOnly().Last(LastInts); + } + + [Benchmark] + public double IntAsListReadOnlyLastFast() + { + return intList.AsReadOnly().LastF(LastInts); + } + + [Benchmark] + public double IntArrayAsReadOnlyLastLinq() + { + return Array.AsReadOnly(intArray).Last(LastInts); + } + + [Benchmark] + public double IntArrayAsReadOnlyLastFast() + { + return Array.AsReadOnly(intArray).LastF(LastInts); + } + + //[Benchmark] //public double IntArrayWhereAggregateLinq() //{ diff --git a/LinqFaster/First.cs b/LinqFaster/First.cs index 9153d37..95383b2 100644 --- a/LinqFaster/First.cs +++ b/LinqFaster/First.cs @@ -9,7 +9,6 @@ namespace JM.LinqFaster { public static partial class LinqFaster { - // -------------------------- Arrays -------------------------------------------- /// @@ -68,6 +67,7 @@ public static T FirstF(this T[] source, Func predicate) /// The array to return the first element of. /// default value if source is empty, otherwise, the first element /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T FirstOrDefaultF(this T[] source) { if (source == null) diff --git a/LinqFaster/Last.cs b/LinqFaster/Last.cs index d6072e6..abe3632 100644 --- a/LinqFaster/Last.cs +++ b/LinqFaster/Last.cs @@ -1,5 +1,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Runtime.CompilerServices; + +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global namespace JM.LinqFaster { @@ -12,11 +17,12 @@ public static partial class LinqFaster /// /// An sequence to return the last element of. /// The value at the last position in the source sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T LastF(this T[] source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -31,24 +37,27 @@ public static T LastF(this T[] source) /// A sequence to return an element from. /// A function to test each element for a condition. /// - public static T LastF(this T[] source, Predicate predicate) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); } - var lastIndex = Array.FindLastIndex(source, predicate); - - if (lastIndex == -1) - throw Error.NoMatch(); - else - return source[lastIndex]; + for (int i = source.Length - 1; i >= 0; i--) + { + if (predicate(source[i])) + { + return source[i]; + } + } + throw Error.NoMatch(); } /// @@ -57,11 +66,12 @@ public static T LastF(this T[] source, Predicate predicate) /// An sequence to return the last element of. /// default value if the source sequence is empty; otherwise, /// the last element in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T LastOrDefaultF(this T[] source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -78,134 +88,155 @@ public static T LastOrDefaultF(this T[] source) /// default value if the sequence is empty or if no elements pass the test /// in the predicate function; otherwise, the last element that passes the test in the /// predicate function. - public static T LastOrDefaultF(this T[] source, Predicate predicate) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); } - var lastIndex = Array.FindLastIndex(source, predicate); - - if (lastIndex == -1) - return default(T); - else - return source[lastIndex]; + for (int i = source.Length - 1; i >= 0; i--) + { + if (predicate(source[i])) + { + return source[i]; + } + } + return default(T); } - // -------------------------- this Spans -------------------------------------------- + /// - /// Returns the last element of a sequence. + /// Returns the first element of an Array / List / IReadOnlyList. /// - /// An sequence to return the last element of. - /// The value at the last position in the source sequence. - public static T LastF(this Span source) + /// The array to return the first element of. + /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this IReadOnlyList source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } - if (source.Length == 0) + if (source.Count == 0) { throw Error.NoElements(); } - return source[source.Length - 1]; + return source[source.Count - 1]; } /// - /// Returns the last element of a sequence that satisfies a specified condition. + /// Returns the first element in an array / List / IReadOnlyList that satisfies a specified condition. /// - /// A sequence to return an element from. + /// An IReadOnlyList to return an element from. /// A function to test each element for a condition. - /// - public static T LastF(this Span source, Predicate predicate) + /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this IReadOnlyList source, Func predicate) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); } - for (int i = source.Length - 1; i >= 0; i--) + switch (source) { - if (predicate(source[i])) return source[i]; + case null: + throw Error.ArgumentNull(nameof(source)); + case T[] sa: + return sa.LastF(predicate); + default: + for (int i = source.Count - 1; i >= 0; i--) + { + if (predicate(source[i])) + { + return source[i]; + } + } + + break; } - - throw Error.NoMatch(); + throw Error.NoMatch(); } /// - /// Returns the last element of a sequence, or a default value if the sequence contains no elements. - /// - /// An sequence to return the last element of. - /// default value if the source sequence is empty; otherwise, - /// the last element in the sequence - public static T LastOrDefaultF(this Span source) + /// Returns the first element of an array, or a default value if the + /// array contains no elements. + /// + /// The array to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this IReadOnlyList source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } - if (source.Length == 0) + if (source.Count == 0) { return default(T); } - return source[source.Length - 1]; + return source[source.Count - 1]; } /// - /// Returns the last element of a sequence that satisfies a condition or a default value if no such element is found. + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. /// - /// A sequence to return the last element of. + /// An IEnumerable to return an element from. /// A function to test each element for a condition. - /// default value if the sequence is empty or if no elements pass the test - /// in the predicate function; otherwise, the last element that passes the test in the - /// predicate function. - public static T LastOrDefaultF(this Span source, Predicate predicate) + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Pure] + public static T LastOrDefaultF(this IReadOnlyList source, Func predicate) { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); } - - for (int i = source.Length - 1; i >= 0; i--) + + switch (source) { - if (predicate(source[i])) return source[i]; + case null: + throw Error.ArgumentNull(nameof(source)); + case T[] sa: + return sa.LastOrDefaultF(predicate); + default: + for (int i = source.Count - 1; i >= 0; i--) + { + if (predicate(source[i])) + { + return source[i]; + } + } + break; } - return default(T); - } // -------------------------- Lists -------------------------------------------- /// - /// Returns the last element of a sequence. + /// Returns the first element of a list /// - /// An sequence to return the last element of. - /// The value at the last position in the source sequence. + /// The list to return the first element of. + /// The first element in the specified list. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T LastF(this List source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -215,42 +246,48 @@ public static T LastF(this List source) } /// - /// Returns the last element of a sequence that satisfies a specified condition. + /// Returns the first element in a list that satisfies a specified condition. /// - /// A sequence to return an element from. + /// An list to return an element from. /// A function to test each element for a condition. - /// + /// The first element in the list that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T LastF(this List source, Predicate predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); } - var lastIndex = source.FindLastIndex(predicate); + for (int i = source.Count - 1; i >= 0; i--) + { + if (predicate(source[i])) + { + return source[i]; + } + } - if (lastIndex == -1) - throw Error.NoMatch(); - else - return source[lastIndex]; + throw Error.NoMatch(); } /// - /// Returns the last element of a sequence, or a default value if the sequence contains no elements. - /// - /// An sequence to return the last element of. - /// default value if the source sequence is empty; otherwise, - /// the last element in the sequence + /// Returns the first element of an array, or a default value if the + /// array contains no elements. + /// + /// The array to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T LastOrDefaultF(this List source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -260,31 +297,240 @@ public static T LastOrDefaultF(this List source) } /// - /// Returns the last element of a sequence that satisfies a condition or a default value if no such element is found. + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. /// - /// A sequence to return the last element of. + /// An IEnumerable to return an element from. /// A function to test each element for a condition. - /// default value if the sequence is empty or if no elements pass the test - /// in the predicate function; otherwise, the last element that passes the test in the - /// predicate function. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T LastOrDefaultF(this List source, Predicate predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { - throw Error.ArgumentNull("predicate"); + throw Error.ArgumentNull(nameof(predicate)); } - var lastIndex = source.FindLastIndex(predicate); + for (int i = source.Count - 1; i >= 0; i--) + { + if (predicate(source[i])) + { + return source[i]; + } + } + return default(T); + } + + // -------------------------- Span -------------------------------------------- + #region Normal Span + /// + /// Returns the first element of an Span. + /// + /// The Span to return the first element of. + /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + return source[source.Length - 1]; + } + + /// + /// Returns the first element in an Span that satisfies a specified condition. + /// + /// An Span to return an element from. + /// A function to test each element for a condition. + /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this Span source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } - if (lastIndex == -1) + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + for (int i = source.Length - 1; i >= 0; i--) + { + if (func(source[i])) + { + return source[i]; + } + } + + throw Error.NoMatch(); + } + + /// + /// Returns the first element of an Span, or a default value if the + /// array contains no elements. + /// + /// The Span to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { return default(T); - else - return source[lastIndex]; + } + return source[source.Length - 1]; + } + + /// + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. + /// + /// An Span to return an element from. + /// A function to test each element for a condition. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this Span source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + for (int i = source.Length - 1; i >= 0; i--) + { + if (func(source[i])) + { + return source[i]; + } + } + + return default(T); + } + #endregion Normal Span + + #region ReadOnlySpan + /// + /// Returns the first element of an ReadOnlySpan. + /// + /// The ReadOnlySpan to return the first element of. + /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + return source[source.Length - 1]; + } + + /// + /// Returns the first element in an ReadOnlySpan that satisfies a specified condition. + /// + /// An ReadOnlySpan to return an element from. + /// A function to test each element for a condition. + /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this ReadOnlySpan source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + for (int i = source.Length - 1; i >= 0; i--) + { + if (func(source[i])) + { + return source[i]; + } + } + + throw Error.NoMatch(); + } + + /// + /// Returns the first element of an ReadOnlySpan, or a default value if the + /// array contains no elements. + /// + /// The ReadOnlySpan to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + return default(T); + } + return source[source.Length - 1]; + } + + /// + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. + /// + /// An ReadOnlySpan to return an element from. + /// A function to test each element for a condition. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this ReadOnlySpan source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + for (int i = source.Length - 1; i >= 0; i--) + { + if (func(source[i])) + { + return source[i]; + } + } + + return default(T); } + #endregion ReadOnlySpan } } diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 1cb17f9..995556c 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -793,7 +793,7 @@ An sequence to return the last element of. The value at the last position in the source sequence. - + Returns the last element of a sequence that satisfies a specified condition. @@ -809,7 +809,7 @@ default value if the source sequence is empty; otherwise, the last element in the sequence - + Returns the last element of a sequence that satisfies a condition or a default value if no such element is found. @@ -819,71 +819,137 @@ in the predicate function; otherwise, the last element that passes the test in the predicate function. - + - Returns the last element of a sequence. + Returns the first element of an Array / List / IReadOnlyList. - An sequence to return the last element of. - The value at the last position in the source sequence. + The array to return the first element of. + The first element in the specified array. - + - Returns the last element of a sequence that satisfies a specified condition. + Returns the first element in an array / List / IReadOnlyList that satisfies a specified condition. - A sequence to return an element from. + An IReadOnlyList to return an element from. A function to test each element for a condition. - + The first element that satisfies the condition. - + - Returns the last element of a sequence, or a default value if the sequence contains no elements. - - An sequence to return the last element of. - default value if the source sequence is empty; otherwise, - the last element in the sequence + Returns the first element of an array, or a default value if the + array contains no elements. + + The array to return the first element of. + default value if source is empty, otherwise, the first element + in source. - + - Returns the last element of a sequence that satisfies a condition or a default value if no such element is found. + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. - A sequence to return the last element of. + An IEnumerable to return an element from. A function to test each element for a condition. - default value if the sequence is empty or if no elements pass the test - in the predicate function; otherwise, the last element that passes the test in the - predicate function. + - Returns the last element of a sequence. + Returns the first element of a list - An sequence to return the last element of. - The value at the last position in the source sequence. + The list to return the first element of. + The first element in the specified list. - Returns the last element of a sequence that satisfies a specified condition. + Returns the first element in a list that satisfies a specified condition. - A sequence to return an element from. + An list to return an element from. A function to test each element for a condition. - + The first element in the list that satisfies the condition. - Returns the last element of a sequence, or a default value if the sequence contains no elements. - - An sequence to return the last element of. - default value if the source sequence is empty; otherwise, - the last element in the sequence + Returns the first element of an array, or a default value if the + array contains no elements. + + The array to return the first element of. + default value if source is empty, otherwise, the first element + in source. - Returns the last element of a sequence that satisfies a condition or a default value if no such element is found. + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. - A sequence to return the last element of. + An IEnumerable to return an element from. A function to test each element for a condition. - default value if the sequence is empty or if no elements pass the test - in the predicate function; otherwise, the last element that passes the test in the - predicate function. + + + + + Returns the first element of an Span. + + The Span to return the first element of. + The first element in the specified array. + + + + Returns the first element in an Span that satisfies a specified condition. + + An Span to return an element from. + A function to test each element for a condition. + The first element that satisfies the condition. + + + + Returns the first element of an Span, or a default value if the + array contains no elements. + + The Span to return the first element of. + default value if source is empty, otherwise, the first element + in source. + + + + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. + + An Span to return an element from. + A function to test each element for a condition. + + + + + Returns the first element of an ReadOnlySpan. + + The ReadOnlySpan to return the first element of. + The first element in the specified array. + + + + Returns the first element in an ReadOnlySpan that satisfies a specified condition. + + An ReadOnlySpan to return an element from. + A function to test each element for a condition. + The first element that satisfies the condition. + + + + Returns the first element of an ReadOnlySpan, or a default value if the + array contains no elements. + + The ReadOnlySpan to return the first element of. + default value if source is empty, otherwise, the first element + in source. + + + + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. + + An ReadOnlySpan to return an element from. + A function to test each element for a condition. + From 57932a129b798fa77c25c8e301f85d0702a6f64b Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Mon, 5 Aug 2019 11:19:38 +0100 Subject: [PATCH 16/30] Initial commit for #24: [Enhancement] DefaultIfEmptyF should be implemented - Add Start File --- LinqFaster/DefaultIfEmpty.cs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 LinqFaster/DefaultIfEmpty.cs diff --git a/LinqFaster/DefaultIfEmpty.cs b/LinqFaster/DefaultIfEmpty.cs new file mode 100644 index 0000000..67c4cf4 --- /dev/null +++ b/LinqFaster/DefaultIfEmpty.cs @@ -0,0 +1,29 @@ +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global + +namespace JM.LinqFaster +{ + public static partial class LinqFaster + { + // -------------------------- Arrays -------------------------------------------- + + /// + /// Returns an array (For speed) with a single value set to default{T} + /// + /// + /// + /// source or new array{1} + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T[] DefaultIfEmptyF(this T[] source) + { + if ((source == null) + || (source.Length == 0) + ) + { + return new T[] { default(T) }; + } + return source; + } + } +} From c7652e0fad6ed61a64b364be4e447693b321e797 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Tue, 6 Aug 2019 09:18:00 +0100 Subject: [PATCH 17/30] MaxF's for #15 : [Enhancement] Can these API's also work on IReadOnlyList - Use types instead of vars - Breakout Max Benchmarks - Breakout MaxF API's for different types into seperate files --- Benchmarks/Benchmarks.cs | 167 +-- Benchmarks/Benchmarks.csproj | 1 + Benchmarks/BenchmarksMax.cs | 163 +++ BenchmarksCore/Program.cs | 7 +- LinqFaster/DefaultIfEmpty.cs | 9 +- LinqFaster/Distinct.cs | 2 +- LinqFaster/Max.cs | 1166 ----------------- LinqFaster/MaxArray.cs | 480 +++++++ LinqFaster/MaxList.cs | 867 ++++++++++++ LinqFaster/MaxSpan.cs | 853 ++++++++++++ LinqFaster/Min.cs | 42 +- LinqFaster/OrderBy.cs | 16 +- LinqFaster/Range.cs | 2 +- LinqFaster/Repeat.cs | 4 +- LinqFaster/Reverse.cs | 6 +- LinqFaster/Select.cs | 12 +- LinqFaster/SelectMany.cs | 24 +- LinqFaster/SelectWhere.cs | 24 +- LinqFaster/SequenceEqual.cs | 2 +- LinqFaster/Skip.cs | 12 +- LinqFaster/Take.cs | 18 +- LinqFaster/WhereAggregate.cs | 24 +- LinqFaster/WhereSelect.cs | 12 +- LinqFaster/WhereSum.cs | 60 +- LinqFaster/Zip.cs | 12 +- LinqFasterParallel/AverageParallel.cs | 41 +- LinqFasterParallel/ContainsParallel.cs | 8 +- LinqFasterParallel/CountParallel.cs | 5 +- LinqFasterParallel/MaxParallel.cs | 81 +- LinqFasterParallel/MinParallel.cs | 81 +- LinqFasterParallel/SelectParallel.cs | 29 +- LinqFasterParallel/SelectWhereParallel.cs | 41 +- LinqFasterParallel/SequenceEqualParallel.cs | 12 +- LinqFasterParallel/SumParallel.cs | 41 +- LinqFasterParallel/WhereAggregateParallel.cs | 33 +- LinqFasterParallel/WhereParallel.cs | 13 +- LinqFasterParallel/WhereSelectParallel.cs | 25 +- LinqFasterParallelSIMD/SelectSIMDParallel.cs | 5 +- .../SequenceEqualSIMDParallel.cs | 10 +- LinqFasterParallelSIMD/SumSIMDParallel.cs | 10 +- LinqFasterSIMD/ContainsSIMD.cs | 4 +- LinqFasterSIMD/MaxSIMD.cs | 4 +- LinqFasterSIMD/MinSIMD.cs | 4 +- LinqFasterSIMD/RangeSIMD.cs | 6 +- LinqFasterSIMD/RepeatSIMD.cs | 6 +- LinqFasterSIMD/SelectSIMD.cs | 6 +- LinqFasterSIMD/SequenceEqualSIMD.cs | 18 +- LinqFasterSIMD/SumSIMD.cs | 12 +- Tests/AggregateTests.cs | 32 +- Tests/AnyAllTests.cs | 16 +- Tests/AverageTests.cs | 48 +- Tests/ContainsTests.cs | 16 +- Tests/CountTests.cs | 8 +- Tests/FirstTests.cs | 24 +- Tests/LastTests.cs | 24 +- Tests/MaxTests.cs | 6 +- Tests/OrderByTests.cs | 9 +- Tests/ParallelSIMDTests/SelectSIMDP.cs | 7 +- .../SequenceEqualsSIMDTests.cs | 12 +- Tests/ParallelSIMDTests/SumSIMDP.cs | 8 +- Tests/ParallelTests/AverageParallelTests.cs | 62 +- Tests/ParallelTests/ContainsParallelTests.cs | 16 +- Tests/ParallelTests/CountParallelTests.cs | 8 +- Tests/ParallelTests/SelectParallelTests.cs | 11 +- .../ParallelTests/SelectWhereParallelTests.cs | 11 +- Tests/ParallelTests/SequenceEqualsTests.cs | 34 +- Tests/ParallelTests/SumParallelTests.cs | 52 +- .../WhereAggregateParallelTests.cs | 20 +- Tests/ParallelTests/WhereParallelTEsts.cs | 25 +- .../ParallelTests/WhereSelectParallelTests.cs | 25 +- Tests/RangeTests.cs | 11 +- Tests/RepeatTests.cs | 11 +- Tests/ReverseTests.cs | 11 +- Tests/SIMDTests/AverageSIMDTests.cs | 12 +- Tests/SIMDTests/ContainsSIMDTests.cs | 8 +- Tests/SIMDTests/MaxSIMDTests.cs | 12 +- Tests/SIMDTests/MinSIMDTests.cs | 8 +- Tests/SIMDTests/RangeSIMDTests.cs | 7 +- Tests/SIMDTests/RepeatTests.cs | 7 +- Tests/SIMDTests/SelectSIMDTests.cs | 4 +- Tests/SIMDTests/SequenceEqualsSIMDTests.cs | 12 +- Tests/SIMDTests/SumSIMDTests.cs | 12 +- Tests/SelectManyTests.cs | 11 +- Tests/SelectTEsts.cs | 17 +- Tests/SelectWhereTests.cs | 11 +- Tests/SequenceEqualsTests.cs | 34 +- Tests/SingleTests.cs | 24 +- Tests/SkipTests.cs | 19 +- Tests/SumTests.cs | 68 +- Tests/TakeTests.cs | 21 +- Tests/WhereAggregateTests.cs | 20 +- Tests/WhereSelectTests.cs | 25 +- Tests/WhereSumTEsts.cs | 32 +- Tests/WhereTests.cs | 25 +- docs/linqfaster.xml | 240 +++- 95 files changed, 3540 insertions(+), 2076 deletions(-) create mode 100644 Benchmarks/BenchmarksMax.cs delete mode 100644 LinqFaster/Max.cs create mode 100644 LinqFaster/MaxArray.cs create mode 100644 LinqFaster/MaxList.cs create mode 100644 LinqFaster/MaxSpan.cs diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index d179406..044e03b 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using BenchmarkDotNet.Attributes; @@ -13,7 +14,7 @@ namespace Tests { [MemoryDiagnoser] - public class Benchmarks + public partial class Benchmarks { private const int LARGE_TEST_SIZE = 1000000; private const int SMALL_TEST_SIZE = 100; @@ -33,6 +34,10 @@ public class Benchmarks private double?[] doubleNullArray; private string[] strarray; + private static readonly Func mulXInts = (acc, x) => acc += x * x; + private static readonly Func firstInts = (x) => x > 0; + private static readonly Func LastInts = (x) => x > 0; + [Params(1000000)] public int TEST_SIZE { get; set; } @@ -44,7 +49,6 @@ public Benchmarks() [GlobalSetup] public void Setup() { - Random r = new Random(); byteArray = new byte[TEST_SIZE]; shortArray = new short[TEST_SIZE]; intArray = new int[TEST_SIZE]; @@ -418,7 +422,6 @@ public void Setup() //} - //private static readonly Func mulXInts = (acc, x) => acc += x * x; //[Benchmark] //public double IntArrayAggregateLinq() @@ -499,22 +502,21 @@ public void Setup() // return intList.AsReadOnly().AggregateF(0.0, mulXInts); //} - //private static readonly Func firstInts = (x) => x > 0; //[Benchmark] - //public double IntArrayFirstLinq() + //public double IntArrayFirstLinqSelector() //{ // return intArray.First(firstInts); //} //[Benchmark] - //public double IntArrayFirstFast() + //public double IntArrayFirstFastSelector() //{ // return intArray.FirstF(firstInts); //} //[Benchmark] - //public double IntArrayFirstFast1() + //public double IntArrayFirstArrayFindSelector() //{ // Predicate predicate = new Predicate(firstInts); // return Array.Find(intArray, predicate); @@ -522,7 +524,7 @@ public void Setup() //[Benchmark] - //public double IntSpanFirstForEach() + //public double IntSpanFirstForEachSelector() //{ // int[] localArray = intArray; // Span asSpan = localArray.AsSpan(); @@ -538,7 +540,7 @@ public void Setup() //} //[Benchmark] - //public double IntSpanFirstFast() + //public double IntSpanFirstFastSelector() //{ // int[] localArray = intArray; // Span asSpan = localArray.AsSpan(); @@ -546,122 +548,121 @@ public void Setup() //} //[Benchmark] - //public double IntListFirstLinq() + //public double IntListFirstLinqSelector() //{ // return intList.First(firstInts); //} //[Benchmark] - //public double IntListFirstFast() + //public double IntListFirstFastSelector() //{ // return intList.FirstF(firstInts); //} //[Benchmark] - //public double IntAsListReadOnlyFirstLinq() + //public double IntAsListReadOnlyFirstLinqSelector() //{ // return intList.AsReadOnly().First(firstInts); //} //[Benchmark] - //public double IntAsListReadOnlyFirstFast() + //public double IntAsListReadOnlyFirstFastSelector() //{ // return intList.AsReadOnly().FirstF(firstInts); //} //[Benchmark] - //public double IntArrayAsReadOnlyFirstLinq() + //public double IntArrayAsReadOnlyFirstLinqSelector() //{ // return Array.AsReadOnly(intArray).First(firstInts); //} //[Benchmark] - //public double IntArrayAsReadOnlyFirstFast() + //public double IntArrayAsReadOnlyFirstFastSelector() //{ // return Array.AsReadOnly(intArray).FirstF(firstInts); //} - private static readonly Func LastInts = (x) => x > 0; - [Benchmark] - public double IntArrayLastLinq() - { - return intArray.Last(LastInts); - } + //[Benchmark] + //public double IntArrayLastLinqSelector() + //{ + // return intArray.Last(LastInts); + //} - [Benchmark] - public double IntArrayLastFast() - { - return intArray.LastF(LastInts); - } + //[Benchmark] + //public double IntArrayLastFastSelector() + //{ + // return intArray.LastF(LastInts); + //} - [Benchmark] - public double IntArrayLastFast1() - { - Predicate predicate = new Predicate(LastInts); - return Array.Find(intArray, predicate); - } + //[Benchmark] + //public double IntArrayLastArrayFindSelector() + //{ + // Predicate predicate = new Predicate(LastInts); + // return Array.Find(intArray, predicate); + //} - [Benchmark] - public double IntSpanLastForEach() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - foreach (int i in asSpan) - { - if (LastInts(i)) - { - return i; - } - } + //[Benchmark] + //public double IntSpanLastForEachSelector() + //{ + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // foreach (int i in asSpan) + // { + // if (LastInts(i)) + // { + // return i; + // } + // } - return 0; - } + // return 0; + //} - [Benchmark] - public double IntSpanLastFast() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - return asSpan.LastF(LastInts); - } + //[Benchmark] + //public double IntSpanLastFastSelector() + //{ + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // return asSpan.LastF(LastInts); + //} - [Benchmark] - public double IntListLastLinq() - { - return intList.Last(LastInts); - } + //[Benchmark] + //public double IntListLastLinqSelector() + //{ + // return intList.Last(LastInts); + //} - [Benchmark] - public double IntListLastFast() - { - return intList.LastF(LastInts); - } + //[Benchmark] + //public double IntListLastFastSelector() + //{ + // return intList.LastF(LastInts); + //} - [Benchmark] - public double IntAsListReadOnlyLastLinq() - { - return intList.AsReadOnly().Last(LastInts); - } + //[Benchmark] + //public double IntAsListReadOnlyLastLinqSelector() + //{ + // return intList.AsReadOnly().Last(LastInts); + //} - [Benchmark] - public double IntAsListReadOnlyLastFast() - { - return intList.AsReadOnly().LastF(LastInts); - } + //[Benchmark] + //public double IntAsListReadOnlyLastFastSelector() + //{ + // return intList.AsReadOnly().LastF(LastInts); + //} - [Benchmark] - public double IntArrayAsReadOnlyLastLinq() - { - return Array.AsReadOnly(intArray).Last(LastInts); - } + //[Benchmark] + //public double IntArrayAsReadOnlyLastLinqSelector() + //{ + // return Array.AsReadOnly(intArray).Last(LastInts); + //} - [Benchmark] - public double IntArrayAsReadOnlyLastFast() - { - return Array.AsReadOnly(intArray).LastF(LastInts); - } + //[Benchmark] + //public double IntArrayAsReadOnlyLastFastSelector() + //{ + // return Array.AsReadOnly(intArray).LastF(LastInts); + //} //[Benchmark] diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 4de8578..173aa9f 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -199,6 +199,7 @@ + diff --git a/Benchmarks/BenchmarksMax.cs b/Benchmarks/BenchmarksMax.cs new file mode 100644 index 0000000..7d34f7e --- /dev/null +++ b/Benchmarks/BenchmarksMax.cs @@ -0,0 +1,163 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; + +namespace Tests +{ + public partial class Benchmarks + { + private static readonly Func MaxInts = (x) => x + 1; + + [Benchmark] + public double IntArrayMaxLinq() + { + return intArray.Max(); + } + + [Benchmark] + public double IntArrayMaxFast() + { + return intArray.MaxF(); + } + + [Benchmark] + public double IntSpanMaxForEach() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + int max = int.MinValue; + foreach (int i in asSpan) + { + if (max > i) + { + max = i; + } + } + + return max; + } + + [Benchmark] + public double IntSpanMaxFast() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.MaxF(); + } + + [Benchmark] + public double IntListMaxLinq() + { + return intList.Max(); + } + + [Benchmark] + public double IntListMaxFast() + { + return intList.MaxF(); + } + + [Benchmark] + public double IntAsListReadOnlyMaxLinq() + { + return intList.AsReadOnly().Max(); + } + + [Benchmark] + public double IntAsListReadOnlyMaxFast() + { + return intList.AsReadOnly().MaxF(); + } + + [Benchmark] + public double IntArrayAsReadOnlyMaxLinq() + { + return Array.AsReadOnly(intArray).Max(); + } + + [Benchmark] + public double IntArrayAsReadOnlyMaxFast() + { + return Array.AsReadOnly(intArray).MaxF(); + } + + + [Benchmark] + public double IntArrayMaxLinqSelector() + { + return intArray.Max(MaxInts); + } + + [Benchmark] + public double IntArrayMaxFastSelector() + { + return intArray.MaxF(MaxInts); + } + + [Benchmark] + public double IntSpanMaxForEachSelector() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + int max = int.MinValue; + foreach (int i in asSpan) + { + int l = MaxInts(i); + if (max > l) + { + max = l; + } + } + + return max; + } + + [Benchmark] + public double IntSpanMaxFastSelector() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.MaxF(MaxInts); + } + + [Benchmark] + public double IntListMaxLinqSelector() + { + return intList.Max(MaxInts); + } + + [Benchmark] + public double IntListMaxFastSelector() + { + return intList.MaxF(MaxInts); + } + + [Benchmark] + public double IntAsListReadOnlyMaxLinqSelector() + { + return intList.AsReadOnly().Max(MaxInts); + } + + [Benchmark] + public double IntAsListReadOnlyMaxFastSelector() + { + return intList.AsReadOnly().MaxF(MaxInts); + } + + [Benchmark] + public double IntArrayAsReadOnlyMaxLinqSelector() + { + return Array.AsReadOnly(intArray).Max(MaxInts); + } + + [Benchmark] + public double IntArrayAsReadOnlyMaxFastSelector() + { + return Array.AsReadOnly(intArray).MaxF(MaxInts); + } + + } +} diff --git a/BenchmarksCore/Program.cs b/BenchmarksCore/Program.cs index 2da9cd1..3bae77b 100644 --- a/BenchmarksCore/Program.cs +++ b/BenchmarksCore/Program.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using BenchmarkDotNet.Configs; using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Reports; namespace Tests { @@ -236,14 +237,14 @@ public static void Main(string[] args) { int[] a = { 1, 2, 3, 4, 5, 6, 7, 8 }; int[] b = { 1, 0, 4, 4, 6, 7, 2, 10 }; - var r = a.SequenceCompareS(b); + int[] r = a.SequenceCompareS(b); a.Slice(2, 4).SumF(); - foreach (var i in r) + foreach (int i in r) { Console.Write(i + ","); } - var summary = BenchmarkRunner.Run(ManualConfig.Create(DefaultConfig.Instance).With(Job.RyuJitX64)); + Summary summary = BenchmarkRunner.Run(ManualConfig.Create(DefaultConfig.Instance).With(Job.RyuJitX64)); Console.ReadLine(); } diff --git a/LinqFaster/DefaultIfEmpty.cs b/LinqFaster/DefaultIfEmpty.cs index 67c4cf4..395d330 100644 --- a/LinqFaster/DefaultIfEmpty.cs +++ b/LinqFaster/DefaultIfEmpty.cs @@ -4,12 +4,19 @@ namespace JM.LinqFaster { + // LINQ's DefaultIfEmpty-method checks if the sequence is empty. + // If that is the case, it will return a singleton sequence: + // A sequence containing exactly one element. + // This one element has the default value of the sequence's type. + // If the sequence does contain elements, the DefaultIfEmpty-method will + // simply return the sequence itself. + // Note: DefaultIfEmpty also has an overload that takes a user-provided default value public static partial class LinqFaster { // -------------------------- Arrays -------------------------------------------- /// - /// Returns an array (For speed) with a single value set to default{T} + /// Returns source or (if needed) an array (For speed) with a single value set to default{T} /// /// /// diff --git a/LinqFaster/Distinct.cs b/LinqFaster/Distinct.cs index d20f426..c4bd673 100644 --- a/LinqFaster/Distinct.cs +++ b/LinqFaster/Distinct.cs @@ -40,7 +40,7 @@ public static void DistinctInPlaceF(this List source, IEqualit int pos = 1; for (int i = 1; i < source.Count; i++) { - var newV = source[i]; + TSource newV = source[i]; source[pos] = newV; if (!eqComparer.Equals(newV, oldV)) { diff --git a/LinqFaster/Max.cs b/LinqFaster/Max.cs deleted file mode 100644 index c2298f5..0000000 --- a/LinqFaster/Max.cs +++ /dev/null @@ -1,1166 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace JM.LinqFaster -{ - //int, long, float,double, decimal - public static partial class LinqFaster - { - // -------------------------- ARRAYS -------------------------------------------- - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static T MaxF(this T[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - T r = default(T); - if (r == null) - { - r = source[0]; - for (int i = 1; i < source.Length; i++) - { - if (source[i] != null && comparer.Compare(source[i], r) > 0) r = source[i]; - } - } - else - { - r = source[0]; - for (int i = 1; i < source.Length; i++) - { - if (comparer.Compare(source[i], r) > 0) r = source[i]; - } - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static TResult MaxF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (selector == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - TResult r = default(TResult); - if (r == null) - { - r = selector(source[0]); - for (int i = 1; i < source.Length; i++) - { - var v = selector(source[i]); - if (v != null && comparer.Compare(v, r) > 0) r = v; - } - } - else - { - r = selector(source[0]); - for (int i = 1; i < source.Length; i++) - { - var v = selector(source[i]); - if (comparer.Compare(v, r) > 0) r = v; - } - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static int MaxF(this int[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - int r = int.MinValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static int MaxF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - int r = int.MinValue; - for (int i = 0; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static long MaxF(this long[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - long r = long.MinValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static long MaxF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long r = long.MinValue; - for (int i = 0; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static float MaxF(this float[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - float r = source[0]; - int startIndex = 0; - for (; startIndex < source.Length; startIndex++) - { - if (!float.IsNaN(source[startIndex])) - { - r = source[startIndex]; - break; - } - } - for (int i = startIndex; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static float MaxF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - float r = selector(source[0]); - int startIndex = 0; - for (; startIndex < source.Length; startIndex++) - { - var v = selector(source[startIndex]); - if (!float.IsNaN(v)) - { - r = v; - break; - } - } - for (int i = startIndex; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static double MaxF(this double[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - double r = source[0]; - int startIndex = 0; - for (; startIndex < source.Length; startIndex++) - { - if (!double.IsNaN(source[startIndex])) - { - r = source[startIndex]; - break; - } - } - for (int i = startIndex; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static double MaxF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double r = selector(source[0]); - int startIndex = 0; - for (; startIndex < source.Length; startIndex++) - { - var v = selector(source[startIndex]); - if (!double.IsNaN(v)) - { - r = v; - break; - } - } - for (int i = startIndex; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static decimal MaxF(this decimal[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - decimal r = decimal.MinValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static decimal MaxF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - decimal r = decimal.MinValue; - for (int i = 0; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - // -------------------------- this Spans -------------------------------------------- - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static T MaxF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - T r = default(T); - if (r == null) - { - r = source[0]; - for (int i = 1; i < source.Length; i++) - { - if (source[i] != null && comparer.Compare(source[i], r) > 0) r = source[i]; - } - } - else - { - r = source[0]; - for (int i = 1; i < source.Length; i++) - { - if (comparer.Compare(source[i], r) > 0) r = source[i]; - } - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static TResult MaxF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (selector == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - TResult r = default(TResult); - if (r == null) - { - r = selector(source[0]); - for (int i = 1; i < source.Length; i++) - { - var v = selector(source[i]); - if (v != null && comparer.Compare(v, r) > 0) r = v; - } - } - else - { - r = selector(source[0]); - for (int i = 1; i < source.Length; i++) - { - var v = selector(source[i]); - if (comparer.Compare(v, r) > 0) r = v; - } - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static int MaxF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - int r = int.MinValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static int MaxF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - int r = int.MinValue; - for (int i = 0; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static long MaxF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - long r = long.MinValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static long MaxF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long r = long.MinValue; - for (int i = 0; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static float MaxF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - float r = source[0]; - int startIndex = 0; - for (; startIndex < source.Length; startIndex++) - { - if (!float.IsNaN(source[startIndex])) - { - r = source[startIndex]; - break; - } - } - for (int i = startIndex; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static float MaxF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - float r = selector(source[0]); - int startIndex = 0; - for (; startIndex < source.Length; startIndex++) - { - var v = selector(source[startIndex]); - if (!float.IsNaN(v)) - { - r = v; - break; - } - } - for (int i = startIndex; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static double MaxF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - double r = source[0]; - int startIndex = 0; - for (; startIndex < source.Length; startIndex++) - { - if (!double.IsNaN(source[startIndex])) - { - r = source[startIndex]; - break; - } - } - for (int i = startIndex; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static double MaxF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double r = selector(source[0]); - int startIndex = 0; - for (; startIndex < source.Length; startIndex++) - { - var v = selector(source[startIndex]); - if (!double.IsNaN(v)) - { - r = v; - break; - } - } - for (int i = startIndex; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static decimal MaxF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - decimal r = decimal.MinValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static decimal MaxF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - decimal r = decimal.MinValue; - for (int i = 0; i < source.Length; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - // -------------------------- LISTS -------------------------------------------- - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static T MaxF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - T r = default(T); - if (r == null) - { - r = source[0]; - for (int i = 1; i < source.Count; i++) - { - if (source[i] != null && comparer.Compare(source[i], r) > 0) r = source[i]; - } - } - else - { - r = source[0]; - for (int i = 1; i < source.Count; i++) - { - if (comparer.Compare(source[i], r) > 0) r = source[i]; - } - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static TResult MaxF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - TResult r = default(TResult); - if (r == null) - { - r = selector(source[0]); - for (int i = 1; i < source.Count; i++) - { - var v = selector(source[i]); - if (v != null && comparer.Compare(v, r) > 0) r = v; - } - } - else - { - r = selector(source[0]); - for (int i = 1; i < source.Count; i++) - { - var v = selector(source[i]); - if (comparer.Compare(v, r) > 0) r = v; - } - } - return r; - } - - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static int MaxF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - int r = int.MinValue; - for (int i = 0; i < source.Count; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static int MaxF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - int r = int.MinValue; - for (int i = 0; i < source.Count; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static long MaxF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - long r = long.MinValue; - for (int i = 0; i < source.Count; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static long MaxF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("source"); - } - long r = long.MinValue; - for (int i = 0; i < source.Count; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static float MaxF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - float r = source[0]; - int startIndex = 0; - for (; startIndex < source.Count; startIndex++) - { - if (!float.IsNaN(source[startIndex])) - { - r = source[startIndex]; - break; - } - } - for (int i = startIndex; i < source.Count; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static float MaxF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - float r = selector(source[0]); - int startIndex = 0; - for (; startIndex < source.Count; startIndex++) - { - var v = selector(source[startIndex]); - if (!float.IsNaN(v)) - { - r = v; - break; - } - } - for (int i = startIndex; i < source.Count; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static double MaxF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - double r = source[0]; - int startIndex = 0; - for (; startIndex < source.Count; startIndex++) - { - if (!double.IsNaN(source[startIndex])) - { - r = source[startIndex]; - break; - } - } - for (int i = startIndex; i < source.Count; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static double MaxF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - double r = selector(source[0]); - int startIndex = 0; - for (; startIndex < source.Count; startIndex++) - { - var v = selector(source[startIndex]); - if (!double.IsNaN(v)) - { - r = v; - break; - } - } - for (int i = startIndex; i < source.Count; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - /// - /// Returns the maximum value in a sequence of values. - /// - /// A sequence of values to determine the maximum of. - /// The maximum value in the sequence - public static decimal MaxF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - decimal r = decimal.MinValue; - for (int i = 0; i < source.Count; i++) - { - if (source[i] > r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static decimal MaxF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - decimal r = decimal.MinValue; - for (int i = 0; i < source.Count; i++) - { - var v = selector(source[i]); - if (v > r) r = v; - } - return r; - } - - - } -} diff --git a/LinqFaster/MaxArray.cs b/LinqFaster/MaxArray.cs new file mode 100644 index 0000000..3632288 --- /dev/null +++ b/LinqFaster/MaxArray.cs @@ -0,0 +1,480 @@ +using System; +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global +// ReSharper disable LoopCanBeConvertedToQuery + +namespace JM.LinqFaster +{ + // Common types optimised: int, long, float, double, decimal + // Other types will be handled via the templates which are approx 2 time longer than + // the above optimised base types + public static partial class LinqFaster + { + // Note: although there is a lot of shared code in the following + // comparers, we do not incorporate it into a base class for perf + // reasons. Adding another base class (even one with no fields) + // means another generic instantiation, which can be costly esp. + // for value types. + + // -------------------------- ARRAYS -------------------------------------------- + // + // It has been found that by starting the sequence _always_ at zero, then the for loop is optimsed even more ! + // + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MaxF(this T[] source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + T r = source[0]; + if (default(T) == null) + { + for (int i = 0; i < source.Length; i++) + { + T item = source[i]; + if ((item != null) + && ((r == null) + || (item.CompareTo(r) > 0) + ) + ) + { + r = item; + } + } + } + else + { + for (int i = 0; i < source.Length; i++) + { + if (source[i].CompareTo(r) > 0) + { + r = source[i]; + } + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MaxF(this T[] source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(T) == null) + { + for (int i = 0; i < source.Length; i++) + { + TResult item = selector(source[i]); + if ((item != null) + && ((r == null) + || (item.CompareTo(r) > 0) + ) + ) + { + r = item; + } + } + } + else + { + for (int i = 0; i < source.Length; i++) + { + TResult v = selector(source[i]); + if (v.CompareTo(r) > 0) + { + r = v; + } + } + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + /// + /// This is faster than the templated functions above. + /// Probably because the comparator function os only run once and there is not stack invloved + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this int[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 0; i < source.Length; i++) + { + if (source[i] > r) + { + r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + /// + /// This is faster than the templated functions above. + /// Probably because the comparator function os only run once and there is not stack invloved + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + int r = selector(source[0]); + for (int i = 0; i < source.Length; i++) + { + int v = selector(source[i]); + if (v > r) + { + r = v; + } + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + /// + /// This is faster than the templated functions above. + /// Probably because the comparator function os only run once and there is not stack invloved + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this long[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 0; i < source.Length; i++) + { + if (source[i] > r) + { + r = source[i]; + } + } + return r; + } + + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + /// + /// This is faster than the templated functions above. + /// Probably because the comparator function os only run once and there is not stack invloved + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + long r = selector(source[0]); + for (int i = 0; i < source.Length; i++) + { + long v = selector(source[i]); + if (v > r) + { + r = v; + } + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + /// + /// Special case to deal with NAN's + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this float[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] > r) r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + /// + /// Special case to deal with NAN's + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + float v = selector(source[i]); + if (v > r) r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + /// + /// Special case to deal with NAN's + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this double[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] > r) r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + /// + /// Special case to deal with NAN's + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + double v = selector(source[startIndex]); + if (double.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + double v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this decimal[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 0; i < source.Length; i++) + { + if (source[i] > r) + { + r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + decimal r = selector(source[0]); + for (int i = 0; i < source.Length; i++) + { + decimal v = selector(source[i]); + if (v > r) + { + r = v; + } + } + return r; + } + + + } +} diff --git a/LinqFaster/MaxList.cs b/LinqFaster/MaxList.cs new file mode 100644 index 0000000..e0c04a9 --- /dev/null +++ b/LinqFaster/MaxList.cs @@ -0,0 +1,867 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global +// ReSharper disable LoopCanBeConvertedToQuery + +namespace JM.LinqFaster +{ + // Common types optimised: int, long, float, double, decimal + // Other types will be handled via the templates which are approx 2 time longer than + // the above optimised base types + public static partial class LinqFaster + { + // Note: although there is a lot of shared code in the following + // comparers, we do not incorporate it into a base class for perf + // reasons. Adding another base class (even one with no fields) + // means another generic instantiation, which can be costly esp. + // for value types. + + // -------------------------- LISTS -------------------------------------------- + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MaxF(this List source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + + T r = source[0]; + if (default(T) == null) + { + for (int i = 1; i < sourceCount; i++) + { + T item = source[i]; + if (item != null + && item.CompareTo(r) > 0) + r = item; + } + } + else + { + for (int i = 1; i < sourceCount; i++) + { + T item = source[i]; + if (item.CompareTo(r) > 0) + r = item; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MaxF(this List source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(TResult) == null) + { + for (int i = 1; i < sourceCount; i++) + { + TResult item = selector(source[i]); + if (item != null + && item.CompareTo(r) > 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < sourceCount; i++) + { + TResult item = selector(source[i]); + if (item.CompareTo(r) > 0) + r = item; + } + } + return r; + } + + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] > r) r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + int r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + int v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(source)); + } + long r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + long v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + float v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + double v = selector(source[startIndex]); + if (double.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + double v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + decimal r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + decimal v = selector(source[i]); + if (v > r) r = v; + } + return r; + } + + // -------------------------- IReadOnlyList -------------------------------------------- + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MaxF(this IReadOnlyList source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + + T r = source[0]; + if (default(T) == null) + { + for (int i = 1; i < sourceCount; i++) + { + T item = source[i]; + if (item != null + && item.CompareTo(r) > 0) + r = item; + } + } + else + { + for (int i = 1; i < sourceCount; i++) + { + T item = source[i]; + if (item.CompareTo(r) > 0) + r = item; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MaxF(this IReadOnlyList source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(TResult) == null) + { + for (int i = 1; i < sourceCount; i++) + { + TResult item = selector(source[i]); + if (item != null + && item.CompareTo(r) > 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < sourceCount; i++) + { + TResult item = selector(source[i]); + if (item.CompareTo(r) > 0) + r = item; + } + } + return r; + } + + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] > r) r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + int r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + int v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(source)); + } + long r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + long v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + float v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + double v = selector(source[startIndex]); + if (double.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + double v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + decimal r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + decimal v = selector(source[i]); + if (v > r) r = v; + } + return r; + } + + + } +} diff --git a/LinqFaster/MaxSpan.cs b/LinqFaster/MaxSpan.cs new file mode 100644 index 0000000..a7c8e11 --- /dev/null +++ b/LinqFaster/MaxSpan.cs @@ -0,0 +1,853 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global +// ReSharper disable LoopCanBeConvertedToQuery + +namespace JM.LinqFaster +{ + // Common types optimised: int, long, float, double, decimal + // Other types will be handled via the templates which are approx 2 time longer than + // the above optimised base types + public static partial class LinqFaster + { + // Note: although there is a lot of shared code in the following + // comparers, we do not incorporate it into a base class for perf + // reasons. Adding another base class (even one with no fields) + // means another generic instantiation, which can be costly esp. + // for value types. + + // -------------------------- this Spans -------------------------------------------- + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MaxF(this Span source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + Comparer comparer = Comparer.Default; + T r = source[0]; + if (default(T) == null) + { + for (int i = 1; i < source.Length; i++) + { + T item = source[i]; + if (item != null + && item.CompareTo(r) > 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < source.Length; i++) + { + if (comparer.Compare(source[i], r) > 0) r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MaxF(this Span source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(TResult) == null) + { + for (int i = 1; i < source.Length; i++) + { + TResult item = selector(source[i]); + if (item != null + && item.CompareTo(r) > 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < source.Length; i++) + { + TResult item = selector(source[i]); + if (item.CompareTo(r) > 0) + { + r = item; + } + + } + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] > r) + { + r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + int r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + int v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + long r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + long v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + float v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + double v = selector(source[startIndex]); + if (!double.IsNaN(v)) + { + r = v; + break; + } + } + for (int i = startIndex; i < source.Length; i++) + { + double v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + decimal r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + decimal v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + // -------------------------- ReadOnlySpans -------------------------------------------- + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MaxF(this ReadOnlySpan source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + Comparer comparer = Comparer.Default; + T r = source[0]; + if (default(T) == null) + { + for (int i = 1; i < source.Length; i++) + { + T item = source[i]; + if (item != null + && item.CompareTo(r) > 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < source.Length; i++) + { + if (comparer.Compare(source[i], r) > 0) r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MaxF(this ReadOnlySpan source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(TResult) == null) + { + for (int i = 1; i < source.Length; i++) + { + TResult item = selector(source[i]); + if (item != null + && item.CompareTo(r) > 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < source.Length; i++) + { + TResult item = selector(source[i]); + if (item.CompareTo(r) > 0) + { + r = item; + } + + } + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] > r) + { + r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MaxF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + int r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + int v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MaxF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + long r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + long v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MaxF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + float v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + double v = selector(source[startIndex]); + if (!double.IsNaN(v)) + { + r = v; + break; + } + } + for (int i = startIndex; i < source.Length; i++) + { + double v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + + /// + /// Returns the maximum value in a sequence of values. + /// + /// A sequence of values to determine the maximum of. + /// The maximum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] > r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the maximum value. + /// + /// A sequence of values to determine the maximum value of. + /// A transform function to apply to each element. + /// The maximum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MaxF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull("selector"); + } + decimal r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + decimal v = selector(source[i]); + if (v > r) + r = v; + } + return r; + } + + + } +} \ No newline at end of file diff --git a/LinqFaster/Min.cs b/LinqFaster/Min.cs index f641652..258ad6d 100644 --- a/LinqFaster/Min.cs +++ b/LinqFaster/Min.cs @@ -74,7 +74,7 @@ public static T MinF(this T[] source) r = selector(source[0]); for (int i = 1; i < source.Length; i++) { - var v = selector(source[i]); + TResult v = selector(source[i]); if (v != null && comparer.Compare(v, r) < 0) r = v; } } @@ -83,7 +83,7 @@ public static T MinF(this T[] source) r = selector(source[0]); for (int i = 1; i < source.Length; i++) { - var v = selector(source[i]); + TResult v = selector(source[i]); if (comparer.Compare(v, r) < 0) r = v; } } @@ -137,7 +137,7 @@ public static int MinF(this T[] source, Func selector) int r = int.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + int v = selector(source[i]); if (v < r) r = v; } return r; @@ -190,7 +190,7 @@ public static long MinF(this T[] source, Func selector) long r = long.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + long v = selector(source[i]); if (v < r) r = v; } return r; @@ -244,7 +244,7 @@ public static float MinF(this T[] source, Func selector) float r = float.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + float v = selector(source[i]); if (v < r) r = v; else if (float.IsNaN(v)) return v; @@ -300,7 +300,7 @@ public static double MinF(this T[] source, Func selector) double r = double.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + double v = selector(source[i]); if (v < r) r = v; else if (double.IsNaN(v)) return v; @@ -353,7 +353,7 @@ public static decimal MinF(this T[] source, Func selector) decimal r = decimal.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + decimal v = selector(source[i]); if (v < r) r = v; } return r; @@ -426,7 +426,7 @@ public static T MinF(this Span source) r = selector(source[0]); for (int i = 1; i < source.Length; i++) { - var v = selector(source[i]); + TResult v = selector(source[i]); if (v != null && comparer.Compare(v, r) < 0) r = v; } } @@ -435,7 +435,7 @@ public static T MinF(this Span source) r = selector(source[0]); for (int i = 1; i < source.Length; i++) { - var v = selector(source[i]); + TResult v = selector(source[i]); if (comparer.Compare(v, r) < 0) r = v; } } @@ -489,7 +489,7 @@ public static int MinF(this Span source, Func selector) int r = int.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + int v = selector(source[i]); if (v < r) r = v; } return r; @@ -542,7 +542,7 @@ public static long MinF(this Span source, Func selector) long r = long.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + long v = selector(source[i]); if (v < r) r = v; } return r; @@ -596,7 +596,7 @@ public static float MinF(this Span source, Func selector) float r = float.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + float v = selector(source[i]); if (v < r) r = v; else if (float.IsNaN(v)) return v; @@ -652,7 +652,7 @@ public static double MinF(this Span source, Func selector) double r = double.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + double v = selector(source[i]); if (v < r) r = v; else if (double.IsNaN(v)) return v; @@ -705,7 +705,7 @@ public static decimal MinF(this Span source, Func selector) decimal r = decimal.MaxValue; for (int i = 0; i < source.Length; i++) { - var v = selector(source[i]); + decimal v = selector(source[i]); if (v < r) r = v; } return r; @@ -797,7 +797,7 @@ public static int MinF(this List source, Func selector) int r = int.MaxValue; for (int i = 0; i < source.Count; i++) { - var v = selector(source[i]); + int v = selector(source[i]); if (v < r) r = v; } return r; @@ -849,7 +849,7 @@ public static long MinF(this List source, Func selector) long r = long.MaxValue; for (int i = 0; i < source.Count; i++) { - var v = selector(source[i]); + long v = selector(source[i]); if (v < r) r = v; } return r; @@ -903,7 +903,7 @@ public static float MinF(this List source, Func selector) float r = float.MaxValue; for (int i = 0; i < source.Count; i++) { - var v = selector(source[i]); + float v = selector(source[i]); if (v < r) r = v; else if (float.IsNaN(v)) return v; } @@ -958,7 +958,7 @@ public static double MinF(this List source, Func selector) double r = double.MaxValue; for (int i = 0; i < source.Count; i++) { - var v = selector(source[i]); + double v = selector(source[i]); if (v < r) r = v; else if (double.IsNaN(v)) return v; } @@ -1007,7 +1007,7 @@ public static decimal MinF(this List source, Func selector) decimal r = decimal.MaxValue; for (int i = 0; i < source.Count; i++) { - var v = selector(source[i]); + decimal v = selector(source[i]); if (v < r) r = v; } return r; @@ -1043,7 +1043,7 @@ public static decimal MinF(this List source, Func selector) r = selector(source[0]); for (int i = 1; i < source.Count; i++) { - var v = selector(source[i]); + TResult v = selector(source[i]); if (v != null && comparer.Compare(v, r) < 0) r = v; } } @@ -1052,7 +1052,7 @@ public static decimal MinF(this List source, Func selector) r = selector(source[0]); for (int i = 1; i < source.Count; i++) { - var v = selector(source[i]); + TResult v = selector(source[i]); if (comparer.Compare(v, r) < 0) r = v; } } diff --git a/LinqFaster/OrderBy.cs b/LinqFaster/OrderBy.cs index bedbb92..456c5b8 100644 --- a/LinqFaster/OrderBy.cs +++ b/LinqFaster/OrderBy.cs @@ -32,12 +32,12 @@ public static partial class LinqFaster comparer = Comparer.Default; } - var keys = new TKey[source.Length]; + TKey[] keys = new TKey[source.Length]; for (int i = 0; i < keys.Length; i++) { keys[i] = keySelector(source[i]); } - var result = (TSource[])source.Clone(); + TSource[] result = (TSource[])source.Clone(); Array.Sort(keys,result,comparer); return result; } @@ -63,11 +63,11 @@ public static partial class LinqFaster comparer = Comparer.Default; } - var keys = new TKey[source.Length]; + TKey[] keys = new TKey[source.Length]; for (int i = 0; i < keys.Length; i++) { keys[i] = keySelector(source[i]); } - var result = (TSource[])source.Clone(); + TSource[] result = (TSource[])source.Clone(); Array.Sort(keys, result, comparer.Reverse()); return result; } @@ -100,8 +100,8 @@ public static partial class LinqFaster comparer = Comparer.Default; } - var result = new List(source); - var lambdaComparer = new LambdaComparer(keySelector, comparer); + List result = new List(source); + LambdaComparer lambdaComparer = new LambdaComparer(keySelector, comparer); result.Sort(lambdaComparer); return result; } @@ -127,8 +127,8 @@ public static partial class LinqFaster comparer = Comparer.Default; } - var result = new List(source); - var lambdaComparer = new ReverseLambdaComparer(keySelector, comparer); + List result = new List(source); + ReverseLambdaComparer lambdaComparer = new ReverseLambdaComparer(keySelector, comparer); result.Sort(lambdaComparer); return result; } diff --git a/LinqFaster/Range.cs b/LinqFaster/Range.cs index 9599a3e..d168f7b 100644 --- a/LinqFaster/Range.cs +++ b/LinqFaster/Range.cs @@ -44,7 +44,7 @@ public static List RangeListF(int start, int count) } - var result = new List(count); + List result = new List(count); for (int i = 0; i < count; i++) { result.Add(i + start); diff --git a/LinqFaster/Repeat.cs b/LinqFaster/Repeat.cs index dee9339..cc5c5b3 100644 --- a/LinqFaster/Repeat.cs +++ b/LinqFaster/Repeat.cs @@ -16,7 +16,7 @@ public static partial class LinqFaster /// A sequence that contains a repeated value public static T[] RepeatArrayF(T element, int count) { - var result = new T[count]; + T[] result = new T[count]; for (int i = 0; i < result.Length; i++) { result[i] = element; @@ -34,7 +34,7 @@ public static T[] RepeatArrayF(T element, int count) /// A sequence that contains a repeated value public static List RepeatListF(T element, int count) { - var result = new List(count); + List result = new List(count); for (int i = 0; i < count; i++) { result.Add(element); diff --git a/LinqFaster/Reverse.cs b/LinqFaster/Reverse.cs index 9579283..310c931 100644 --- a/LinqFaster/Reverse.cs +++ b/LinqFaster/Reverse.cs @@ -12,7 +12,7 @@ public static partial class LinqFaster /// A sequence whose elements correspond to those of the input sequence in reverse order. public static T[] ReverseF(this T[] source) { - var result = new T[source.Length]; + T[] result = new T[source.Length]; int lenLessOne = source.Length - 1; for (int i = 0; i < result.Length; i++) { @@ -42,7 +42,7 @@ public static void ReverseInPlaceF(this T[] source) /// A sequence whose elements correspond to those of the input sequence in reverse order. public static T[] ReverseF(this Span source) { - var result = new T[source.Length]; + T[] result = new T[source.Length]; int lenLessOne = source.Length - 1; for (int i = 0; i < result.Length; i++) { @@ -66,7 +66,7 @@ public static void ReverseInPlaceF(this Span source) /// A sequence whose elements correspond to those of the input sequence in reverse order. public static List ReverseF(this List source) { - var result = new List(source.Count); + List result = new List(source.Count); for (int i = source.Count - 1; i >= 0; i--) { result.Add(source[i]); diff --git a/LinqFaster/Select.cs b/LinqFaster/Select.cs index 5a0000a..0a48abf 100644 --- a/LinqFaster/Select.cs +++ b/LinqFaster/Select.cs @@ -74,7 +74,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) throw Error.ArgumentNull("selector"); } - var r = new TResult[source.Length]; + TResult[] r = new TResult[source.Length]; for (int i = 0; i < source.Length; i++) { r[i] = selector(source[i]); @@ -101,7 +101,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) { throw Error.ArgumentNull("selector"); } - var r = new TResult[source.Length]; + TResult[] r = new TResult[source.Length]; for (int i = 0; i < source.Length; i++) { r[i] = selector(source[i], i); @@ -176,7 +176,7 @@ public static void SelectInPlaceF(this Span source, Func select throw Error.ArgumentNull("selector"); } - var r = new TResult[source.Length]; + TResult[] r = new TResult[source.Length]; for (int i = 0; i < source.Length; i++) { r[i] = selector(source[i]); @@ -203,7 +203,7 @@ public static void SelectInPlaceF(this Span source, Func select { throw Error.ArgumentNull("selector"); } - var r = new TResult[source.Length]; + TResult[] r = new TResult[source.Length]; for (int i = 0; i < source.Length; i++) { r[i] = selector(source[i], i); @@ -278,7 +278,7 @@ public static void SelectInPlaceF(this List source, Func select throw Error.ArgumentNull("selector"); } - var r = new List(source.Count); + List r = new List(source.Count); for (int i = 0; i < source.Count; i++) { @@ -307,7 +307,7 @@ public static void SelectInPlaceF(this List source, Func select throw Error.ArgumentNull("selector"); } - var r = new List(source.Count); + List r = new List(source.Count); for (int i = 0; i < source.Count; i++) { diff --git a/LinqFaster/SelectMany.cs b/LinqFaster/SelectMany.cs index 580c648..3f4a156 100644 --- a/LinqFaster/SelectMany.cs +++ b/LinqFaster/SelectMany.cs @@ -26,10 +26,10 @@ public static partial class LinqFaster throw Error.ArgumentNull("selector"); } - var result = new List(source.Length); + List result = new List(source.Length); for (int i = 0; i < source.Length; i++) { - var va = selector(source[i]); + TResult[] va = selector(source[i]); for (int j = 0; j < va.Length; j++) { result.Add(va[j]); @@ -57,10 +57,10 @@ public static partial class LinqFaster throw Error.ArgumentNull("selector"); } - var result = new List(source.Length); + List result = new List(source.Length); for (int i = 0; i < source.Length; i++) { - var va = selector(source[i], i); + TResult[] va = selector(source[i], i); for (int j = 0; j < va.Length; j++) { result.Add(va[j]); @@ -90,10 +90,10 @@ public static partial class LinqFaster throw Error.ArgumentNull("selector"); } - var result = new List(source.Length); + List result = new List(source.Length); for (int i = 0; i < source.Length; i++) { - var va = selector(source[i]); + TResult[] va = selector(source[i]); for (int j = 0; j < va.Length; j++) { result.Add(va[j]); @@ -121,10 +121,10 @@ public static partial class LinqFaster throw Error.ArgumentNull("selector"); } - var result = new List(source.Length); + List result = new List(source.Length); for (int i = 0; i < source.Length; i++) { - var va = selector(source[i], i); + TResult[] va = selector(source[i], i); for (int j = 0; j < va.Length; j++) { result.Add(va[j]); @@ -153,10 +153,10 @@ public static partial class LinqFaster throw Error.ArgumentNull("selector"); } - var result = new List(source.Count); + List result = new List(source.Count); for (int i = 0; i < source.Count; i++) { - var va = selector(source[i]); + List va = selector(source[i]); for (int j = 0; j < va.Count; j++) { result.Add(va[j]); @@ -184,10 +184,10 @@ public static partial class LinqFaster throw Error.ArgumentNull("selector"); } - var result = new List(source.Count); + List result = new List(source.Count); for (int i = 0; i < source.Count; i++) { - var va = selector(source[i], i); + List va = selector(source[i], i); for (int j = 0; j < va.Count; j++) { result.Add(va[j]); diff --git a/LinqFaster/SelectWhere.cs b/LinqFaster/SelectWhere.cs index f7aa39d..e697b04 100644 --- a/LinqFaster/SelectWhere.cs +++ b/LinqFaster/SelectWhere.cs @@ -28,11 +28,11 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var result = new TResult[source.Length]; + TResult[] result = new TResult[source.Length]; int idx = 0; for (int i = 0; i < source.Length; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (predicate(s)) { result[idx] = s; @@ -63,11 +63,11 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var result = new TResult[source.Length]; + TResult[] result = new TResult[source.Length]; int idx = 0; for (int i = 0; i < source.Length; i++) { - var s = selector(source[i], i); + TResult s = selector(source[i], i); if (predicate(s, i)) { result[idx] = s; @@ -100,11 +100,11 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var result = new TResult[source.Length]; + TResult[] result = new TResult[source.Length]; int idx = 0; for (int i = 0; i < source.Length; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (predicate(s)) { result[idx] = s; @@ -135,11 +135,11 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var result = new TResult[source.Length]; + TResult[] result = new TResult[source.Length]; int idx = 0; for (int i = 0; i < source.Length; i++) { - var s = selector(source[i], i); + TResult s = selector(source[i], i); if (predicate(s, i)) { result[idx] = s; @@ -172,10 +172,10 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var r = new List(); + List r = new List(); for (int i = 0; i < source.Count; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (predicate(s)) r.Add(s); } return r; @@ -201,10 +201,10 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var r = new List(); + List r = new List(); for (int i = 0; i < source.Count; i++) { - var s = selector(source[i], i); + TResult s = selector(source[i], i); if (predicate(s, i)) r.Add(s); } return r; diff --git a/LinqFaster/SequenceEqual.cs b/LinqFaster/SequenceEqual.cs index 5830304..ada87e1 100644 --- a/LinqFaster/SequenceEqual.cs +++ b/LinqFaster/SequenceEqual.cs @@ -70,7 +70,7 @@ public static int[] SequenceCompareF(this T[] first, T[] second, IComparer } if (first.Length != second.Length) throw Error.NotSupported(); - var result = new int[first.Length]; + int[] result = new int[first.Length]; for (int i = 0; i < first.Length; i++) { result[i] = comparer.Compare(first[i], second[i]); diff --git a/LinqFaster/Skip.cs b/LinqFaster/Skip.cs index c1ecf81..f45fb8b 100644 --- a/LinqFaster/Skip.cs +++ b/LinqFaster/Skip.cs @@ -27,7 +27,7 @@ public static T[] SkipF(this T[] source, int count) return new T[0]; } - var result = new T[source.Length - count]; + T[] result = new T[source.Length - count]; Array.Copy(source, count, result, 0, result.Length); return result; } @@ -54,7 +54,7 @@ public static T[] SkipWhileF(this T[] source, Func predicate) { if (!predicate(source[i])) break; } - var result = new T[source.Length - i]; + T[] result = new T[source.Length - i]; Array.Copy(source, i, result, 0, result.Length); return result; } @@ -82,7 +82,7 @@ public static T[] SkipF(this Span source, int count) return new T[0]; } - var result = new T[source.Length - count]; + T[] result = new T[source.Length - count]; for (int i = count; i < source.Length; i++) { result[i - count] = source[i]; @@ -112,7 +112,7 @@ public static T[] SkipWhileF(this Span source, Func predicate) { if (!predicate(source[count])) break; } - var result = new T[source.Length - count]; + T[] result = new T[source.Length - count]; for (int i = count; i < source.Length; i++) { result[i - count] = source[i]; @@ -146,7 +146,7 @@ public static List SkipF(this List source, int count) return new List(); } - var result = new List(source.Count - count); + List result = new List(source.Count - count); for (int i = count; i < source.Count; i++) { result.Add(source[i]); @@ -179,7 +179,7 @@ public static List SkipWhileF(this List source, Func predicate } } - var result = new List(source.Count - i); + List result = new List(source.Count - i); for (; i < source.Count; i++) { result.Add(source[i]); diff --git a/LinqFaster/Take.cs b/LinqFaster/Take.cs index 16847c4..7a2543a 100644 --- a/LinqFaster/Take.cs +++ b/LinqFaster/Take.cs @@ -27,7 +27,7 @@ public static T[] TakeF(this T[] source, int count) count = source.Length; } - var result = new T[count]; + T[] result = new T[count]; Array.Copy(source, 0, result, 0, count); return result; } @@ -55,7 +55,7 @@ public static T[] TakeWhileF(this T[] source, Func predicate) if (!predicate(source[count])) break; } - var result = new T[count]; + T[] result = new T[count]; Array.Copy(source, 0, result, 0, count); return result; } @@ -83,7 +83,7 @@ public static T[] TakeWhileF(this T[] source, Func predicate) if (!predicate(source[count], count)) break; } - var result = new T[count]; + T[] result = new T[count]; Array.Copy(source, 0, result, 0, count); return result; } @@ -110,7 +110,7 @@ public static T[] TakeF(this Span source, int count) count = source.Length; } - var result = new T[count]; + T[] result = new T[count]; for (int i = 0; i < result.Length; i++) { result[i] = source[i]; @@ -142,7 +142,7 @@ public static T[] TakeWhileF(this Span source, Func predicate) if (!predicate(source[count])) break; } - var result = new T[count]; + T[] result = new T[count]; for (int i = 0; i < result.Length; i++) { result[i] = source[i]; @@ -173,7 +173,7 @@ public static T[] TakeWhileF(this Span source, Func predicat if (!predicate(source[count], count)) break; } - var result = new T[count]; + T[] result = new T[count]; for (int i = 0; i < result.Length; i++) { result[i] = source[i]; @@ -205,7 +205,7 @@ public static List TakeF(this List source, int count) count = source.Count; } - var result = new List(count); + List result = new List(count); for (int i = 0; i < count; i++) { result.Add(source[i]); @@ -230,7 +230,7 @@ public static List TakeWhileF(this List source, Func predicate throw Error.ArgumentNull("predicate"); } - var result = new List(); + List result = new List(); for (int i = 0; i < source.Count; i++) { if (predicate(source[i])) @@ -263,7 +263,7 @@ public static List TakeWhileF(this List source, Func pred throw Error.ArgumentNull("predicate"); } - var result = new List(); + List result = new List(); for (int i = 0; i < source.Count; i++) { if (predicate(source[i], i)) diff --git a/LinqFaster/WhereAggregate.cs b/LinqFaster/WhereAggregate.cs index 4be7e30..b40de3a 100644 --- a/LinqFaster/WhereAggregate.cs +++ b/LinqFaster/WhereAggregate.cs @@ -31,7 +31,7 @@ public static T WhereAggregateF(this T[] source, Func predicate, Fun throw Error.ArgumentNull("func"); } - var result = default(T); + T result = default(T); int i = 0; for (; i < source.Length; i++) @@ -72,7 +72,7 @@ public static T WhereAggregateF(this T[] source, Func predicate throw Error.ArgumentNull("predicate"); } - var result = default(T); + T result = default(T); int i = 0; for (; i < source.Length; i++) @@ -120,7 +120,7 @@ public static T WhereAggregateF(this T[] source, Func predicate } TAccumulate result = seed; - foreach (var v in source) + foreach (TSource v in source) { if (predicate(v)) result = func(result, v); @@ -161,7 +161,7 @@ public static T WhereAggregateF(this T[] source, Func predicate TAccumulate result = seed; int count = 0; - foreach (var v in source) + foreach (TSource v in source) { if (predicate(v)) { result = func(result, v); @@ -196,7 +196,7 @@ public static T WhereAggregateF(this Span source, Func predicate, throw Error.ArgumentNull("func"); } - var result = default(T); + T result = default(T); int i = 0; for (; i < source.Length; i++) @@ -237,7 +237,7 @@ public static T WhereAggregateF(this Span source, Func predi throw Error.ArgumentNull("predicate"); } - var result = default(T); + T result = default(T); int i = 0; for (; i < source.Length; i++) @@ -285,7 +285,7 @@ public static T WhereAggregateF(this Span source, Func predi } TAccumulate result = seed; - foreach (var v in source) + foreach (TSource v in source) { if (predicate(v)) result = func(result, v); @@ -326,7 +326,7 @@ public static T WhereAggregateF(this Span source, Func predi TAccumulate result = seed; int count = 0; - foreach (var v in source) + foreach (TSource v in source) { if (predicate(v)) { @@ -364,7 +364,7 @@ public static T WhereAggregateF(this List source, Func predicate, throw Error.ArgumentNull("func"); } - var result = default(T); + T result = default(T); int i = 0; for (; i < source.Count; i++) @@ -405,7 +405,7 @@ public static T WhereAggregateF(this List source, Func predi throw Error.ArgumentNull("predicate"); } - var result = default(T); + T result = default(T); int i = 0; for (; i < source.Count; i++) @@ -455,7 +455,7 @@ public static T WhereAggregateF(this List source, Func predi TAccumulate result = seed; for (int i = 0; i < source.Count; i++) { - var v = source[i]; + TSource v = source[i]; if (predicate(v)) result = func(result, v); } @@ -491,7 +491,7 @@ public static T WhereAggregateF(this List source, Func predi TAccumulate result = seed; for (int i = 0; i < source.Count; i++) { - var v = source[i]; + TSource v = source[i]; if (predicate(v)) result = func(result, v); } diff --git a/LinqFaster/WhereSelect.cs b/LinqFaster/WhereSelect.cs index f744572..10e081f 100644 --- a/LinqFaster/WhereSelect.cs +++ b/LinqFaster/WhereSelect.cs @@ -33,7 +33,7 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var result = new TResult[source.Length]; + TResult[] result = new TResult[source.Length]; int idx = 0; for (int i = 0; i < source.Length; i++) { @@ -72,7 +72,7 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var result = new TResult[source.Length]; + TResult[] result = new TResult[source.Length]; int idx = 0; for (int i = 0; i < source.Length; i++) { @@ -114,7 +114,7 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var result = new TResult[source.Length]; + TResult[] result = new TResult[source.Length]; int idx = 0; for (int i = 0; i < source.Length; i++) { @@ -153,7 +153,7 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var result = new TResult[source.Length]; + TResult[] result = new TResult[source.Length]; int idx = 0; for (int i = 0; i < source.Length; i++) { @@ -194,7 +194,7 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var r = new List(); + List r = new List(); for (int i = 0; i < source.Count; i++) { if (predicate(source[i])) r.Add(selector(source[i])); @@ -227,7 +227,7 @@ public static partial class LinqFaster throw Error.ArgumentNull("predicate"); } - var r = new List(); + List r = new List(); int idx = 0; for (int i = 0; i < source.Count; i++) { diff --git a/LinqFaster/WhereSum.cs b/LinqFaster/WhereSum.cs index 832b86a..c0ed746 100644 --- a/LinqFaster/WhereSum.cs +++ b/LinqFaster/WhereSum.cs @@ -23,7 +23,7 @@ public static int WhereSumF(this int[] source, Func predicate) int sum = 0; checked { - foreach (var v in source) + foreach (int v in source) { if (predicate(v)) { @@ -56,7 +56,7 @@ public static int WhereSumF(this T[] source,Func predicate, Func predicate) long sum = 0; checked { - foreach (var v in source) + foreach (long v in source) { if (predicate(v)) { @@ -115,7 +115,7 @@ public static long WhereSumF(this T[] source,Func predicate, Func predicate) } double sum = 0; - foreach (var v in source) + foreach (float v in source) { if (predicate(v)) { @@ -171,7 +171,7 @@ public static float WhereSumF(this T[] source, Func predicate,Func predicate throw Error.ArgumentNull("source"); } double sum = 0; - foreach (var v in source) + foreach (double v in source) { if (predicate(v)) { @@ -226,7 +226,7 @@ public static double WhereSumF(this T[] source, Func predicate,Func predic } decimal sum = 0; - foreach (var v in source) + foreach (decimal v in source) { if (predicate(v)) { @@ -282,7 +282,7 @@ public static decimal WhereSumF(this T[] source,Func predicate, Func< } decimal sum = 0; - foreach (var v in source) + foreach (T v in source) { if (predicate(v)) { @@ -310,7 +310,7 @@ public static int WhereSumF(this Span source, Func predicate) int sum = 0; checked { - foreach (var v in source) + foreach (int v in source) { if (predicate(v)) { @@ -343,7 +343,7 @@ public static int WhereSumF(this Span source, Func predicate, Fun int sum = 0; checked { - foreach (var v in source) + foreach (T v in source) { if (predicate(v)) { @@ -369,7 +369,7 @@ public static long WhereSumF(this Span source, Func predicate) long sum = 0; checked { - foreach (var v in source) + foreach (long v in source) { if (predicate(v)) { @@ -402,7 +402,7 @@ public static long WhereSumF(this Span source, Func predicate, Fu long sum = 0; checked { - foreach (var v in source) + foreach (T v in source) { if (predicate(v)) { @@ -427,7 +427,7 @@ public static float WhereSumF(this Span source, Func predica } double sum = 0; - foreach (var v in source) + foreach (float v in source) { if (predicate(v)) { @@ -458,7 +458,7 @@ public static float WhereSumF(this Span source, Func predicate, F } double sum = 0; - foreach (var v in source) + foreach (T v in source) { if (predicate(v)) { @@ -482,7 +482,7 @@ public static double WhereSumF(this Span source, Func pred throw Error.ArgumentNull("source"); } double sum = 0; - foreach (var v in source) + foreach (double v in source) { if (predicate(v)) { @@ -513,7 +513,7 @@ public static double WhereSumF(this Span source, Func predicate, } double sum = 0; - foreach (var v in source) + foreach (T v in source) { if (predicate(v)) { @@ -538,7 +538,7 @@ public static decimal WhereSumF(this Span source, Func p } decimal sum = 0; - foreach (var v in source) + foreach (decimal v in source) { if (predicate(v)) { @@ -569,7 +569,7 @@ public static decimal WhereSumF(this Span source, Func predicate, } decimal sum = 0; - foreach (var v in source) + foreach (T v in source) { if (predicate(v)) { @@ -599,7 +599,7 @@ public static int WhereSumF(this List source, Func predicate) { for (int i = 0; i < source.Count; i++) { - var s = source[i]; + int s = source[i]; if (predicate(s)) { sum += s; @@ -633,7 +633,7 @@ public static int WhereSumF(this List source, Func predicate, Func { for (int i = 0; i < source.Count; i++) { - var s = source[i]; + T s = source[i]; if (predicate(s)) { sum += selector(s); @@ -660,7 +660,7 @@ public static long WhereSumF(this List source, Func predicate) { for (int i = 0; i < source.Count; i++) { - var s = source[i]; + long s = source[i]; if (predicate(s)) { sum += s; @@ -694,7 +694,7 @@ public static long WhereSumF(this List source, Func predicate, Fun { for (int i = 0; i < source.Count; i++) { - var s = source[i]; + T s = source[i]; if (predicate(s)) { sum += selector(s); @@ -720,7 +720,7 @@ public static float WhereSumF(this List source, Func predicat for (int i = 0; i < source.Count; i++) { - var s = source[i]; + float s = source[i]; if (predicate(s)) { sum += s; @@ -752,7 +752,7 @@ public static float WhereSumF(this List source, Func predicate,Fun double sum = 0; for (int i = 0; i < source.Count; i++) { - var s = source[i]; + T s = source[i]; if (predicate(s)) { sum += selector(s); @@ -777,7 +777,7 @@ public static double WhereSumF(this List source, Func predi double sum = 0; for (int i = 0; i < source.Count; i++) { - var s = source[i]; + double s = source[i]; if (predicate(s)) { sum += s; @@ -809,7 +809,7 @@ public static double WhereSumF(this List source,Func predicate, Fu double sum = 0; for (int i = 0; i < source.Count; i++) { - var s = source[i]; + T s = source[i]; if (predicate(s)) { sum += selector(s); @@ -835,7 +835,7 @@ public static decimal WhereSumF(this List source, Func pr for (int i = 0; i < source.Count; i++) { - var s = source[i]; + decimal s = source[i]; if (predicate(s)) { sum += s; @@ -867,7 +867,7 @@ public static decimal WhereSumF(this List source, Func predicate,F decimal sum = 0; for (int i = 0; i < source.Count; i++) { - var s = source[i]; + T s = source[i]; if (predicate(s)) { sum += selector(s); diff --git a/LinqFaster/Zip.cs b/LinqFaster/Zip.cs index 4f10ec1..380773a 100644 --- a/LinqFaster/Zip.cs +++ b/LinqFaster/Zip.cs @@ -31,7 +31,7 @@ public static partial class LinqFaster //maintain array bounds elision if (first.Length < second.Length) { - var result = new R[first.Length]; + R[] result = new R[first.Length]; for (int i = 0; i < first.Length; i++) { result[i] = selector(first[i], second[i]); @@ -41,7 +41,7 @@ public static partial class LinqFaster } else { - var result = new R[second.Length]; + R[] result = new R[second.Length]; for (int i = 0; i < second.Length; i++) { result[i] = selector(first[i], second[i]); @@ -76,7 +76,7 @@ public static partial class LinqFaster //maintain array bounds elision if (first.Length < second.Length) { - var result = new R[first.Length]; + R[] result = new R[first.Length]; for (int i = 0; i < first.Length; i++) { result[i] = selector(first[i], second[i]); @@ -86,7 +86,7 @@ public static partial class LinqFaster } else { - var result = new R[second.Length]; + R[] result = new R[second.Length]; for (int i = 0; i < second.Length; i++) { result[i] = selector(first[i], second[i]); @@ -121,7 +121,7 @@ public static partial class LinqFaster //maintain array bounds elision if (first.Count < second.Count) { - var result = new List(first.Count); + List result = new List(first.Count); for (int i = 0; i < first.Count; i++) { result.Add(selector(first[i], second[i])); @@ -131,7 +131,7 @@ public static partial class LinqFaster } else { - var result = new List(second.Count); + List result = new List(second.Count); for (int i = 0; i < second.Count; i++) { result.Add(selector(first[i], second[i])); diff --git a/LinqFasterParallel/AverageParallel.cs b/LinqFasterParallel/AverageParallel.cs index 4f24efe..b6a1bfd 100644 --- a/LinqFasterParallel/AverageParallel.cs +++ b/LinqFasterParallel/AverageParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using static JM.LinqFaster.Utils.CustomPartition; @@ -29,7 +30,7 @@ public static double AverageP(this int[] source, int? batchSize = null) } long sum = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -74,7 +75,7 @@ public static double AverageP(this T[] source, Func selector, int? ba } long sum = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -112,7 +113,7 @@ public static double AverageP(this long[] source, int? batchSize = null) } long sum = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -157,7 +158,7 @@ public static double AverageP(this T[] source, Func selector, int? b } long sum = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -196,7 +197,7 @@ public static float AverageP(this float[] source, int? batchSize = null) double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -240,7 +241,7 @@ public static float AverageP(this T[] source, Func selector, int? b double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -277,7 +278,7 @@ public static double AverageP(this double[] source, int? batchSize = null) double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -321,7 +322,7 @@ public static double AverageP(this T[] source, Func selector, int? double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -358,7 +359,7 @@ public static decimal AverageP(this decimal[] source, int? batchSize = null) decimal sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => (decimal)0.0, (range, s, acc) => @@ -404,7 +405,7 @@ public static decimal AverageP(this T[] source, Func selector, in decimal sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => (decimal)0.0, (range, s, acc) => @@ -442,7 +443,7 @@ public static double AverageP(this List source, int? batchSize = null) } long sum = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -487,7 +488,7 @@ public static double AverageP(this List source, Func selector, int } long sum = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -524,7 +525,7 @@ public static double AverageP(this List source, int? batchSize = null) } long sum = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -569,7 +570,7 @@ public static double AverageP(this List source, Func selector, in } long sum = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -608,7 +609,7 @@ public static double AverageP(this List source, int? batchSize = null) double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -651,7 +652,7 @@ public static double AverageP(this List source, Func selector, i double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -688,7 +689,7 @@ public static double AverageP(this List source, int? batchSize = null) double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -732,7 +733,7 @@ public static double AverageP(this List source, Func selector, double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -769,7 +770,7 @@ public static decimal AverageP(this List source, int? batchSize = null) decimal sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => (decimal)0.0, (range, s, acc) => @@ -814,7 +815,7 @@ public static decimal AverageP(this List source, Func selector decimal sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => (decimal)0.0, (range, s, acc) => diff --git a/LinqFasterParallel/ContainsParallel.cs b/LinqFasterParallel/ContainsParallel.cs index 0134568..f9eed25 100644 --- a/LinqFasterParallel/ContainsParallel.cs +++ b/LinqFasterParallel/ContainsParallel.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Threading; using static JM.LinqFaster.Utils.CustomPartition; @@ -31,7 +33,7 @@ public static bool ContainsP(this TSource[] source, TSource value, IEqu int total = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -74,7 +76,7 @@ public static bool ContainsP(this List source, TSource value, int total = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { diff --git a/LinqFasterParallel/CountParallel.cs b/LinqFasterParallel/CountParallel.cs index 8d231e1..3c8275e 100644 --- a/LinqFasterParallel/CountParallel.cs +++ b/LinqFasterParallel/CountParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using static JM.LinqFaster.Utils.CustomPartition; @@ -30,7 +31,7 @@ public static int CountP(this T[] source, Func predicate, int? batch } int total = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => @@ -79,7 +80,7 @@ public static int CountP(this List source, Func predicate, int? b } int total = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => diff --git a/LinqFasterParallel/MaxParallel.cs b/LinqFasterParallel/MaxParallel.cs index b62d9e4..f419f97 100644 --- a/LinqFasterParallel/MaxParallel.cs +++ b/LinqFasterParallel/MaxParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using static JM.LinqFaster.Utils.CustomPartition; @@ -26,7 +27,7 @@ public static T MaxP(this T[] source, int? batchSize = null) } object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); Comparer comparer = Comparer.Default; T Max = default(T); if (Max == null) @@ -99,9 +100,9 @@ public static T MaxP(this T[] source, int? batchSize = null) } object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); Comparer comparer = Comparer.Default; - var Max = default(TResult); + TResult Max = default(TResult); if (Max == null) { Max = selector(source[0]); @@ -111,7 +112,7 @@ public static T MaxP(this T[] source, int? batchSize = null) { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (s != null && comparer.Compare(s, threadMax) > 0) threadMax = s; } return threadMax; @@ -136,7 +137,7 @@ public static T MaxP(this T[] source, int? batchSize = null) { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (comparer.Compare(s, threadMax) > 0) threadMax = s; } return threadMax; @@ -176,7 +177,7 @@ public static int MaxP(this int[] source, int? batchSize = null) int Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -224,14 +225,14 @@ public static int MaxP(this T[] source, Func selector, int? batchSize int Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + int s = selector(source[i]); if (s > threadMax) { threadMax = s; @@ -272,7 +273,7 @@ public static long MaxP(this long[] source, int? batchSize = null) long Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -320,14 +321,14 @@ public static long MaxP(this T[] source, Func selector, int? batchSi long Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + long s = selector(source[i]); if (s > threadMax) { threadMax = s; @@ -368,7 +369,7 @@ public static float MaxP(this float[] source, int? batchSize = null) float Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -416,14 +417,14 @@ public static float MaxP(this T[] source, Func selector, int? batch float Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + float s = selector(source[i]); if (s > threadMax) { threadMax = s; @@ -464,7 +465,7 @@ public static double MaxP(this double[] source, int? batchSize = null) double Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -512,14 +513,14 @@ public static double MaxP(this T[] source, Func selector, int? bat double Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + double s = selector(source[i]); if (s > threadMax) { threadMax = s; @@ -560,7 +561,7 @@ public static decimal MaxP(this decimal[] source, int? batchSize = null) decimal Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -608,14 +609,14 @@ public static decimal MaxP(this T[] source, Func selector, int? b decimal Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + decimal s = selector(source[i]); if (s > threadMax) { threadMax = s; @@ -658,7 +659,7 @@ public static T MaxP(this List source, int? batchSize = null) } object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); Comparer comparer = Comparer.Default; T Max = default(T); if (Max == null) @@ -731,9 +732,9 @@ public static T MaxP(this List source, int? batchSize = null) } object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); Comparer comparer = Comparer.Default; - var Max = default(TResult); + TResult Max = default(TResult); if (Max == null) { Max = selector(source[0]); @@ -743,7 +744,7 @@ public static T MaxP(this List source, int? batchSize = null) { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (s != null && comparer.Compare(s, threadMax) > 0) threadMax = s; } return threadMax; @@ -768,7 +769,7 @@ public static T MaxP(this List source, int? batchSize = null) { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (comparer.Compare(s, threadMax) > 0) threadMax = s; } return threadMax; @@ -808,7 +809,7 @@ public static int MaxP(this List source, int? batchSize = null) int Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -856,14 +857,14 @@ public static int MaxP(this List source, Func selector, int? batch int Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + int s = selector(source[i]); if (s > threadMax) { threadMax = s; @@ -904,7 +905,7 @@ public static long MaxP(this List source, int? batchSize = null) long Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -952,14 +953,14 @@ public static long MaxP(this List source, Func selector, int? bat long Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + long s = selector(source[i]); if (s > threadMax) { threadMax = s; @@ -1000,7 +1001,7 @@ public static float MaxP(this List source, int? batchSize = null) float Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -1048,14 +1049,14 @@ public static float MaxP(this List source, Func selector, int? b float Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + float s = selector(source[i]); if (s > threadMax) { threadMax = s; @@ -1096,7 +1097,7 @@ public static double MaxP(this List source, int? batchSize = null) double Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -1144,14 +1145,14 @@ public static double MaxP(this List source, Func selector, int? double Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + double s = selector(source[i]); if (s > threadMax) { threadMax = s; @@ -1192,7 +1193,7 @@ public static decimal MaxP(this List source, int? batchSize = null) decimal Max = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => @@ -1240,14 +1241,14 @@ public static decimal MaxP(this List source, Func selector, in decimal Max = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Max, (range, state, threadMax) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + decimal s = selector(source[i]); if (s > threadMax) { threadMax = s; diff --git a/LinqFasterParallel/MinParallel.cs b/LinqFasterParallel/MinParallel.cs index e95d758..8e45aeb 100644 --- a/LinqFasterParallel/MinParallel.cs +++ b/LinqFasterParallel/MinParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using static JM.LinqFaster.Utils.CustomPartition; @@ -30,7 +31,7 @@ public static T MinP(this T[] source, int? batchSize = null) } object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); Comparer comparer = Comparer.Default; T min = default(T); if (min == null) @@ -103,9 +104,9 @@ public static T MinP(this T[] source, int? batchSize = null) } object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); Comparer comparer = Comparer.Default; - var min = default(TResult); + TResult min = default(TResult); if (min == null) { min = selector(source[0]); @@ -115,7 +116,7 @@ public static T MinP(this T[] source, int? batchSize = null) { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (s != null && comparer.Compare(s, threadMin) < 0) threadMin = s; } return threadMin; @@ -140,7 +141,7 @@ public static T MinP(this T[] source, int? batchSize = null) { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (comparer.Compare(s, threadMin) < 0) threadMin = s; } return threadMin; @@ -180,7 +181,7 @@ public static int MinP(this int[] source, int? batchSize = null) int min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -228,14 +229,14 @@ public static int MinP(this T[] source, Func selector, int? batchSize int min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + int s = selector(source[i]); if (s < threadMin) { threadMin = s; @@ -276,7 +277,7 @@ public static long MinP(this long[] source, int? batchSize = null) long min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -324,14 +325,14 @@ public static long MinP(this T[] source, Func selector, int? batchSi long min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + long s = selector(source[i]); if (s < threadMin) { threadMin = s; @@ -372,7 +373,7 @@ public static float MinP(this float[] source, int? batchSize = null) float min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -420,14 +421,14 @@ public static float MinP(this T[] source, Func selector, int? batch float min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + float s = selector(source[i]); if (s < threadMin) { threadMin = s; @@ -468,7 +469,7 @@ public static double MinP(this double[] source, int? batchSize = null) double min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -516,14 +517,14 @@ public static double MinP(this T[] source, Func selector, int? bat double min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + double s = selector(source[i]); if (s < threadMin) { threadMin = s; @@ -564,7 +565,7 @@ public static decimal MinP(this decimal[] source, int? batchSize = null) decimal min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -612,14 +613,14 @@ public static decimal MinP(this T[] source, Func selector, int? b decimal min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + decimal s = selector(source[i]); if (s < threadMin) { threadMin = s; @@ -662,7 +663,7 @@ public static T MinP(this List source, int? batchSize = null) } object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); Comparer comparer = Comparer.Default; T min = default(T); if (min == null) @@ -735,9 +736,9 @@ public static T MinP(this List source, int? batchSize = null) } object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); Comparer comparer = Comparer.Default; - var min = default(TResult); + TResult min = default(TResult); if (min == null) { min = selector(source[0]); @@ -747,7 +748,7 @@ public static T MinP(this List source, int? batchSize = null) { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (s != null && comparer.Compare(s, threadMin) < 0) threadMin = s; } return threadMin; @@ -772,7 +773,7 @@ public static T MinP(this List source, int? batchSize = null) { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (comparer.Compare(s, threadMin) < 0) threadMin = s; } return threadMin; @@ -812,7 +813,7 @@ public static int MinP(this List source, int? batchSize = null) int min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -860,14 +861,14 @@ public static int MinP(this List source, Func selector, int? batch int min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + int s = selector(source[i]); if (s < threadMin) { threadMin = s; @@ -908,7 +909,7 @@ public static long MinP(this List source, int? batchSize = null) long min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -956,14 +957,14 @@ public static long MinP(this List source, Func selector, int? bat long min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + long s = selector(source[i]); if (s < threadMin) { threadMin = s; @@ -1004,7 +1005,7 @@ public static float MinP(this List source, int? batchSize = null) float min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -1052,14 +1053,14 @@ public static float MinP(this List source, Func selector, int? b float min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + float s = selector(source[i]); if (s < threadMin) { threadMin = s; @@ -1100,7 +1101,7 @@ public static double MinP(this List source, int? batchSize = null) double min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -1148,14 +1149,14 @@ public static double MinP(this List source, Func selector, int? double min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + double s = selector(source[i]); if (s < threadMin) { threadMin = s; @@ -1196,7 +1197,7 @@ public static decimal MinP(this List source, int? batchSize = null) decimal min = source[0]; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => @@ -1244,14 +1245,14 @@ public static decimal MinP(this List source, Func selector, in decimal min = selector(source[0]); object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => min, (range, state, threadMin) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + decimal s = selector(source[i]); if (s < threadMin) { threadMin = s; diff --git a/LinqFasterParallel/SelectParallel.cs b/LinqFasterParallel/SelectParallel.cs index b60b9ed..bc0d95b 100644 --- a/LinqFasterParallel/SelectParallel.cs +++ b/LinqFasterParallel/SelectParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using static JM.LinqFaster.Utils.CustomPartition; @@ -27,7 +28,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, int? } - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { for (int i = range.Item1; i < range.Item2; i++) @@ -57,7 +58,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, i } - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { for (int i = range.Item1; i < range.Item2; i++) @@ -86,9 +87,9 @@ public static void SelectInPlaceP(this T[] source, Func selector, i throw Error.ArgumentNull("selector"); } - var r = new TResult[source.Length]; + TResult[] r = new TResult[source.Length]; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { for (int i = range.Item1; i < range.Item2; i++) { @@ -117,8 +118,8 @@ public static void SelectInPlaceP(this T[] source, Func selector, i { throw Error.ArgumentNull("selector"); } - var r = new TResult[source.Length]; - var rangePartitioner = MakePartition(source.Length, batchSize); + TResult[] r = new TResult[source.Length]; + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { for (int i = range.Item1; i < range.Item2; i++) { @@ -150,7 +151,7 @@ public static void SelectInPlaceP(this List source, Func selector, i } - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { for (int i = range.Item1; i < range.Item2; i++) @@ -180,7 +181,7 @@ public static void SelectInPlaceP(this List source, Func select } - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { for (int i = range.Item1; i < range.Item2; i++) @@ -208,9 +209,9 @@ public static void SelectInPlaceP(this List source, Func select { throw Error.ArgumentNull("selector"); } - var r = new TResult[source.Count]; + TResult[] r = new TResult[source.Count]; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { for (int i = range.Item1; i < range.Item2; i++) @@ -242,9 +243,9 @@ public static void SelectInPlaceP(this List source, Func select throw Error.ArgumentNull("selector"); } - var r = new TResult[source.Count]; + TResult[] r = new TResult[source.Count]; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { for (int i = range.Item1; i < range.Item2; i++) { @@ -276,9 +277,9 @@ public static void SelectInPlaceP(this List source, Func select throw Error.ArgumentNull("selector"); } - var r = new List(source.Count); + List r = new List(source.Count); - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { for (int i = range.Item1; i < range.Item2; i++) diff --git a/LinqFasterParallel/SelectWhereParallel.cs b/LinqFasterParallel/SelectWhereParallel.cs index fce58a6..a358f47 100644 --- a/LinqFasterParallel/SelectWhereParallel.cs +++ b/LinqFasterParallel/SelectWhereParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using static JM.LinqFaster.Utils.CustomPartition; @@ -32,16 +33,16 @@ public static partial class LinqFasterParallel throw Error.ArgumentNull("predicate"); } - var isChosen = new bool[source.Length]; - var tempResults = new TResult[source.Length]; + bool[] isChosen = new bool[source.Length]; + TResult[] tempResults = new TResult[source.Length]; int count = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState,acc) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (predicate(s)) { isChosen[i] = true; @@ -56,7 +57,7 @@ public static partial class LinqFasterParallel Interlocked.Add(ref count, acc); }); - var result = new TResult[count]; + TResult[] result = new TResult[count]; int idx = 0; for (int i = 0; i < isChosen.Length; i++) { @@ -94,16 +95,16 @@ public static partial class LinqFasterParallel throw Error.ArgumentNull("predicate"); } - var isChosen = new bool[source.Length]; - var tempResults = new TResult[source.Length]; + bool[] isChosen = new bool[source.Length]; + TResult[] tempResults = new TResult[source.Length]; int count = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i],i); + TResult s = selector(source[i],i); if (predicate(s,i)) { isChosen[i] = true; @@ -118,7 +119,7 @@ public static partial class LinqFasterParallel Interlocked.Add(ref count, acc); }); - var result = new TResult[count]; + TResult[] result = new TResult[count]; int idx = 0; for (int i = 0; i < isChosen.Length; i++) { @@ -158,16 +159,16 @@ public static partial class LinqFasterParallel throw Error.ArgumentNull("predicate"); } - var isChosen = new bool[source.Count]; - var tempResults = new TResult[source.Count]; + bool[] isChosen = new bool[source.Count]; + TResult[] tempResults = new TResult[source.Count]; int count = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i]); + TResult s = selector(source[i]); if (predicate(s)) { isChosen[i] = true; @@ -182,7 +183,7 @@ public static partial class LinqFasterParallel Interlocked.Add(ref count, acc); }); - var result = new List(count); + List result = new List(count); for (int i = 0; i < isChosen.Length; i++) { if (isChosen[i]) @@ -218,16 +219,16 @@ public static partial class LinqFasterParallel throw Error.ArgumentNull("predicate"); } - var isChosen = new bool[source.Count]; - var tempResults = new TResult[source.Count]; + bool[] isChosen = new bool[source.Count]; + TResult[] tempResults = new TResult[source.Count]; int count = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => { for (int i = range.Item1; i < range.Item2; i++) { - var s = selector(source[i], i); + TResult s = selector(source[i], i); if (predicate(s, i)) { isChosen[i] = true; @@ -242,7 +243,7 @@ public static partial class LinqFasterParallel Interlocked.Add(ref count, acc); }); - var result = new List(count); + List result = new List(count); for (int i = 0; i < isChosen.Length; i++) { if (isChosen[i]) diff --git a/LinqFasterParallel/SequenceEqualParallel.cs b/LinqFasterParallel/SequenceEqualParallel.cs index 1d84c34..b623ca0 100644 --- a/LinqFasterParallel/SequenceEqualParallel.cs +++ b/LinqFasterParallel/SequenceEqualParallel.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Threading; using static JM.LinqFaster.Utils.CustomPartition; @@ -38,7 +40,7 @@ public static bool SequenceEqualP(this T[] first, T[] second, IEqualityCompar if (first.Length != second.Length) return false; if (first == second) return true; int count = 0; - var rangePartitioner = MakePartition(first.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(first.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -87,7 +89,7 @@ public static bool SequenceEqualP(this List first, List second, IEquali if (first == second) return true; int count = 0; - var rangePartitioner = MakePartition(first.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(first.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -135,7 +137,7 @@ public static bool SequenceEqualP(this T[] first, List second, IEqualityCo if (first.Length != second.Count) return false; int count = 0; - var rangePartitioner = MakePartition(first.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(first.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -183,7 +185,7 @@ public static bool SequenceEqualP(this List first, T[] second, IEqualityCo if (first.Count != second.Length) return false; int count = 0; - var rangePartitioner = MakePartition(first.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(first.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { diff --git a/LinqFasterParallel/SumParallel.cs b/LinqFasterParallel/SumParallel.cs index 2753785..45d5c91 100644 --- a/LinqFasterParallel/SumParallel.cs +++ b/LinqFasterParallel/SumParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using static JM.LinqFaster.Utils.CustomPartition; @@ -22,7 +23,7 @@ public static int SumP(this int[] source, int? batchSize = null) throw Error.ArgumentNull("source"); } int sum = 0; - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, s, acc) => @@ -62,7 +63,7 @@ public static int SumP(this T[] source, Func selector, int? batchSize } int sum = 0; - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, s, acc) => @@ -94,7 +95,7 @@ public static long SumP(this long[] source, int? batchSize = null) throw Error.ArgumentNull("source"); } long sum = 0; - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -133,7 +134,7 @@ public static long SumP(this T[] source, Func selector, int? batchSi } long sum = 0; - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -166,7 +167,7 @@ public static float SumP(this float[] source, int? batchSize = null) } double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -211,7 +212,7 @@ public static float SumP(this T[] source, Func selector, int? batch double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -249,7 +250,7 @@ public static double SumP(this double[] source, int? batchSize = null) } double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -292,7 +293,7 @@ public static double SumP(this T[] source, Func selector, int? bat } double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -330,7 +331,7 @@ public static decimal SumP(this decimal[] source, int? batchSize = null) } decimal sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => (decimal)0.0, (range, s, acc) => @@ -374,7 +375,7 @@ public static decimal SumP(this T[] source, Func selector, int? b decimal sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Length,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => (decimal)0.0, (range, s, acc) => @@ -411,7 +412,7 @@ public static int SumP(this List source, int? batchSize = null) throw Error.ArgumentNull("source"); } int sum = 0; - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, s, acc) => @@ -450,7 +451,7 @@ public static int SumP(this List source, Func selector, int? batch } int sum = 0; - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, s, acc) => @@ -482,7 +483,7 @@ public static long SumP(this List source, int? batchSize = null) throw Error.ArgumentNull("source"); } long sum = 0; - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -521,7 +522,7 @@ public static long SumP(this List source, Func selector, int? bat } long sum = 0; - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0L, (range, s, acc) => @@ -554,7 +555,7 @@ public static float SumP(this List source, int? batchSize = null) } double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -591,7 +592,7 @@ public static float SumP(this List source, Func selector, int? b double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -622,7 +623,7 @@ public static double SumP(this List source, int? batchSize = null) } double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -659,7 +660,7 @@ public static double SumP(this List source, Func selector, int? double sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0.0, (range, s, acc) => @@ -693,7 +694,7 @@ public static decimal SumP(this List source, int? batchSize = null) decimal sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => (decimal)0.0, (range, s, acc) => @@ -733,7 +734,7 @@ public static decimal SumP(this List source, Func selector, in decimal sum = 0; object LOCK = new object(); - var rangePartitioner = MakePartition(source.Count,batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => (decimal)0.0, (range, s, acc) => diff --git a/LinqFasterParallel/WhereAggregateParallel.cs b/LinqFasterParallel/WhereAggregateParallel.cs index f6c7557..20946f0 100644 --- a/LinqFasterParallel/WhereAggregateParallel.cs +++ b/LinqFasterParallel/WhereAggregateParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using static JM.LinqFaster.Utils.CustomPartition; @@ -33,7 +34,7 @@ public static TSource WhereAggregateP(this TSource[] source, Func> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -46,7 +47,7 @@ public static TSource WhereAggregateP(this TSource[] source, Func(this TSource[] source, Func> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -107,7 +108,7 @@ public static TSource WhereAggregateP(this TSource[] source, Func(this TSource[] source, Func> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -170,7 +171,7 @@ public static TSource WhereAggregateP(this TSource[] source, Func(this TSource[] source, Func> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -223,7 +224,7 @@ public static TSource WhereAggregateP(this TSource[] source, Func(this List source, Func> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -276,7 +277,7 @@ public static TSource WhereAggregateP(this List source, Func(this List source, Func> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -337,7 +338,7 @@ public static TSource WhereAggregateP(this List source, Func(this List source, Func> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -399,7 +400,7 @@ public static TSource WhereAggregateP(this List source, Func(this List source, Func> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -452,7 +453,7 @@ public static TSource WhereAggregateP(this List source, Func(this TSource[] source, Func> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => @@ -47,7 +48,7 @@ public static TSource[] WhereP(this TSource[] source, Func(this TSource[] source, Func> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => @@ -102,7 +103,7 @@ public static TSource[] WhereP(this TSource[] source, Func WhereP(this List source, Func> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, @@ -194,7 +195,7 @@ public static List WhereP(this List source, Func> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, diff --git a/LinqFasterParallel/WhereSelectParallel.cs b/LinqFasterParallel/WhereSelectParallel.cs index c448ab9..f7b053d 100644 --- a/LinqFasterParallel/WhereSelectParallel.cs +++ b/LinqFasterParallel/WhereSelectParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using static JM.LinqFaster.Utils.CustomPartition; @@ -32,9 +33,9 @@ public static partial class LinqFasterParallel throw Error.ArgumentNull("predicate"); } - var isChosen = new bool[source.Length]; + bool[] isChosen = new bool[source.Length]; int count = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState,acc) => { @@ -53,7 +54,7 @@ public static partial class LinqFasterParallel Interlocked.Add(ref count, acc); }); - var result = new TResult[count]; + TResult[] result = new TResult[count]; int idx = 0; for (int i = 0; i < isChosen.Length; i++) { @@ -93,9 +94,9 @@ public static partial class LinqFasterParallel throw Error.ArgumentNull("predicate"); } - var isChosen = new bool[source.Length]; + bool[] isChosen = new bool[source.Length]; int count = 0; - var rangePartitioner = MakePartition(source.Length, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => { @@ -114,7 +115,7 @@ public static partial class LinqFasterParallel Interlocked.Add(ref count, acc); }); - var result = new TResult[count]; + TResult[] result = new TResult[count]; int idx = 0; for (int i = 0; i < isChosen.Length; i++) { @@ -154,9 +155,9 @@ public static partial class LinqFasterParallel throw Error.ArgumentNull("predicate"); } - var isChosen = new bool[source.Count]; + bool[] isChosen = new bool[source.Count]; int count = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => { @@ -175,7 +176,7 @@ public static partial class LinqFasterParallel Interlocked.Add(ref count, acc); }); - var result = new List(count); + List result = new List(count); for (int i = 0; i < isChosen.Length; i++) { if (isChosen[i]) @@ -213,9 +214,9 @@ public static partial class LinqFasterParallel throw Error.ArgumentNull("predicate"); } - var isChosen = new bool[source.Count]; + bool[] isChosen = new bool[source.Count]; int count = 0; - var rangePartitioner = MakePartition(source.Count, batchSize); + OrderablePartitioner> rangePartitioner = MakePartition(source.Count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => 0, (range, loopState, acc) => { @@ -234,7 +235,7 @@ public static partial class LinqFasterParallel Interlocked.Add(ref count, acc); }); - var result = new List(count); + List result = new List(count); int idx = 0; for (int i = 0; i < isChosen.Length; i++) { diff --git a/LinqFasterParallelSIMD/SelectSIMDParallel.cs b/LinqFasterParallelSIMD/SelectSIMDParallel.cs index 4afb884..61665aa 100644 --- a/LinqFasterParallelSIMD/SelectSIMDParallel.cs +++ b/LinqFasterParallelSIMD/SelectSIMDParallel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Numerics; using static JM.LinqFaster.Utils.CustomPartition; @@ -33,8 +34,8 @@ public static partial class LinqFasterSIMDParallel throw Error.ArgumentOutOfRange("Vector widths do not match."); } - var result = new U[source.Length]; - var rangePartitioner = MakeSIMDPartition(source.Length, count, batchSize); + U[] result = new U[source.Length]; + OrderablePartitioner> rangePartitioner = MakeSIMDPartition(source.Length, count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, s) => { diff --git a/LinqFasterParallelSIMD/SequenceEqualSIMDParallel.cs b/LinqFasterParallelSIMD/SequenceEqualSIMDParallel.cs index fcc46c8..d4a1568 100644 --- a/LinqFasterParallelSIMD/SequenceEqualSIMDParallel.cs +++ b/LinqFasterParallelSIMD/SequenceEqualSIMDParallel.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Numerics; using System.Threading; using static JM.LinqFaster.Utils.CustomPartition; @@ -33,9 +35,9 @@ public static partial class LinqFasterSIMDParallel if (first.Length != second.Length) return false; if (first == second) return true; - var count = Vector.Count; + int count = Vector.Count; int nonEqualCount = 0; - var rangePartitioner = MakeSIMDPartition(first.Length, count, batchSize); + OrderablePartitioner> rangePartitioner = MakeSIMDPartition(first.Length, count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, (range, loopState) => { @@ -53,7 +55,7 @@ public static partial class LinqFasterSIMDParallel }); if (nonEqualCount != 0) return false; - var comparer = EqualityComparer.Default; + EqualityComparer comparer = EqualityComparer.Default; for (int i = first.Length - (first.Length % count); i < first.Length; i++) { if (!comparer.Equals(first[i], second[i])) return false; diff --git a/LinqFasterParallelSIMD/SumSIMDParallel.cs b/LinqFasterParallelSIMD/SumSIMDParallel.cs index e0493c5..c3f8888 100644 --- a/LinqFasterParallelSIMD/SumSIMDParallel.cs +++ b/LinqFasterParallelSIMD/SumSIMDParallel.cs @@ -1,4 +1,6 @@ -using System.Numerics; +using System; +using System.Collections.Concurrent; +using System.Numerics; using static JM.LinqFaster.Utils.GenericOperators; using static JM.LinqFaster.Utils.CustomPartition; @@ -21,11 +23,11 @@ public static partial class LinqFasterSIMDParallel throw Error.ArgumentNull("source"); } - var count = Vector.Count; - var sum = Vector.Zero; + int count = Vector.Count; + Vector sum = Vector.Zero; object LOCK = new object(); - var rangePartitioner = MakeSIMDPartition(source.Length, count, batchSize); + OrderablePartitioner> rangePartitioner = MakeSIMDPartition(source.Length, count, batchSize); System.Threading.Tasks.Parallel.ForEach(rangePartitioner, () => Vector.Zero, (range, s, acc) => diff --git a/LinqFasterSIMD/ContainsSIMD.cs b/LinqFasterSIMD/ContainsSIMD.cs index a4bc588..8cde1cc 100644 --- a/LinqFasterSIMD/ContainsSIMD.cs +++ b/LinqFasterSIMD/ContainsSIMD.cs @@ -22,8 +22,8 @@ public static bool ContainsS(this T[] source, T value) throw Error.ArgumentNull("source"); } - var count = Vector.Count; - var vectorValue = new Vector(value); + int count = Vector.Count; + Vector vectorValue = new Vector(value); for (int i = 0; i < source.Length-count;i+=count) { if (Vector.EqualsAny(new Vector(source,i),vectorValue)) diff --git a/LinqFasterSIMD/MaxSIMD.cs b/LinqFasterSIMD/MaxSIMD.cs index 9ef0588..159ef41 100644 --- a/LinqFasterSIMD/MaxSIMD.cs +++ b/LinqFasterSIMD/MaxSIMD.cs @@ -28,10 +28,10 @@ public static T MaxS (this T[] source) int count = Vector.Count; if (count <= source.Length) { - var vMax = new Vector(source, 0); + Vector vMax = new Vector(source, 0); for (int i = count; i <= source.Length-count; i+=count) { - var v = new Vector(source, i); + Vector v = new Vector(source, i); vMax = Vector.Max(v, vMax); } diff --git a/LinqFasterSIMD/MinSIMD.cs b/LinqFasterSIMD/MinSIMD.cs index 6a29289..8f8181d 100644 --- a/LinqFasterSIMD/MinSIMD.cs +++ b/LinqFasterSIMD/MinSIMD.cs @@ -29,10 +29,10 @@ public static T MinS (this T[] source) int count = Vector.Count; if (count <= source.Length) { - var vMin = new Vector(source, 0); + Vector vMin = new Vector(source, 0); for (int i = count; i <= source.Length-count; i+=count) { - var v = new Vector(source, i); + Vector v = new Vector(source, i); vMin = Vector.Min(v, vMin); } diff --git a/LinqFasterSIMD/RangeSIMD.cs b/LinqFasterSIMD/RangeSIMD.cs index 7bf0af0..2bfff44 100644 --- a/LinqFasterSIMD/RangeSIMD.cs +++ b/LinqFasterSIMD/RangeSIMD.cs @@ -20,7 +20,7 @@ public static int[] RangeS(int start, int len) throw Error.ArgumentOutOfRange("len"); } - var count = Vector.Count; + int count = Vector.Count; int[] result = new int[len]; if (len >= count) { //use result array for double duty to save memory @@ -29,8 +29,8 @@ public static int[] RangeS(int start, int len) result[i] = i + start; } - var V = new Vector(result); - var Increment = new Vector(count); + Vector V = new Vector(result); + Vector Increment = new Vector(count); V = V + Increment; for (int i = count; i <= len - count; i += count) { V.CopyTo(result, i); diff --git a/LinqFasterSIMD/RepeatSIMD.cs b/LinqFasterSIMD/RepeatSIMD.cs index f54e563..ea79a4a 100644 --- a/LinqFasterSIMD/RepeatSIMD.cs +++ b/LinqFasterSIMD/RepeatSIMD.cs @@ -19,9 +19,9 @@ public static T[] RepeatS(T e, int count) throw Error.ArgumentOutOfRange("count"); } - var result = new T[count]; - var v = new Vector(e); - var vCount = Vector.Count; + T[] result = new T[count]; + Vector v = new Vector(e); + int vCount = Vector.Count; int i = 0; for (; i <= result.Length-vCount; i += vCount) diff --git a/LinqFasterSIMD/SelectSIMD.cs b/LinqFasterSIMD/SelectSIMD.cs index 0585e9d..f908cca 100644 --- a/LinqFasterSIMD/SelectSIMD.cs +++ b/LinqFasterSIMD/SelectSIMD.cs @@ -27,14 +27,14 @@ public static partial class LinqFasterSIMD throw Error.ArgumentNull("selectorSIMD"); } - var count = Vector.Count; + int count = Vector.Count; if (count != Vector.Count) { throw Error.ArgumentOutOfRange("selectorSIMD"); } - var result = new U[source.Length]; + U[] result = new U[source.Length]; int i = 0; for (; i <= source.Length-count;i+=count) @@ -71,7 +71,7 @@ public static void SelectInPlaceS(this T[] source, Func, Vector> throw Error.ArgumentNull("selectorSIMD"); } - var count = Vector.Count; + int count = Vector.Count; int i = 0; diff --git a/LinqFasterSIMD/SequenceEqualSIMD.cs b/LinqFasterSIMD/SequenceEqualSIMD.cs index 57786fc..69e6578 100644 --- a/LinqFasterSIMD/SequenceEqualSIMD.cs +++ b/LinqFasterSIMD/SequenceEqualSIMD.cs @@ -30,7 +30,7 @@ public static partial class LinqFasterSIMD if (first.Length != second.Length) return false; if (first == second) return true; - var count = Vector.Count; + int count = Vector.Count; for (int i = 0; i <= first.Length - count; i += count) { if (!Vector.EqualsAll(new Vector(first, i), new Vector(second, i))) @@ -38,7 +38,7 @@ public static partial class LinqFasterSIMD return false; } } - var comparer = EqualityComparer.Default; + EqualityComparer comparer = EqualityComparer.Default; for (int i = first.Length - (first.Length % count); i < first.Length; i++) { if (!comparer.Equals(first[i], second[i])) return false; @@ -68,17 +68,17 @@ public static partial class LinqFasterSIMD if (first.Length != second.Length) throw Error.NotSupported(); - var minusone = new Vector(-1); - var count = Vector.Count; - var result = new int[first.Length]; + Vector minusone = new Vector(-1); + int count = Vector.Count; + int[] result = new int[first.Length]; for (int i = 0; i <= first.Length - count; i += count) { - var a = new Vector(first, i); - var b = new Vector(second, i); + Vector a = new Vector(first, i); + Vector b = new Vector(second, i); if (!Vector.EqualsAll(a, b)) { - var gt = Vector.BitwiseAnd(Vector.AsVectorInt32(Vector.GreaterThan(a, b)), Vector.One); - var lt = Vector.BitwiseAnd(Vector.AsVectorInt32(Vector.LessThan(a, b)), minusone); + Vector gt = Vector.BitwiseAnd(Vector.AsVectorInt32(Vector.GreaterThan(a, b)), Vector.One); + Vector lt = Vector.BitwiseAnd(Vector.AsVectorInt32(Vector.LessThan(a, b)), minusone); Vector.BitwiseOr(gt, lt).CopyTo(result, i); } } diff --git a/LinqFasterSIMD/SumSIMD.cs b/LinqFasterSIMD/SumSIMD.cs index 0052050..5591858 100644 --- a/LinqFasterSIMD/SumSIMD.cs +++ b/LinqFasterSIMD/SumSIMD.cs @@ -21,15 +21,15 @@ public static partial class LinqFasterSIMD throw Error.ArgumentNull("source"); } - var state = Vector.Zero; - var count = Vector.Count; + Vector state = Vector.Zero; + int count = Vector.Count; for (int i = 0; i <= source.Length - count; i+=count) { state = state + new Vector(source, i); } - var result = default(T); + T result = default(T); for (int i = source.Length-source.Length % count; i < source.Length;i++) { @@ -65,15 +65,15 @@ public static partial class LinqFasterSIMD throw Error.ArgumentNull("selectorSIMD"); } - var state = Vector.Zero; - var count = Vector.Count; + Vector state = Vector.Zero; + int count = Vector.Count; for (int i = 0; i <= source.Length-count; i += count) { state = state + selectorSIMD(new Vector(source, i)); } - var result = default(U); + U result = default(U); if (selector != null) { diff --git a/Tests/AggregateTests.cs b/Tests/AggregateTests.cs index 295afb8..103a58c 100644 --- a/Tests/AggregateTests.cs +++ b/Tests/AggregateTests.cs @@ -13,25 +13,25 @@ internal class AggregateTests public void AggregateArray() { - var a = intArray.AggregateF(addXInts); - var aSpan = intArray.AsSpan().AggregateF(addXInts); - var b = intArray.Aggregate(addXInts); + int a = intArray.AggregateF(addXInts); + int aSpan = intArray.AsSpan().AggregateF(addXInts); + int b = intArray.Aggregate(addXInts); Assert.That(a, Is.EqualTo(b)); Assert.That(aSpan, Is.EqualTo(b)); Func lambda2 = (acc, x) => acc += x; - var seed = "seed"; - var c = intArray.AggregateF(seed, lambda2); - var d = intArray.Aggregate(seed, lambda2); + string seed = "seed"; + string c = intArray.AggregateF(seed, lambda2); + string d = intArray.Aggregate(seed, lambda2); Assert.That(c, Is.EqualTo(d)); - var cSpan = intArray.AsSpan().AggregateF(seed, lambda2); + string cSpan = intArray.AsSpan().AggregateF(seed, lambda2); Assert.That(cSpan, Is.EqualTo(d)); - var e = intArray.AggregateF(seed, lambda2, (x => "")); - var f = intArray.Aggregate(seed, lambda2, (x => "")); + string e = intArray.AggregateF(seed, lambda2, (x => "")); + string f = intArray.Aggregate(seed, lambda2, (x => "")); Assert.That(e, Is.EqualTo(f)); @@ -41,20 +41,20 @@ public void AggregateArray() public void AggregateList() { - var a = intList.AggregateF(addXInts); - var b = intList.Aggregate(addXInts); + int a = intList.AggregateF(addXInts); + int b = intList.Aggregate(addXInts); Assert.That(a, Is.EqualTo(b)); Func lambda2 = (acc, x) => acc += x; - var seed = "seed"; - var c = intList.AggregateF(seed, lambda2); - var d = intList.Aggregate(seed, lambda2); + string seed = "seed"; + string c = intList.AggregateF(seed, lambda2); + string d = intList.Aggregate(seed, lambda2); Assert.That(c, Is.EqualTo(d)); - var e = intList.AggregateF(seed, lambda2, (x => "")); - var f = intList.Aggregate(seed, lambda2, (x => "")); + string e = intList.AggregateF(seed, lambda2, (x => "")); + string f = intList.Aggregate(seed, lambda2, (x => "")); Assert.That(e, Is.EqualTo(f)); diff --git a/Tests/AnyAllTests.cs b/Tests/AnyAllTests.cs index 99f9887..e43ec0c 100644 --- a/Tests/AnyAllTests.cs +++ b/Tests/AnyAllTests.cs @@ -12,8 +12,8 @@ class AnyAllTests [Test] public void AllArray() { - var a = intArray.AllF(x => x % 2 == 0); - var b = intArray.All(x => x % 2 == 0); + bool a = intArray.AllF(x => x % 2 == 0); + bool b = intArray.All(x => x % 2 == 0); Assert.That(a, Is.EqualTo(b)); } @@ -22,8 +22,8 @@ public void AllArray() [Test] public void AllList() { - var a = intList.AllF(x => x % 2 == 0); - var b = intList.All(x => x % 2 == 0); + bool a = intList.AllF(x => x % 2 == 0); + bool b = intList.All(x => x % 2 == 0); Assert.That(a, Is.EqualTo(b)); } @@ -32,8 +32,8 @@ public void AllList() public void AnyArray() { - var a = intArray.AnyF(); - var b = intArray.Any(); + bool a = intArray.AnyF(); + bool b = intArray.Any(); Assert.That(a, Is.EqualTo(b)); @@ -59,8 +59,8 @@ public void AnyArray() public void AnyList() { - var a = intList.AnyF(); - var b = intList.Any(); + bool a = intList.AnyF(); + bool b = intList.Any(); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/AverageTests.cs b/Tests/AverageTests.cs index 9a9989d..9e6d49e 100644 --- a/Tests/AverageTests.cs +++ b/Tests/AverageTests.cs @@ -13,8 +13,8 @@ class AverageTests [Test] public void AverageArrayInt() { - var a = intArray.AverageF(); - var b = intArray.Average(); + double a = intArray.AverageF(); + double b = intArray.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -22,8 +22,8 @@ public void AverageArrayInt() [Test] public void AverageArrayLong() { - var a = Test.longArray.AverageF(); - var b = Test.longArray.Average(); + double a = Test.longArray.AverageF(); + double b = Test.longArray.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -31,8 +31,8 @@ public void AverageArrayLong() [Test] public void AverageArrayFloat() { - var a = floatArray.AverageF(); - var b = floatArray.Average(); + float a = floatArray.AverageF(); + float b = floatArray.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -40,8 +40,8 @@ public void AverageArrayFloat() [Test] public void AverageArrayDouble() { - var a = Test.doubleArray.AverageF(); - var b = Test.doubleArray.Average(); + double a = Test.doubleArray.AverageF(); + double b = Test.doubleArray.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -49,8 +49,8 @@ public void AverageArrayDouble() [Test] public void AverageArrayDecimal() { - var a = decimalArray.AverageF(); - var b = decimalArray.Average(); + decimal a = decimalArray.AverageF(); + decimal b = decimalArray.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -59,8 +59,8 @@ public void AverageArrayDecimal() public void AverageArrayString() { Func lambda = (x => int.Parse(x)); - var a = stringArray.AverageF(lambda); - var b = stringArray.Average(lambda); + float a = stringArray.AverageF(lambda); + float b = stringArray.Average(lambda); Assert.That(a, Is.EqualTo(b)); } @@ -71,40 +71,40 @@ public void AverageArrayString() [Test] public void AverageListInt() { - var a = intList.AverageF(); - var b = intList.Average(); + double a = intList.AverageF(); + double b = intList.Average(); Assert.That(a, Is.EqualTo(b)); } [Test] public void AverageListLong() { - var a = Test.longList.AverageF(); - var b = Test.longList.Average(); + double a = Test.longList.AverageF(); + double b = Test.longList.Average(); Assert.That(a, Is.EqualTo(b)); } [Test] public void AverageListFloat() { - var a = floatList.AverageF(); - var b = floatList.Average(); + float a = floatList.AverageF(); + float b = floatList.Average(); Assert.That(a, Is.EqualTo(b)); } [Test] public void AverageListDouble() { - var a = Test.doubleList.AverageF(); - var b = Test.doubleList.Average(); + double a = Test.doubleList.AverageF(); + double b = Test.doubleList.Average(); Assert.That(a, Is.EqualTo(b)); } [Test] public void AverageListDecimal() { - var a = decimalList.AverageF(); - var b = decimalList.Average(); + decimal a = decimalList.AverageF(); + decimal b = decimalList.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -112,8 +112,8 @@ public void AverageArrayString() [Test] public void AverageListString() { Func lambda = (x => int.Parse(x)); - var a = stringList.AverageF(lambda); - var b = stringList.Average(lambda); + float a = stringList.AverageF(lambda); + float b = stringList.Average(lambda); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/ContainsTests.cs b/Tests/ContainsTests.cs index bda87e6..e0aab69 100644 --- a/Tests/ContainsTests.cs +++ b/Tests/ContainsTests.cs @@ -11,32 +11,32 @@ class ContainsTests { [Test] public void ContainsStringArrayTrue() { - var a = stringArray.ContainsF("0",EqualityComparer.Default); - var b = stringArray.Contains("0", EqualityComparer.Default); + bool a = stringArray.ContainsF("0",EqualityComparer.Default); + bool b = stringArray.Contains("0", EqualityComparer.Default); Assert.That(a, Is.EqualTo(b)); } [Test] public void ContainsStringArrayFalse() { - var a = stringArray.ContainsF("No Match", EqualityComparer.Default); - var b = stringArray.Contains("No Match", EqualityComparer.Default); + bool a = stringArray.ContainsF("No Match", EqualityComparer.Default); + bool b = stringArray.Contains("No Match", EqualityComparer.Default); Assert.That(a, Is.EqualTo(b)); } [Test] public void ContainsStringListTrue() { - var a = stringList.ContainsF("0", EqualityComparer.Default); - var b = stringList.Contains("0", EqualityComparer.Default); + bool a = stringList.ContainsF("0", EqualityComparer.Default); + bool b = stringList.Contains("0", EqualityComparer.Default); Assert.That(a, Is.EqualTo(b)); } [Test] public void ContainsStringListFalse() { - var a = stringList.ContainsF("no match", EqualityComparer.Default); - var b = stringList.Contains("no match", EqualityComparer.Default); + bool a = stringList.ContainsF("no match", EqualityComparer.Default); + bool b = stringList.Contains("no match", EqualityComparer.Default); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/CountTests.cs b/Tests/CountTests.cs index 4fcf9ab..131fd4d 100644 --- a/Tests/CountTests.cs +++ b/Tests/CountTests.cs @@ -10,8 +10,8 @@ class CountTests { [Test] public void CountArray() { - var a = intArray.CountF(onlyEvenInts); - var b = intArray.Count(onlyEvenInts); + int a = intArray.CountF(onlyEvenInts); + int b = intArray.Count(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); } @@ -19,8 +19,8 @@ class CountTests { [Test] public void CountList() { - var a = intList.CountF(onlyEvenInts); - var b = intList.Count(onlyEvenInts); + int a = intList.CountF(onlyEvenInts); + int b = intList.Count(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/FirstTests.cs b/Tests/FirstTests.cs index 0888444..7ceaf97 100644 --- a/Tests/FirstTests.cs +++ b/Tests/FirstTests.cs @@ -10,44 +10,44 @@ class FirstTests { [Test] public void FirstArray() { - var a = intArray.FirstF(); - var b = intArray.First(); + int a = intArray.FirstF(); + int b = intArray.First(); Assert.That(a, Is.EqualTo(b)); } [Test] public void FirstArrayPredicate() { - var a = intArray.FirstF(x => x > 0); - var b = intArray.First(x => x > 0); + int a = intArray.FirstF(x => x > 0); + int b = intArray.First(x => x > 0); Assert.That(a, Is.EqualTo(b)); } [Test] public void FirstOrDefaultArray() { - var a = intArray.FirstOrDefaultF(x => x > 99999); - var b = intArray.FirstOrDefault(x => x > 99999); + int a = intArray.FirstOrDefaultF(x => x > 99999); + int b = intArray.FirstOrDefault(x => x > 99999); Assert.That(a, Is.EqualTo(b)); } [Test] public void FirstList() { - var a = intList.FirstF(); - var b = intList.First(); + int a = intList.FirstF(); + int b = intList.First(); Assert.That(a, Is.EqualTo(b)); } [Test] public void FirstListPredicate() { - var a = intList.FirstF(x => x > 0); - var b = intList.First(x => x > 0); + int a = intList.FirstF(x => x > 0); + int b = intList.First(x => x > 0); Assert.That(a, Is.EqualTo(b)); } [Test] public void FirstOrDefaultList() { - var a = intList.FirstOrDefaultF(x => x > 99999); - var b = intList.FirstOrDefault(x => x > 99999); + int a = intList.FirstOrDefaultF(x => x > 99999); + int b = intList.FirstOrDefault(x => x > 99999); Assert.That(a, Is.EqualTo(b)); } } diff --git a/Tests/LastTests.cs b/Tests/LastTests.cs index 10fa257..eb3308c 100644 --- a/Tests/LastTests.cs +++ b/Tests/LastTests.cs @@ -10,44 +10,44 @@ class LastTests { [Test] public void LastArray() { - var a = intArray.LastF(); - var b = intArray.Last(); + int a = intArray.LastF(); + int b = intArray.Last(); Assert.That(a, Is.EqualTo(b)); } [Test] public void LastArrayPredicate() { - var a = intArray.LastF(x => x > 0); - var b = intArray.Last(x => x > 0); + int a = intArray.LastF(x => x > 0); + int b = intArray.Last(x => x > 0); Assert.That(a, Is.EqualTo(b)); } [Test] public void LastOrDefaultArray() { - var a = intArray.LastOrDefaultF(x => x > 99999); - var b = intArray.LastOrDefault(x => x > 99999); + int a = intArray.LastOrDefaultF(x => x > 99999); + int b = intArray.LastOrDefault(x => x > 99999); Assert.That(a, Is.EqualTo(b)); } [Test] public void LastList() { - var a = intList.LastF(); - var b = intList.Last(); + int a = intList.LastF(); + int b = intList.Last(); Assert.That(a, Is.EqualTo(b)); } [Test] public void LastListPredicate() { - var a = intList.LastF(x => x > 0); - var b = intList.Last(x => x > 0); + int a = intList.LastF(x => x > 0); + int b = intList.Last(x => x > 0); Assert.That(a, Is.EqualTo(b)); } [Test] public void LastOrDefaultList() { - var a = intList.LastOrDefaultF(x => x > 99999); - var b = intList.LastOrDefault(x => x > 99999); + int a = intList.LastOrDefaultF(x => x > 99999); + int b = intList.LastOrDefault(x => x > 99999); Assert.That(a, Is.EqualTo(b)); } } diff --git a/Tests/MaxTests.cs b/Tests/MaxTests.cs index affcc69..ca9d248 100644 --- a/Tests/MaxTests.cs +++ b/Tests/MaxTests.cs @@ -11,6 +11,7 @@ namespace Tests class MaxTests { public void HelperMax(T[] array) + where T : IComparable { T a = array.MaxF(); T b = array.Max(); @@ -19,6 +20,7 @@ public void HelperMax(T[] array) } public void HelperMax(List list) + where T : IComparable { T a = list.MaxF(); T b = list.Max(); @@ -27,14 +29,16 @@ public void HelperMax(List list) } public void HelperMax(T[] array, Func selector) + where U : IComparable { U a = array.MaxF(selector); U b = array.Max(selector); - Assert.That(a, Is.EqualTo(b)); + //Assert.That(a, Is.EqualTo(b)); } public void HelperMax(List list, Func selector) + where U : IComparable { U a = list.MaxF(selector); U b = list.Max(selector); diff --git a/Tests/OrderByTests.cs b/Tests/OrderByTests.cs index 89d0705..91ab72e 100644 --- a/Tests/OrderByTests.cs +++ b/Tests/OrderByTests.cs @@ -1,6 +1,7 @@ using NUnit.Framework; using JM.LinqFaster; using System; +using System.Collections.Generic; using static Tests.Test; namespace Tests @@ -12,7 +13,7 @@ class OrderByTests public void OrderByArray() { Func lambda1 = (x => x*x); - var a = intArray.OrderByF(lambda1); + int[] a = intArray.OrderByF(lambda1); for (int i = 0; i < a.Length-1;i++) { Assert.That(lambda1(a[i]), Is.LessThanOrEqualTo(lambda1(a[i+1]))); @@ -23,7 +24,7 @@ public void OrderByArray() [Test] public void OrderByDescendingArray() { Func lambda1 = (x => x * x); - var a = intArray.OrderByDescendingF(lambda1); + int[] a = intArray.OrderByDescendingF(lambda1); for (int i = 0; i < a.Length - 1; i++) { Assert.That(lambda1(a[i]), Is.GreaterThanOrEqualTo(lambda1(a[i + 1]))); @@ -35,7 +36,7 @@ public void OrderByArray() [Test] public void OrderByList() { Func lambda1 = (x => x * x); - var a = intList.OrderByF(lambda1); + List a = intList.OrderByF(lambda1); for (int i = 0; i < a.Count - 1; i++) { Assert.That(lambda1(a[i]), Is.LessThanOrEqualTo(lambda1(a[i + 1]))); } @@ -45,7 +46,7 @@ public void OrderByArray() [Test] public void OrderByDescendingList() { Func lambda1 = (x => x * x); - var a = intList.OrderByDescendingF(lambda1); + List a = intList.OrderByDescendingF(lambda1); for (int i = 0; i < a.Count - 1; i++) { Assert.That(lambda1(a[i]), Is.GreaterThanOrEqualTo(lambda1(a[i + 1]))); } diff --git a/Tests/ParallelSIMDTests/SelectSIMDP.cs b/Tests/ParallelSIMDTests/SelectSIMDP.cs index 224c484..e495ba2 100644 --- a/Tests/ParallelSIMDTests/SelectSIMDP.cs +++ b/Tests/ParallelSIMDTests/SelectSIMDP.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using JM.LinqFaster.SIMD.Parallel; using System.Linq; @@ -10,8 +11,8 @@ class SelectSIMDPTests [Test] public void SelectSIMDP() { - var a = Test.intArray.SelectSP(x => x * x, x => x*x); - var b = Test.intArray.Select(x => x * x); + int[] a = Test.intArray.SelectSP(x => x * x, x => x*x); + IEnumerable b = Test.intArray.Select(x => x * x); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/ParallelSIMDTests/SequenceEqualsSIMDTests.cs b/Tests/ParallelSIMDTests/SequenceEqualsSIMDTests.cs index f651ddb..b725564 100644 --- a/Tests/ParallelSIMDTests/SequenceEqualsSIMDTests.cs +++ b/Tests/ParallelSIMDTests/SequenceEqualsSIMDTests.cs @@ -10,9 +10,9 @@ class SequenceEqualsSIMDParallelTests { [Test] public void SequenceEqualArray() { - var intArray2 = (int[])intArray.Clone(); - var a = LinqFasterSIMDParallel.SequenceEqualSP(intArray, intArray2); - var b = Enumerable.SequenceEqual(intArray, intArray2); + int[] intArray2 = (int[])intArray.Clone(); + bool a = LinqFasterSIMDParallel.SequenceEqualSP(intArray, intArray2); + bool b = Enumerable.SequenceEqual(intArray, intArray2); Assert.That(a, Is.EqualTo(b)); } @@ -20,10 +20,10 @@ public void SequenceEqualArray() [Test] public void SequenceNotEqualArray() { - var intArray2 = (int[])intArray.Clone(); + int[] intArray2 = (int[])intArray.Clone(); intArray2[3] = -10; - var a = LinqFasterSIMDParallel.SequenceEqualSP(intArray, intArray2); - var b = Enumerable.SequenceEqual(intArray, intArray2); + bool a = LinqFasterSIMDParallel.SequenceEqualSP(intArray, intArray2); + bool b = Enumerable.SequenceEqual(intArray, intArray2); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/ParallelSIMDTests/SumSIMDP.cs b/Tests/ParallelSIMDTests/SumSIMDP.cs index 254ab56..f1ed704 100644 --- a/Tests/ParallelSIMDTests/SumSIMDP.cs +++ b/Tests/ParallelSIMDTests/SumSIMDP.cs @@ -10,13 +10,13 @@ class SumSIMDP [Test] public void SumSIMDPArray() { - var a = Test.intArray.SumSP(); - var b = Test.intArray.Sum(); + int a = Test.intArray.SumSP(); + int b = Test.intArray.Sum(); Assert.That(a, Is.EqualTo(b)); - var c = Test.floatArray.SumSP(); - var d = Test.floatArray.Sum(); + float c = Test.floatArray.SumSP(); + float d = Test.floatArray.Sum(); // Assert.That(c, Is.EqualTo(d)); diff --git a/Tests/ParallelTests/AverageParallelTests.cs b/Tests/ParallelTests/AverageParallelTests.cs index 77ef034..a5dee48 100644 --- a/Tests/ParallelTests/AverageParallelTests.cs +++ b/Tests/ParallelTests/AverageParallelTests.cs @@ -12,8 +12,8 @@ class AverageParallel [Test] public void ParallelAverageArrayInt() { - var a = intArray.AverageP(); - var b = intArray.Average(); + double a = intArray.AverageP(); + double b = intArray.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -21,8 +21,8 @@ public void ParallelAverageArrayInt() [Test] public void ParallelAverageArrayLong() { - var a = longArray.AverageP(); - var b = longArray.Average(); + double a = longArray.AverageP(); + double b = longArray.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -30,27 +30,27 @@ public void ParallelAverageArrayLong() [Test] public void ParallelAverageArrayFloat() { - var a = floatArray.AverageP(); - var b = floatArray.Average(); - var diff = Math.Abs(a-b); + float a = floatArray.AverageP(); + float b = floatArray.Average(); + float diff = Math.Abs(a-b); Assert.That(diff, Is.LessThan(0.1f)); } [Test] public void ParallelAverageArrayDouble() { - var a = Test.doubleArray.AverageP(); - var b = Test.doubleArray.Average(); - var diff = Math.Abs(a-b); + double a = Test.doubleArray.AverageP(); + double b = Test.doubleArray.Average(); + double diff = Math.Abs(a-b); Assert.That(diff, Is.LessThan(0.1)); } [Test] public void ParallelAverageArrayDecimal() { - var a = decimalArray.AverageP(); - var b = decimalArray.Average(); - var diff = Math.Abs(a-b); + decimal a = decimalArray.AverageP(); + decimal b = decimalArray.Average(); + decimal diff = Math.Abs(a-b); Assert.That(diff, Is.LessThan(0.1)); } @@ -59,8 +59,8 @@ public void ParallelAverageArrayDecimal() public void ParallelAverageArrayString() { Func lambda = (x => int.Parse(x)); - var a = stringArray.AverageP(lambda); - var b = stringArray.Average(lambda); + float a = stringArray.AverageP(lambda); + float b = stringArray.Average(lambda); Assert.That(a, Is.EqualTo(b)); } @@ -72,8 +72,8 @@ public void ParallelAverageArrayString() [Test] public void ParallelAverageListInt() { - var a = intList.AverageP(); - var b = intList.Average(); + double a = intList.AverageP(); + double b = intList.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -81,8 +81,8 @@ public void ParallelAverageListInt() [Test] public void ParallelAverageListLong() { - var a = Test.longList.AverageP(); - var b = Test.longList.Average(); + double a = Test.longList.AverageP(); + double b = Test.longList.Average(); Assert.That(a, Is.EqualTo(b)); } @@ -90,27 +90,27 @@ public void ParallelAverageListLong() [Test] public void ParallelAverageListFloat() { - var a = floatList.AverageP(); - var b = floatList.Average(); - var diff = Math.Abs(a-b); + double a = floatList.AverageP(); + float b = floatList.Average(); + double diff = Math.Abs(a-b); Assert.That(diff, Is.LessThan(0.1f)); } [Test] public void ParallelAverageListDouble() { - var a = Test.doubleList.AverageP(); - var b = Test.doubleList.Average(); - var diff = Math.Abs(a-b); + double a = Test.doubleList.AverageP(); + double b = Test.doubleList.Average(); + double diff = Math.Abs(a-b); Assert.That(diff, Is.LessThan(0.1)); } [Test] public void ParallelAverageListDecimal() { - var a = decimalList.AverageP(); - var b = decimalList.Average(); - var diff = Math.Abs(a-b); + decimal a = decimalList.AverageP(); + decimal b = decimalList.Average(); + decimal diff = Math.Abs(a-b); Assert.That(diff, Is.LessThan(0.1)); } @@ -118,9 +118,9 @@ public void ParallelAverageListDecimal() public void ParallelAverageListString() { Func lambda = (x => int.Parse(x)); - var a = stringList.AverageP(lambda); - var b = stringList.Average(lambda); - var diff = Math.Abs(a-b); + double a = stringList.AverageP(lambda); + float b = stringList.Average(lambda); + double diff = Math.Abs(a-b); Assert.That(diff, Is.LessThan(0.1f)); } diff --git a/Tests/ParallelTests/ContainsParallelTests.cs b/Tests/ParallelTests/ContainsParallelTests.cs index 1dad0cd..4b81295 100644 --- a/Tests/ParallelTests/ContainsParallelTests.cs +++ b/Tests/ParallelTests/ContainsParallelTests.cs @@ -12,8 +12,8 @@ class ContainsParallel [Test] public void ParallelContainsStringArrayTrue() { - var a = stringArray.ContainsP("0", EqualityComparer.Default); - var b = stringArray.Contains("0", EqualityComparer.Default); + bool a = stringArray.ContainsP("0", EqualityComparer.Default); + bool b = stringArray.Contains("0", EqualityComparer.Default); Assert.That(a, Is.EqualTo(b)); } @@ -21,8 +21,8 @@ public void ParallelContainsStringArrayTrue() [Test] public void ParallelContainsStringArrayFalse() { - var a = stringArray.ContainsP("No Match", EqualityComparer.Default); - var b = stringArray.Contains("No Match", EqualityComparer.Default); + bool a = stringArray.ContainsP("No Match", EqualityComparer.Default); + bool b = stringArray.Contains("No Match", EqualityComparer.Default); Assert.That(a, Is.EqualTo(b)); } @@ -30,8 +30,8 @@ public void ParallelContainsStringArrayFalse() [Test] public void ParallelContainsStringListTrue() { - var a = stringList.ContainsP("0", EqualityComparer.Default); - var b = stringList.Contains("0", EqualityComparer.Default); + bool a = stringList.ContainsP("0", EqualityComparer.Default); + bool b = stringList.Contains("0", EqualityComparer.Default); Assert.That(a, Is.EqualTo(b)); } @@ -39,8 +39,8 @@ public void ParallelContainsStringListTrue() [Test] public void ParallelContainsStringListFalse() { - var a = stringList.ContainsP("no match", EqualityComparer.Default); - var b = stringList.Contains("no match", EqualityComparer.Default); + bool a = stringList.ContainsP("no match", EqualityComparer.Default); + bool b = stringList.Contains("no match", EqualityComparer.Default); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/ParallelTests/CountParallelTests.cs b/Tests/ParallelTests/CountParallelTests.cs index e377381..2805a9c 100644 --- a/Tests/ParallelTests/CountParallelTests.cs +++ b/Tests/ParallelTests/CountParallelTests.cs @@ -11,8 +11,8 @@ class CountParallel [Test] public void ParallelCountArray() { - var a = intArray.CountP(onlyEvenInts); - var b = intArray.Count(onlyEvenInts); + int a = intArray.CountP(onlyEvenInts); + int b = intArray.Count(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); } @@ -21,8 +21,8 @@ public void ParallelCountArray() [Test] public void ParallelCountList() { - var a = intList.CountP(onlyEvenInts); - var b = intList.Count(onlyEvenInts); + int a = intList.CountP(onlyEvenInts); + int b = intList.Count(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/ParallelTests/SelectParallelTests.cs b/Tests/ParallelTests/SelectParallelTests.cs index 4ae41e1..ded374c 100644 --- a/Tests/ParallelTests/SelectParallelTests.cs +++ b/Tests/ParallelTests/SelectParallelTests.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using JM.LinqFaster.Parallel; using System.Linq; using static Tests.Test; @@ -12,8 +13,8 @@ class SelectParallel [Test] public void ParallelSelectArray() { - var a = intArray.SelectP(x => x * x); - var b = intArray.Select(x => x * x); + int[] a = intArray.SelectP(x => x * x); + IEnumerable b = intArray.Select(x => x * x); Assert.That(a, Is.EqualTo(b)); @@ -26,8 +27,8 @@ public void ParallelSelectArray() [Test] public void ParallelSelectList() { - var a = intList.SelectP(x => x * x); - var b = intList.Select(x => x * x).ToList(); + List a = intList.SelectP(x => x * x); + List b = intList.Select(x => x * x).ToList(); Assert.That(a.Count, Is.Not.EqualTo(0)); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/ParallelTests/SelectWhereParallelTests.cs b/Tests/ParallelTests/SelectWhereParallelTests.cs index 431b090..21f4d77 100644 --- a/Tests/ParallelTests/SelectWhereParallelTests.cs +++ b/Tests/ParallelTests/SelectWhereParallelTests.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using JM.LinqFaster.Parallel; using System.Linq; using static Tests.Test; @@ -12,8 +13,8 @@ class SelectWhereParallel [Test] public void ParallelSelectWhereArray() { - var a = intArray.SelectWhereP(squaredInts, onlyEvenInts); - var b = intArray.Select(squaredInts).Where(onlyEvenInts); + int[] a = intArray.SelectWhereP(squaredInts, onlyEvenInts); + IEnumerable b = intArray.Select(squaredInts).Where(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); @@ -26,8 +27,8 @@ public void ParallelSelectWhereArray() [Test] public void ParallelSelectWhereList() { - var a = intList.SelectWhereP(squaredInts, onlyEvenInts); - var b = intList.Select(squaredInts).Where(onlyEvenInts); + List a = intList.SelectWhereP(squaredInts, onlyEvenInts); + IEnumerable b = intList.Select(squaredInts).Where(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/ParallelTests/SequenceEqualsTests.cs b/Tests/ParallelTests/SequenceEqualsTests.cs index 4cf4634..d728126 100644 --- a/Tests/ParallelTests/SequenceEqualsTests.cs +++ b/Tests/ParallelTests/SequenceEqualsTests.cs @@ -10,60 +10,60 @@ class SequenceEqualsParallelTests { [Test] public void SequenceEqualArray() { - var intArray2 = (int[])intArray.Clone(); - var a = LinqFasterParallel.SequenceEqualP(intArray, intArray2); - var b = Enumerable.SequenceEqual(intArray, intArray2); + int[] intArray2 = (int[])intArray.Clone(); + bool a = LinqFasterParallel.SequenceEqualP(intArray, intArray2); + bool b = Enumerable.SequenceEqual(intArray, intArray2); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceNotEqualArray() { - var intArray2 = (int[])intArray.Clone(); + int[] intArray2 = (int[])intArray.Clone(); intArray2[3] = -10; - var a = LinqFasterParallel.SequenceEqualP(intArray, intArray2); - var b = Enumerable.SequenceEqual(intArray, intArray2); + bool a = LinqFasterParallel.SequenceEqualP(intArray, intArray2); + bool b = Enumerable.SequenceEqual(intArray, intArray2); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceEqualList() { - var intList2 = intList.ToList(); - var a = LinqFasterParallel.SequenceEqualP(intList, intList2); - var b = Enumerable.SequenceEqual(intList, intList2); + List intList2 = intList.ToList(); + bool a = LinqFasterParallel.SequenceEqualP(intList, intList2); + bool b = Enumerable.SequenceEqual(intList, intList2); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceNotEqualList() { - var testList = intList.ToList(); + List testList = intList.ToList(); testList[3] = -10; - var a = LinqFasterParallel.SequenceEqualP(intList, testList); - var b = Enumerable.SequenceEqual(intList, testList); + bool a = LinqFasterParallel.SequenceEqualP(intList, testList); + bool b = Enumerable.SequenceEqual(intList, testList); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceEqualListAndArray() { - var a = LinqFasterParallel.SequenceEqualP(intList, intArray); - var b = Enumerable.SequenceEqual(intList, intArray); + bool a = LinqFasterParallel.SequenceEqualP(intList, intArray); + bool b = Enumerable.SequenceEqual(intList, intArray); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceNotEqualListAndArray() { - var testList = new List(); + List testList = new List(); int[] testArray = { 1, 2, 3, 4, }; testList.Add(1); testList.Add(2); testList.Add(3); - var a = LinqFasterParallel.SequenceEqualP(intArray, testList); - var b = Enumerable.SequenceEqual(intArray, testList); + bool a = LinqFasterParallel.SequenceEqualP(intArray, testList); + bool b = Enumerable.SequenceEqual(intArray, testList); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/ParallelTests/SumParallelTests.cs b/Tests/ParallelTests/SumParallelTests.cs index dea5cfe..9f2a502 100644 --- a/Tests/ParallelTests/SumParallelTests.cs +++ b/Tests/ParallelTests/SumParallelTests.cs @@ -12,21 +12,21 @@ class SumParallel [Test] public void ParallelSumArray() { - var a = intArray.SumP(); - var b = intArray.Sum(); + int a = intArray.SumP(); + int b = intArray.Sum(); Assert.That(a, Is.EqualTo(b)); - var c = floatArray.SumP(); - var d = floatArray.Sum(); + float c = floatArray.SumP(); + float d = floatArray.Sum(); - var diff = Math.Abs(c - d); + float diff = Math.Abs(c - d); Assert.That(diff, Is.LessThan(0.1)); - var e = decimalArray.SumP(); - var f = decimalArray.Sum(); + decimal e = decimalArray.SumP(); + decimal f = decimalArray.Sum(); - var diff2 = Math.Abs(e-f); + decimal diff2 = Math.Abs(e-f); Assert.That(diff2, Is.LessThan(0.1)); @@ -35,15 +35,15 @@ public void ParallelSumArray() [Test] public void ParallelSumArraySelector() { - var a = intArray.SumP(x => x + 1); - var b = intArray.Sum(x => x + 1); + int a = intArray.SumP(x => x + 1); + int b = intArray.Sum(x => x + 1); Assert.That(a, Is.EqualTo(b)); - var c = floatArray.SumP(squaredFloats); - var d = floatArray.Sum(squaredFloats); + float c = floatArray.SumP(squaredFloats); + float d = floatArray.Sum(squaredFloats); - var diff = Math.Abs(c - d); + float diff = Math.Abs(c - d); Assert.That(diff, Is.LessThan(0.1)); } @@ -51,36 +51,36 @@ public void ParallelSumArraySelector() [Test] public void ParallelSumList() { - var a = intList.SumP(); - var b = intList.Sum(); + int a = intList.SumP(); + int b = intList.Sum(); Assert.That(a, Is.EqualTo(b)); - var c = floatList.SumP(); - var d = floatList.Sum(); + float c = floatList.SumP(); + float d = floatList.Sum(); - var diff = Math.Abs(c - d); + float diff = Math.Abs(c - d); Assert.That(diff, Is.LessThan(0.1)); - var e = decimalList.SumP(); - var f = decimalList.Sum(); + decimal e = decimalList.SumP(); + decimal f = decimalList.Sum(); - var diff2 = Math.Abs(e - f); + decimal diff2 = Math.Abs(e - f); Assert.That(diff2, Is.LessThan(0.1)); } [Test] public void ParallelSumListSelector() { - var a = intList.SumP(x => x + 1); - var b = intList.Sum(x => x + 1); + int a = intList.SumP(x => x + 1); + int b = intList.Sum(x => x + 1); Assert.That(a, Is.EqualTo(b)); - var c = floatList.SumP(squaredFloats); - var d = floatList.Sum(squaredFloats); + float c = floatList.SumP(squaredFloats); + float d = floatList.Sum(squaredFloats); - var diff = Math.Abs(c - d); + float diff = Math.Abs(c - d); Assert.That(diff, Is.LessThan(0.1)); } diff --git a/Tests/ParallelTests/WhereAggregateParallelTests.cs b/Tests/ParallelTests/WhereAggregateParallelTests.cs index 8a1d10c..5f80499 100644 --- a/Tests/ParallelTests/WhereAggregateParallelTests.cs +++ b/Tests/ParallelTests/WhereAggregateParallelTests.cs @@ -12,12 +12,12 @@ class WhereAggregateParallel [Test] public void ParallelWhereAggregateSumArray() { - var a = + int a = intArray.WhereAggregateP(onlyEvenInts, 0, (acc, x) => acc += x); - var b = intArray.WhereAggregateP(onlyEvenInts, (acc, x) => acc += x); + int b = intArray.WhereAggregateP(onlyEvenInts, (acc, x) => acc += x); - var c = intArray.Where(onlyEvenInts).Sum(); + int c = intArray.Where(onlyEvenInts).Sum(); Assert.That(a, Is.EqualTo(c)); Assert.That(b, Is.EqualTo(c)); @@ -27,11 +27,11 @@ public void ParallelWhereAggregateSumArray() [Test] public void ParallelWhereAggregateSelectorArray() { - var a = + int a = intArray.WhereAggregateP(onlyEvenInts, 0, (acc, x) => acc += x, acc => acc / 2); - var b = intArray.Where(onlyEvenInts).Sum() / 2; + int b = intArray.Where(onlyEvenInts).Sum() / 2; Assert.That(a, Is.EqualTo(b)); @@ -41,12 +41,12 @@ public void ParallelWhereAggregateSelectorArray() [Test] public void ParallelWhereAggregateSumList() { - var a = + int a = intList.WhereAggregateP(onlyEvenInts, 0, (acc, x) => acc += x); - var b = intList.WhereAggregateP(onlyEvenInts, (acc, x) => acc += x); + int b = intList.WhereAggregateP(onlyEvenInts, (acc, x) => acc += x); - var c = intList.Where(onlyEvenInts).Sum(); + int c = intList.Where(onlyEvenInts).Sum(); Assert.That(a, Is.EqualTo(c)); Assert.That(b, Is.EqualTo(c)); @@ -56,11 +56,11 @@ public void ParallelWhereAggregateSumList() [Test] public void ParallelWhereAggregateSelectorList() { - var a = + int a = intList.WhereAggregateP(onlyEvenInts, 0, (acc, x) => acc += x, acc => acc / 2); - var b = intList.Where(onlyEvenInts).Sum() / 2; + int b = intList.Where(onlyEvenInts).Sum() / 2; Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/ParallelTests/WhereParallelTEsts.cs b/Tests/ParallelTests/WhereParallelTEsts.cs index 902b5c9..1cbb4f0 100644 --- a/Tests/ParallelTests/WhereParallelTEsts.cs +++ b/Tests/ParallelTests/WhereParallelTEsts.cs @@ -3,6 +3,7 @@ using System.Linq; using static Tests.Test; using System; +using System.Collections.Generic; namespace Tests { @@ -12,13 +13,13 @@ class WhereParallel [Test] public void ParallelWhereEmpty() { - var emptyArray = new int[0]; + int[] emptyArray = new int[0]; Assert.DoesNotThrow(() => { - var a = emptyArray.WhereP(x => x == 0); - var emptyList = new System.Collections.Generic.List(0); - var b = emptyList.WhereP(x => x == 0); + int[] a = emptyArray.WhereP(x => x == 0); + List emptyList = new System.Collections.Generic.List(0); + List b = emptyList.WhereP(x => x == 0); }); } @@ -27,12 +28,12 @@ public void ParallelWhereEmpty() public void ParallelWhereArray() { Func lambda1 = ((x, i) => x + i % 2 == 0); - var a = intArray.WhereP(lambda1); - var b = intArray.Where(lambda1); + int[] a = intArray.WhereP(lambda1); + IEnumerable b = intArray.Where(lambda1); Assert.That(a, Is.EqualTo(b)); - var c = stringArray.WhereP(x => x == "no matches"); - var d = stringArray.Where(x => x == "no matches"); + string[] c = stringArray.WhereP(x => x == "no matches"); + IEnumerable d = stringArray.Where(x => x == "no matches"); } @@ -40,13 +41,13 @@ public void ParallelWhereArray() public void ParallelWhereList() { Func lambda1 = ((x, i) => x + i % 2 == 0); - var a = intList.WhereP(lambda1); - var b = intList.Where(lambda1); + List a = intList.WhereP(lambda1); + IEnumerable b = intList.Where(lambda1); Assert.That(a, Is.EqualTo(b)); - var c = stringList.WhereP(x => x == "no matches"); - var d = stringList.Where(x => x == "no matches"); + List c = stringList.WhereP(x => x == "no matches"); + IEnumerable d = stringList.Where(x => x == "no matches"); } diff --git a/Tests/ParallelTests/WhereSelectParallelTests.cs b/Tests/ParallelTests/WhereSelectParallelTests.cs index 583b9f7..2417536 100644 --- a/Tests/ParallelTests/WhereSelectParallelTests.cs +++ b/Tests/ParallelTests/WhereSelectParallelTests.cs @@ -3,6 +3,7 @@ using System.Linq; using static Tests.Test; using System; +using System.Collections.Generic; namespace Tests { @@ -12,14 +13,14 @@ class WhereSelectParallel [Test] public void ParallelWhereSelectArray() { - var a = intArray.WhereSelectP(onlyEvenInts, squaredInts); - var b = intArray.Where(onlyEvenInts).Select(squaredInts); + int[] a = intArray.WhereSelectP(onlyEvenInts, squaredInts); + IEnumerable b = intArray.Where(onlyEvenInts).Select(squaredInts); Assert.That(a, Is.EqualTo(b)); Func lambda2 = (x => x == "no matches"); - var c = stringArray.WhereSelectP(lambda2, x => x + "append"); - var d = stringArray.Where(lambda2).Select(x => x + "append"); + string[] c = stringArray.WhereSelectP(lambda2, x => x + "append"); + IEnumerable d = stringArray.Where(lambda2).Select(x => x + "append"); Assert.That(c, Is.EqualTo(d)); @@ -28,22 +29,22 @@ public void ParallelWhereSelectArray() [Test] public void ParallelWhereSelectIndexArray() { - var a = intArray.WhereSelectP((x, i) => x + i % 2 == 0, (x, i) => x + i); - var b = intArray.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); + int[] a = intArray.WhereSelectP((x, i) => x + i % 2 == 0, (x, i) => x + i); + IEnumerable b = intArray.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); Assert.That(a, Is.EqualTo(b)); } [Test] public void ParallelWhereSelectList() { - var a = intList.WhereSelectP(onlyEvenInts, squaredInts); - var b = intList.Where(onlyEvenInts).Select(squaredInts); + List a = intList.WhereSelectP(onlyEvenInts, squaredInts); + IEnumerable b = intList.Where(onlyEvenInts).Select(squaredInts); Assert.That(a, Is.EqualTo(b)); Func lambda2 = (x => x == "no matches"); - var c = stringList.WhereSelectP(lambda2, x => x + "append"); - var d = stringList.Where(lambda2).Select(x => x + "append"); + List c = stringList.WhereSelectP(lambda2, x => x + "append"); + IEnumerable d = stringList.Where(lambda2).Select(x => x + "append"); Assert.That(c, Is.EqualTo(d)); @@ -52,8 +53,8 @@ public void ParallelWhereSelectList() [Test] public void ParallelWhereSelectIndexList() { - var a = intList.WhereSelectP((x, i) => x + i % 2 == 0, (x, i) => x + i); - var b = intList.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); + List a = intList.WhereSelectP((x, i) => x + i % 2 == 0, (x, i) => x + i); + IEnumerable b = intList.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/RangeTests.cs b/Tests/RangeTests.cs index eaa4fde..2932381 100644 --- a/Tests/RangeTests.cs +++ b/Tests/RangeTests.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using JM.LinqFaster; using System.Linq; @@ -10,8 +11,8 @@ class RangeTests [Test] public void RangeArray() { - var a = LinqFaster.RangeArrayF(-100, 200); - var b = Enumerable.Range(-100, 200).ToArray(); + int[] a = LinqFaster.RangeArrayF(-100, 200); + int[] b = Enumerable.Range(-100, 200).ToArray(); Assert.That(a, Is.EqualTo(b)); } @@ -19,8 +20,8 @@ public void RangeArray() [Test] public void RangeList() { - var a = LinqFaster.RangeListF(-100, 200); - var b = Enumerable.Range(-100, 200).ToList(); + List a = LinqFaster.RangeListF(-100, 200); + List b = Enumerable.Range(-100, 200).ToList(); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/RepeatTests.cs b/Tests/RepeatTests.cs index 563b340..362966a 100644 --- a/Tests/RepeatTests.cs +++ b/Tests/RepeatTests.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using JM.LinqFaster; using NUnit.Framework; @@ -9,8 +10,8 @@ class RepeatTests { [Test] public void RepeatArray() { - var a = LinqFaster.RepeatArrayF(2.0f, 10); - var b = Enumerable.Repeat(2.0f, 10).ToList(); + float[] a = LinqFaster.RepeatArrayF(2.0f, 10); + List b = Enumerable.Repeat(2.0f, 10).ToList(); Assert.That(a, Is.EqualTo(b)); } @@ -18,8 +19,8 @@ class RepeatTests [Test] public void RepeatList() { - var a = LinqFaster.RepeatListF(2.0f, 10); - var b = Enumerable.Repeat(2.0f, 10).ToList(); + List a = LinqFaster.RepeatListF(2.0f, 10); + List b = Enumerable.Repeat(2.0f, 10).ToList(); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/ReverseTests.cs b/Tests/ReverseTests.cs index e92f9c6..848e345 100644 --- a/Tests/ReverseTests.cs +++ b/Tests/ReverseTests.cs @@ -2,6 +2,7 @@ using JM.LinqFaster; using System.Linq; using System; +using System.Collections.Generic; using static Tests.Test; namespace Tests @@ -11,9 +12,9 @@ class ReverseTests { [Test] public void ReverseArray() { - var a = intArray.ReverseF(); - var aSpan = intArray.AsSpan().ReverseF(); - var b = intArray.Reverse(); + int[] a = intArray.ReverseF(); + int[] aSpan = intArray.AsSpan().ReverseF(); + IEnumerable b = intArray.Reverse(); Assert.That(a, Is.EqualTo(b)); Assert.That(aSpan, Is.EqualTo(b)); @@ -21,8 +22,8 @@ class ReverseTests { [Test] public void ReverseList() { - var a = intList.ReverseF(); - var b = intList.Select(x => x).ToList(); + List a = intList.ReverseF(); + List b = intList.Select(x => x).ToList(); b.Reverse(); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SIMDTests/AverageSIMDTests.cs b/Tests/SIMDTests/AverageSIMDTests.cs index 040ff99..e8323b2 100644 --- a/Tests/SIMDTests/AverageSIMDTests.cs +++ b/Tests/SIMDTests/AverageSIMDTests.cs @@ -13,8 +13,8 @@ class AverageSIMDTests [Test] public void AverageSIMDInts() { - var a = Test.intArray.Average(); - var b = Test.intArray.AverageS(); + double a = Test.intArray.Average(); + double b = Test.intArray.AverageS(); double diff = Math.Abs(a - b); Assert.That(diff, Is.LessThan(0.1)); } @@ -22,8 +22,8 @@ public void AverageSIMDInts() [Test] public void AverageSIMDFloats() { - var a = Test.floatArray.Average(); - var b = Test.floatArray.AverageSf(); + float a = Test.floatArray.Average(); + float b = Test.floatArray.AverageSf(); double diff = Math.Abs(a - b); Assert.That(diff, Is.LessThan(0.1)); } @@ -31,8 +31,8 @@ public void AverageSIMDFloats() [Test] public void AverageBySIMDInts() { - var a = Test.intArray.Average(x => x - 1); - var b = Test.intArray.AverageS(x => x - new Vector(1)); + double a = Test.intArray.Average(x => x - 1); + double b = Test.intArray.AverageS(x => x - new Vector(1)); double diff = Math.Abs(a - b); Assert.That(diff, Is.LessThan(0.1)); } diff --git a/Tests/SIMDTests/ContainsSIMDTests.cs b/Tests/SIMDTests/ContainsSIMDTests.cs index 3487b2d..b0b29ea 100644 --- a/Tests/SIMDTests/ContainsSIMDTests.cs +++ b/Tests/SIMDTests/ContainsSIMDTests.cs @@ -11,8 +11,8 @@ class ContainsSIMDTests [Test] public void ContainsSIMDYes() { - var a = Test.intArray.Contains(0); - var b = Test.intArray.ContainsS(0); + bool a = Test.intArray.Contains(0); + bool b = Test.intArray.ContainsS(0); Assert.That(a, Is.EqualTo(b)); } @@ -20,8 +20,8 @@ public void ContainsSIMDYes() [Test] public void ContainsSIMDNo() { - var a = Test.longArray.Contains(9999999); - var b = Test.longArray.ContainsS(9999999); + bool a = Test.longArray.Contains(9999999); + bool b = Test.longArray.ContainsS(9999999); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SIMDTests/MaxSIMDTests.cs b/Tests/SIMDTests/MaxSIMDTests.cs index 3c89fab..c2e3099 100644 --- a/Tests/SIMDTests/MaxSIMDTests.cs +++ b/Tests/SIMDTests/MaxSIMDTests.cs @@ -11,8 +11,8 @@ class MaxSIMDTests [Test] public void MaxSIMDInts() { - var a = Test.intArray.MaxS(); - var b = Test.intArray.Max(); + int a = Test.intArray.MaxS(); + int b = Test.intArray.Max(); Assert.That(a, Is.EqualTo(b)); } @@ -20,8 +20,8 @@ public void MaxSIMDInts() [Test] public void MaxSIMDLongs() { - var a = Test.longArray.MaxS(); - var b = Test.longArray.Max(); + long a = Test.longArray.MaxS(); + long b = Test.longArray.Max(); Assert.That(a, Is.EqualTo(b)); } @@ -29,8 +29,8 @@ public void MaxSIMDLongs() [Test] public void MaxSIMDDoubles() { - var a = Test.doubleArray.MaxS(); - var b = Test.doubleArray.Max(); + double a = Test.doubleArray.MaxS(); + double b = Test.doubleArray.Max(); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SIMDTests/MinSIMDTests.cs b/Tests/SIMDTests/MinSIMDTests.cs index 5644294..ee5edbe 100644 --- a/Tests/SIMDTests/MinSIMDTests.cs +++ b/Tests/SIMDTests/MinSIMDTests.cs @@ -11,8 +11,8 @@ class MinSIMDTests [Test] public void MinSIMDLongs() { - var a = Test.longArray.MinS(); - var b = Test.longArray.Min(); + long a = Test.longArray.MinS(); + long b = Test.longArray.Min(); Assert.That(a, Is.EqualTo(b)); } @@ -20,8 +20,8 @@ public void MinSIMDLongs() [Test] public void MinSIMDFloats() { - var a = Test.floatArray.MinS(); - var b = Test.floatArray.Min(); + float a = Test.floatArray.MinS(); + float b = Test.floatArray.Min(); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SIMDTests/RangeSIMDTests.cs b/Tests/SIMDTests/RangeSIMDTests.cs index a8d5eae..69998bf 100644 --- a/Tests/SIMDTests/RangeSIMDTests.cs +++ b/Tests/SIMDTests/RangeSIMDTests.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using JM.LinqFaster.SIMD; using System.Linq; @@ -11,8 +12,8 @@ class RangeSIMDTests [Test] public void RangeSIMD() { - var a = LinqFasterSIMD.RangeS(-100, 100); - var b = Enumerable.Range(-100, 100); + int[] a = LinqFasterSIMD.RangeS(-100, 100); + IEnumerable b = Enumerable.Range(-100, 100); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SIMDTests/RepeatTests.cs b/Tests/SIMDTests/RepeatTests.cs index b51a015..5f9f9bf 100644 --- a/Tests/SIMDTests/RepeatTests.cs +++ b/Tests/SIMDTests/RepeatTests.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using JM.LinqFaster.SIMD; using System.Linq; @@ -11,8 +12,8 @@ class RepeatSIMDTests [Test] public void RepeatSIMD() { - var a = LinqFasterSIMD.RepeatS(4.0, 1000); - var b = Enumerable.Repeat(4.0, 1000); + double[] a = LinqFasterSIMD.RepeatS(4.0, 1000); + IEnumerable b = Enumerable.Repeat(4.0, 1000); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SIMDTests/SelectSIMDTests.cs b/Tests/SIMDTests/SelectSIMDTests.cs index 4db413d..326e73c 100644 --- a/Tests/SIMDTests/SelectSIMDTests.cs +++ b/Tests/SIMDTests/SelectSIMDTests.cs @@ -11,8 +11,8 @@ class SelectSIMDTests [Test] public void SelectSIMD() { - var a = Test.intArray.Select(x => x * x).ToArray(); - var b = Test.intArray.SelectS(x => x * x); + int[] a = Test.intArray.Select(x => x * x).ToArray(); + int[] b = Test.intArray.SelectS(x => x * x); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SIMDTests/SequenceEqualsSIMDTests.cs b/Tests/SIMDTests/SequenceEqualsSIMDTests.cs index 5342890..75e5421 100644 --- a/Tests/SIMDTests/SequenceEqualsSIMDTests.cs +++ b/Tests/SIMDTests/SequenceEqualsSIMDTests.cs @@ -10,9 +10,9 @@ class SequenceEqualsSIMDTests { [Test] public void SequenceEqualArray() { - var intArray2 = (int[])intArray.Clone(); - var a = LinqFasterSIMD.SequenceEqualS(intArray, intArray2); - var b = Enumerable.SequenceEqual(intArray, intArray2); + int[] intArray2 = (int[])intArray.Clone(); + bool a = LinqFasterSIMD.SequenceEqualS(intArray, intArray2); + bool b = Enumerable.SequenceEqual(intArray, intArray2); Assert.That(a, Is.EqualTo(b)); } @@ -20,10 +20,10 @@ public void SequenceEqualArray() [Test] public void SequenceNotEqualArray() { - var intArray2 = (int[])intArray.Clone(); + int[] intArray2 = (int[])intArray.Clone(); intArray2[3] = -10; - var a = LinqFasterSIMD.SequenceEqualS(intArray, intArray2); - var b = Enumerable.SequenceEqual(intArray, intArray2); + bool a = LinqFasterSIMD.SequenceEqualS(intArray, intArray2); + bool b = Enumerable.SequenceEqual(intArray, intArray2); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SIMDTests/SumSIMDTests.cs b/Tests/SIMDTests/SumSIMDTests.cs index f50478a..40b07bb 100644 --- a/Tests/SIMDTests/SumSIMDTests.cs +++ b/Tests/SIMDTests/SumSIMDTests.cs @@ -12,8 +12,8 @@ class SumSIMDTests [Test] public void SumSIMDInts() { - var a = Test.intArray.Sum(); - var b = Test.intArray.SumS(); + int a = Test.intArray.Sum(); + int b = Test.intArray.SumS(); Assert.That(a, Is.EqualTo(b)); } @@ -21,8 +21,8 @@ public void SumSIMDInts() [Test] public void SumSIMDFloats() { - var a = Test.floatArray.Sum(); - var b = Test.floatArray.SumS(); + float a = Test.floatArray.Sum(); + float b = Test.floatArray.SumS(); double diff = Math.Abs(a - b); Assert.That(diff, Is.LessThan(0.1)); } @@ -31,8 +31,8 @@ public void SumSIMDFloats() [Test] public void SumBySIMDFloats() { - var a = Test.floatArray.Sum(x => x * x); - var b = Test.floatArray.SumS(x => x * x); + float a = Test.floatArray.Sum(x => x * x); + float b = Test.floatArray.SumS(x => x * x); double diff = Math.Abs(a - b); Assert.That(diff, Is.LessThan(0.15)); diff --git a/Tests/SelectManyTests.cs b/Tests/SelectManyTests.cs index 05bd3dc..4ac04e1 100644 --- a/Tests/SelectManyTests.cs +++ b/Tests/SelectManyTests.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using JM.LinqFaster; using System.Linq; using static Tests.Test; @@ -12,8 +13,8 @@ class SelectManyTests [Test] public void SelectManyArray() { - var a = floatArray.SelectManyF(x => LinqFaster.RepeatArrayF(x, 2)); - var b = floatArray.SelectMany(x => Enumerable.Repeat(x, 2).ToArray()).ToArray(); + float[] a = floatArray.SelectManyF(x => LinqFaster.RepeatArrayF(x, 2)); + float[] b = floatArray.SelectMany(x => Enumerable.Repeat(x, 2).ToArray()).ToArray(); Assert.That(a, Is.EqualTo(b)); @@ -26,8 +27,8 @@ public void SelectManyArray() [Test] public void SelectManyList() { - var a = floatList.SelectManyF(x => LinqFaster.RepeatListF(x, 2)); - var b = floatList.SelectMany(x => Enumerable.Repeat(x, 2).ToList()).ToList(); + List a = floatList.SelectManyF(x => LinqFaster.RepeatListF(x, 2)); + List b = floatList.SelectMany(x => Enumerable.Repeat(x, 2).ToList()).ToList(); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/SelectTEsts.cs b/Tests/SelectTEsts.cs index 50fe770..719e524 100644 --- a/Tests/SelectTEsts.cs +++ b/Tests/SelectTEsts.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using NUnit.Framework; using JM.LinqFaster; using System.Linq; @@ -12,11 +13,11 @@ class SelectTests [Test] public void SelectArray() { - var a = intArray.SelectF(x => x * x); - var b = intArray.Select(x => x * x); + int[] a = intArray.SelectF(x => x * x); + IEnumerable b = intArray.Select(x => x * x); Assert.That(a, Is.EqualTo(b)); - var b1 = Array.AsReadOnly(intArray).SumF(x => x * x); + int b1 = Array.AsReadOnly(intArray).SumF(x => x * x); a = intArray.SelectF((x, i) => x + i); b = intArray.Select((x, i) => x + i); @@ -27,11 +28,11 @@ public void SelectArray() [Test] public void SelectSumArray() { - var a = intArray.SelectF(x => x * x); - var b = intArray.Select(x => x * x); + int[] a = intArray.SelectF(x => x * x); + IEnumerable b = intArray.Select(x => x * x); Assert.That(a, Is.EqualTo(b)); - var b1 = Array.AsReadOnly(intArray).SumF(x => x * x); + int b1 = Array.AsReadOnly(intArray).SumF(x => x * x); a = intArray.SelectF((x, i) => x + i); b = intArray.Select((x, i) => x + i); @@ -42,8 +43,8 @@ public void SelectSumArray() [Test] public void SelectList() { - var a = intList.SelectF(x => x * x); - var b = intList.Select(x => x * x).ToList(); + List a = intList.SelectF(x => x * x); + List b = intList.Select(x => x * x).ToList(); Assert.That(a.Count, Is.Not.EqualTo(0)); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/SelectWhereTests.cs b/Tests/SelectWhereTests.cs index b827ef4..a9d8577 100644 --- a/Tests/SelectWhereTests.cs +++ b/Tests/SelectWhereTests.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using JM.LinqFaster; using System.Linq; using static Tests.Test; @@ -11,8 +12,8 @@ class SelectWhereTests [Test] public void SelectWhereArray() { - var a = intArray.SelectWhereF(squaredInts,onlyEvenInts); - var b = intArray.Select(squaredInts).Where(onlyEvenInts); + int[] a = intArray.SelectWhereF(squaredInts,onlyEvenInts); + IEnumerable b = intArray.Select(squaredInts).Where(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); @@ -24,8 +25,8 @@ public void SelectWhereArray() [Test] public void SelectWhereList() { - var a = intList.SelectWhereF(squaredInts, onlyEvenInts); - var b = intList.Select(squaredInts).Where(onlyEvenInts); + List a = intList.SelectWhereF(squaredInts, onlyEvenInts); + IEnumerable b = intList.Select(squaredInts).Where(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/SequenceEqualsTests.cs b/Tests/SequenceEqualsTests.cs index 4d78c16..348e9bb 100644 --- a/Tests/SequenceEqualsTests.cs +++ b/Tests/SequenceEqualsTests.cs @@ -10,60 +10,60 @@ class SequenceEqualsTests { [Test] public void SequenceEqualArray() { - var intArray2 = (int[])intArray.Clone(); - var a = LinqFaster.SequenceEqualF(intArray, intArray2); - var b = Enumerable.SequenceEqual(intArray, intArray2); + int[] intArray2 = (int[])intArray.Clone(); + bool a = LinqFaster.SequenceEqualF(intArray, intArray2); + bool b = Enumerable.SequenceEqual(intArray, intArray2); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceNotEqualArray() { - var intArray2 = (int[])intArray.Clone(); + int[] intArray2 = (int[])intArray.Clone(); intArray2[3] = -10; - var a = LinqFaster.SequenceEqualF(intArray, intArray2); - var b = Enumerable.SequenceEqual(intArray, intArray2); + bool a = LinqFaster.SequenceEqualF(intArray, intArray2); + bool b = Enumerable.SequenceEqual(intArray, intArray2); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceEqualList() { - var intList2 = intList.ToList(); - var a = LinqFaster.SequenceEqualF(intList, intList2); - var b = Enumerable.SequenceEqual(intList, intList2); + List intList2 = intList.ToList(); + bool a = LinqFaster.SequenceEqualF(intList, intList2); + bool b = Enumerable.SequenceEqual(intList, intList2); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceNotEqualList() { - var testList = intList.ToList(); + List testList = intList.ToList(); testList[3] = -10; - var a = LinqFaster.SequenceEqualF(intList, testList); - var b = Enumerable.SequenceEqual(intList, testList); + bool a = LinqFaster.SequenceEqualF(intList, testList); + bool b = Enumerable.SequenceEqual(intList, testList); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceEqualListAndArray() { - var a = LinqFaster.SequenceEqualF(intList, intArray); - var b = Enumerable.SequenceEqual(intList, intArray); + bool a = LinqFaster.SequenceEqualF(intList, intArray); + bool b = Enumerable.SequenceEqual(intList, intArray); Assert.That(a, Is.EqualTo(b)); } [Test] public void SequenceNotEqualListAndArray() { - var testList = new List(); + List testList = new List(); int[] testArray = { 1, 2, 3, 4, }; testList.Add(1); testList.Add(2); testList.Add(3); - var a = LinqFaster.SequenceEqualF(intArray, testList); - var b = Enumerable.SequenceEqual(intArray, testList); + bool a = LinqFaster.SequenceEqualF(intArray, testList); + bool b = Enumerable.SequenceEqual(intArray, testList); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SingleTests.cs b/Tests/SingleTests.cs index 929945b..3976896 100644 --- a/Tests/SingleTests.cs +++ b/Tests/SingleTests.cs @@ -37,8 +37,8 @@ class SingleTests { public void SingleArrayOne() { int[] test = { 4 }; - var a = test.SingleF(); - var b = test.SingleF(onlyEvenInts); + int a = test.SingleF(); + int b = test.SingleF(onlyEvenInts); Assert.That(a, Is.EqualTo(4)); Assert.That(b, Is.EqualTo(4)); @@ -49,8 +49,8 @@ class SingleTests { public void SingleArrayDefaultOne() { int[] test = { 4 }; - var a = test.SingleOrDefaultF(); - var b = test.SingleOrDefaultF(onlyEvenInts); + int a = test.SingleOrDefaultF(); + int b = test.SingleOrDefaultF(onlyEvenInts); Assert.That(a, Is.EqualTo(4)); Assert.That(b, Is.EqualTo(4)); @@ -60,8 +60,8 @@ class SingleTests { public void SingleArrayDefaultEmpty() { int[] test = { }; - var a = test.SingleOrDefaultF(); - var b = test.SingleOrDefaultF(onlyEvenInts); + int a = test.SingleOrDefaultF(); + int b = test.SingleOrDefaultF(onlyEvenInts); Assert.That(a, Is.EqualTo(0)); Assert.That(b, Is.EqualTo(0)); @@ -85,8 +85,8 @@ class SingleTests { public void SingleListOne() { List test = new List(); test.Add(4); - var a = test.SingleF(); - var b = test.SingleF(onlyEvenInts); + int a = test.SingleF(); + int b = test.SingleF(onlyEvenInts); Assert.That(a, Is.EqualTo(4)); Assert.That(b, Is.EqualTo(4)); @@ -97,8 +97,8 @@ class SingleTests { List test = new List(); test.Add(4); - var a = test.SingleOrDefaultF(); - var b = test.SingleOrDefaultF(onlyEvenInts); + int a = test.SingleOrDefaultF(); + int b = test.SingleOrDefaultF(onlyEvenInts); Assert.That(a, Is.EqualTo(4)); Assert.That(b, Is.EqualTo(4)); @@ -108,8 +108,8 @@ class SingleTests { public void SingleListDefaultEmpty() { List test = new List(); - var a = test.SingleOrDefaultF(); - var b = test.SingleOrDefaultF(onlyEvenInts); + int a = test.SingleOrDefaultF(); + int b = test.SingleOrDefaultF(onlyEvenInts); Assert.That(a, Is.EqualTo(0)); Assert.That(b, Is.EqualTo(0)); } diff --git a/Tests/SkipTests.cs b/Tests/SkipTests.cs index ddce04e..dfd1ac3 100644 --- a/Tests/SkipTests.cs +++ b/Tests/SkipTests.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using JM.LinqFaster; using System.Linq; using static Tests.Test; @@ -13,16 +14,16 @@ class SkipTests { [TestCase(5)] [TestCase(Test.TEST_SIZE)] public void SkipArray(int count) { - var a = intArray.SkipF(count); - var b = intArray.Skip(count); + int[] a = intArray.SkipF(count); + IEnumerable b = intArray.Skip(count); Assert.That(a, Is.EqualTo(b)); } [Test] public void SkipWhileArray() { - var a = intArray.SkipWhileF(onlyEvenInts); - var b = intArray.SkipWhile(onlyEvenInts); + int[] a = intArray.SkipWhileF(onlyEvenInts); + IEnumerable b = intArray.SkipWhile(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); } @@ -32,16 +33,16 @@ class SkipTests { [TestCase(5)] [TestCase(Test.TEST_SIZE)] public void SkipList(int count) { - var a = intList.SkipF(count); - var b = intList.Skip(count); + List a = intList.SkipF(count); + IEnumerable b = intList.Skip(count); Assert.That(a, Is.EqualTo(b)); } [Test] public void SkipWhileList() { - var a = intList.SkipWhileF(onlyEvenInts); - var b = intList.SkipWhile(onlyEvenInts); + List a = intList.SkipWhileF(onlyEvenInts); + IEnumerable b = intList.SkipWhile(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SumTests.cs b/Tests/SumTests.cs index da29164..b0b4542 100644 --- a/Tests/SumTests.cs +++ b/Tests/SumTests.cs @@ -16,36 +16,36 @@ internal class SumTests [Test] public void SumArray() { - var a = ((IReadOnlyList)intArray).SumF(); + int a = ((IReadOnlyList)intArray).SumF(); - var b = intArray.Sum(); + int b = intArray.Sum(); Assert.That(a, Is.EqualTo(b)); - var an = ((IReadOnlyList)intNullArray).SumF(); - var bn = intNullArray.Sum(); + int? an = ((IReadOnlyList)intNullArray).SumF(); + int? bn = intNullArray.Sum(); Assert.That(an, Is.EqualTo(bn)); - var c = floatArray.SumF(); - var d = floatArray.Sum(); + float c = floatArray.SumF(); + float d = floatArray.Sum(); Assert.That(c, Is.EqualTo(d)); - var dn = floatNullArray.SumF(); + float? dn = floatNullArray.SumF(); Assert.That(c, Is.EqualTo(dn)); - var e = decimalArray.SumF(); - var f = decimalArray.Sum(); + decimal e = decimalArray.SumF(); + decimal f = decimalArray.Sum(); Assert.That(e, Is.EqualTo(f)); - var g = byteArray.SumF(); - var h = byteArray.Aggregate(0U, (current, b1) => current + b1); + uint g = byteArray.SumF(); + uint h = byteArray.Aggregate(0U, (current, b1) => current + b1); Assert.That(g, Is.EqualTo(h)); - var i = shortArray.SumF(); - var j = shortArray.Aggregate(0, (current, s1) => current + s1); + int i = shortArray.SumF(); + int j = shortArray.Aggregate(0, (current, s1) => current + s1); Assert.That(i, Is.EqualTo(j)); - var k = doubleArray.SumF(); - var l = doubleArray.Sum(); + double k = doubleArray.SumF(); + double l = doubleArray.Sum(); Assert.That(k, Is.EqualTo(l)); - var ln = doubleNullArray.SumF(); + double? ln = doubleNullArray.SumF(); Assert.That(k, Is.EqualTo(ln)); @@ -55,19 +55,19 @@ public void SumArray() [Test] public void SumArraySelector() { - var a = intArray.SumF(x => x + 1); - var b = intArray.Sum(x => x + 1); + int a = intArray.SumF(x => x + 1); + int b = intArray.Sum(x => x + 1); Assert.That(a, Is.EqualTo(b)); - var br = Array.AsReadOnly(intArray).SumF(x => x + 1); + int br = Array.AsReadOnly(intArray).SumF(x => x + 1); Assert.That(a, Is.EqualTo(br)); - var an = intNullArray.SumF(x => x ?? 0); - var bn = intNullArray.Sum(x => x ?? 0); + int an = intNullArray.SumF(x => x ?? 0); + int bn = intNullArray.Sum(x => x ?? 0); Assert.That(an, Is.EqualTo(bn)); - var c = floatArray.SumF(squaredFloats); - var d = floatArray.Sum(squaredFloats); + float c = floatArray.SumF(squaredFloats); + float d = floatArray.Sum(squaredFloats); Assert.That(c, Is.EqualTo(d)); } @@ -75,18 +75,18 @@ public void SumArraySelector() [Test] public void SumList() { - var a = intList.SumF(); - var b = intList.Sum(); + int a = intList.SumF(); + int b = intList.Sum(); Assert.That(a, Is.EqualTo(b)); - var c = floatList.SumF(); - var d = floatList.Sum(); + float c = floatList.SumF(); + float d = floatList.Sum(); Assert.That(c, Is.EqualTo(d)); - var e = decimalList.SumF(); - var f = decimalList.Sum(); + decimal e = decimalList.SumF(); + decimal f = decimalList.Sum(); Assert.That(e, Is.EqualTo(f)); } @@ -94,15 +94,15 @@ public void SumList() [Test] public void SumListSelector() { - var a = intList.SumF(x => x + 1); - var b = intList.Sum(x => x + 1); + int a = intList.SumF(x => x + 1); + int b = intList.Sum(x => x + 1); Assert.That(a, Is.EqualTo(b)); - var br = intList.AsReadOnly().SumF(x => x + 1); + int br = intList.AsReadOnly().SumF(x => x + 1); Assert.That(a, Is.EqualTo(br)); - var c = floatList.SumF(squaredFloats); - var d = floatList.Sum(squaredFloats); + float c = floatList.SumF(squaredFloats); + float d = floatList.Sum(squaredFloats); Assert.That(c, Is.EqualTo(d)); } diff --git a/Tests/TakeTests.cs b/Tests/TakeTests.cs index ca52f0a..0577de7 100644 --- a/Tests/TakeTests.cs +++ b/Tests/TakeTests.cs @@ -2,6 +2,7 @@ using JM.LinqFaster; using System.Linq; using System; +using System.Collections.Generic; using static Tests.Test; namespace Tests @@ -15,9 +16,9 @@ class TakeTests { [TestCase(TEST_SIZE)] public void TakeArray(int count) { - var a = intArray.TakeF(count); - var aSpan = intArray.AsSpan().TakeF(count); - var b = intArray.Take(count); + int[] a = intArray.TakeF(count); + int[] aSpan = intArray.AsSpan().TakeF(count); + IEnumerable b = intArray.Take(count); Assert.That(a, Is.EqualTo(b)); Assert.That(aSpan, Is.EqualTo(b)); @@ -25,9 +26,9 @@ class TakeTests { [Test] public void TakeWhileArray() { - var a = intArray.TakeWhileF(onlyEvenInts); - var aSpan = intArray.AsSpan().TakeWhileF(onlyEvenInts); - var b = intArray.TakeWhile(onlyEvenInts); + int[] a = intArray.TakeWhileF(onlyEvenInts); + int[] aSpan = intArray.AsSpan().TakeWhileF(onlyEvenInts); + IEnumerable b = intArray.TakeWhile(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); Assert.That(aSpan, Is.EqualTo(b)); @@ -40,16 +41,16 @@ class TakeTests { [TestCase(TEST_SIZE)] public void TakeList(int count) { - var a = intList.TakeF(count); - var b = intList.Take(count); + List a = intList.TakeF(count); + IEnumerable b = intList.Take(count); Assert.That(a, Is.EqualTo(b)); } [Test] public void TakeWhileList() { - var a = intList.TakeWhileF(onlyEvenInts); - var b = intList.TakeWhile(onlyEvenInts); + List a = intList.TakeWhileF(onlyEvenInts); + IEnumerable b = intList.TakeWhile(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/WhereAggregateTests.cs b/Tests/WhereAggregateTests.cs index c9ca161..ea40341 100644 --- a/Tests/WhereAggregateTests.cs +++ b/Tests/WhereAggregateTests.cs @@ -11,12 +11,12 @@ class WhereAggregateTests [Test] public void WhereAggregateSumArray() { - var a = + int a = intArray.WhereAggregateF(onlyEvenInts, 0, (acc, x) => acc += x); - var b = intArray.WhereAggregateF(onlyEvenInts, (acc, x) => acc += x); + int b = intArray.WhereAggregateF(onlyEvenInts, (acc, x) => acc += x); - var c = intArray.Where(onlyEvenInts).Sum(); + int c = intArray.Where(onlyEvenInts).Sum(); Assert.That(a, Is.EqualTo(c)); Assert.That(b, Is.EqualTo(c)); @@ -25,11 +25,11 @@ public void WhereAggregateSumArray() [Test] public void WhereAggregateSelectorArray() { - var a = + int a = intArray.WhereAggregateF(onlyEvenInts, 0, (acc, x) => acc += x, acc =>acc/2); - var b = intArray.Where(onlyEvenInts).Sum()/2; + int b = intArray.Where(onlyEvenInts).Sum()/2; Assert.That(a, Is.EqualTo(b)); @@ -38,12 +38,12 @@ public void WhereAggregateSumArray() [Test] public void WhereAggregateSumList() { - var a = + int a = intList.WhereAggregateF(onlyEvenInts, 0, (acc, x) => acc += x); - var b = intList.WhereAggregateF(onlyEvenInts, (acc, x) => acc += x); + int b = intList.WhereAggregateF(onlyEvenInts, (acc, x) => acc += x); - var c = intList.Where(onlyEvenInts).Sum(); + int c = intList.Where(onlyEvenInts).Sum(); Assert.That(a, Is.EqualTo(c)); Assert.That(b, Is.EqualTo(c)); @@ -52,11 +52,11 @@ public void WhereAggregateSumArray() [Test] public void WhereAggregateSelectorList() { - var a = + int a = intList.WhereAggregateF(onlyEvenInts, 0, (acc, x) => acc += x, acc => acc / 2); - var b = intList.Where(onlyEvenInts).Sum() / 2; + int b = intList.Where(onlyEvenInts).Sum() / 2; Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/WhereSelectTests.cs b/Tests/WhereSelectTests.cs index b146c62..d0c3983 100644 --- a/Tests/WhereSelectTests.cs +++ b/Tests/WhereSelectTests.cs @@ -2,6 +2,7 @@ using JM.LinqFaster; using System.Linq; using System; +using System.Collections.Generic; using static Tests.Test; namespace Tests @@ -12,14 +13,14 @@ class WhereSelectTests [Test] public void WhereSelectArray() { - var a = intArray.WhereSelectF(onlyEvenInts,squaredInts); - var b = intArray.Where(onlyEvenInts).Select(squaredInts); + int[] a = intArray.WhereSelectF(onlyEvenInts,squaredInts); + IEnumerable b = intArray.Where(onlyEvenInts).Select(squaredInts); Assert.That(a, Is.EqualTo(b)); Func lambda2 = (x => x == "no matches"); - var c = stringArray.WhereSelectF(lambda2, x => x + "append"); - var d = stringArray.Where(lambda2).Select(x => x + "append"); + string[] c = stringArray.WhereSelectF(lambda2, x => x + "append"); + IEnumerable d = stringArray.Where(lambda2).Select(x => x + "append"); Assert.That(c, Is.EqualTo(d)); @@ -27,21 +28,21 @@ public void WhereSelectArray() [Test] public void WhereSelectIndexArray() { - var a = intArray.WhereSelectF((x,i) => x+i % 2 == 0, (x,i) => x+i); - var b = intArray.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); + int[] a = intArray.WhereSelectF((x,i) => x+i % 2 == 0, (x,i) => x+i); + IEnumerable b = intArray.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); Assert.That(a, Is.EqualTo(b)); } [Test] public void WhereSelectList() { - var a = intList.WhereSelectF(onlyEvenInts, squaredInts); - var b = intList.Where(onlyEvenInts).Select(squaredInts); + List a = intList.WhereSelectF(onlyEvenInts, squaredInts); + IEnumerable b = intList.Where(onlyEvenInts).Select(squaredInts); Assert.That(a, Is.EqualTo(b)); Func lambda2 = (x => x == "no matches"); - var c = stringList.WhereSelectF(lambda2, x => x + "append"); - var d = stringList.Where(lambda2).Select(x => x + "append"); + List c = stringList.WhereSelectF(lambda2, x => x + "append"); + IEnumerable d = stringList.Where(lambda2).Select(x => x + "append"); Assert.That(c, Is.EqualTo(d)); @@ -49,8 +50,8 @@ public void WhereSelectArray() [Test] public void WhereSelectIndexList() { - var a = intList.WhereSelectF((x, i) => x + i % 2 == 0, (x, i) => x + i); - var b = intList.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); + List a = intList.WhereSelectF((x, i) => x + i % 2 == 0, (x, i) => x + i); + IEnumerable b = intList.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/WhereSumTEsts.cs b/Tests/WhereSumTEsts.cs index 3ebb751..87b85c2 100644 --- a/Tests/WhereSumTEsts.cs +++ b/Tests/WhereSumTEsts.cs @@ -11,13 +11,13 @@ class WhereSumTests [Test] public void WhereSumArray() { - var a = intArray.WhereSumF(x => x % 2 == 0); - var b = intArray.Where(x=>x%2==0).Sum(); + int a = intArray.WhereSumF(x => x % 2 == 0); + int b = intArray.Where(x=>x%2==0).Sum(); Assert.That(a, Is.EqualTo(b)); - var c = floatArray.WhereSumF(x => x > 0.0f); - var d = floatArray.Where(x => x > 0.0f).Sum(); + float c = floatArray.WhereSumF(x => x > 0.0f); + float d = floatArray.Where(x => x > 0.0f).Sum(); Assert.That(c, Is.EqualTo(d)); @@ -25,13 +25,13 @@ public void WhereSumArray() [Test] public void WhereSumArraySelector() { - var a = intArray.WhereSumF(x => x % 2 == 0,x=>x+1); - var b = intArray.Where(x => x % 2 == 0).Sum(x=>x+1); + int a = intArray.WhereSumF(x => x % 2 == 0,x=>x+1); + int b = intArray.Where(x => x % 2 == 0).Sum(x=>x+1); Assert.That(a, Is.EqualTo(b)); - var c = floatArray.WhereSumF(x => x > 0.0f,x => x / 2.0f); - var d = floatArray.Where(x => x > 0.0f).Sum(x => x/2.0f); + float c = floatArray.WhereSumF(x => x > 0.0f,x => x / 2.0f); + float d = floatArray.Where(x => x > 0.0f).Sum(x => x/2.0f); Assert.That(c, Is.EqualTo(d)); @@ -40,26 +40,26 @@ public void WhereSumArray() [Test] public void WhereSumList() { - var a = intList.WhereSumF(x => x % 2 == 0); - var b = intList.Where(x => x % 2 == 0).Sum(); + int a = intList.WhereSumF(x => x % 2 == 0); + int b = intList.Where(x => x % 2 == 0).Sum(); Assert.That(a, Is.EqualTo(b)); - var c = floatList.WhereSumF(x => x > 0.0f); - var d = floatList.Where(x => x > 0.0f).Sum(); + float c = floatList.WhereSumF(x => x > 0.0f); + float d = floatList.Where(x => x > 0.0f).Sum(); Assert.That(c, Is.EqualTo(d)); } [Test] public void WhereSumListSelector() { - var a = intList.WhereSumF(x => x % 2 == 0, x => x + 1); - var b = intList.Where(x => x % 2 == 0).Sum(x => x + 1); + int a = intList.WhereSumF(x => x % 2 == 0, x => x + 1); + int b = intList.Where(x => x % 2 == 0).Sum(x => x + 1); Assert.That(a, Is.EqualTo(b)); - var c = floatList.WhereSumF(x => x > 0.0f, x => x / 2.0f); - var d = floatList.Where(x => x > 0.0f).Sum(x => x / 2.0f); + float c = floatList.WhereSumF(x => x > 0.0f, x => x / 2.0f); + float d = floatList.Where(x => x > 0.0f).Sum(x => x / 2.0f); Assert.That(c, Is.EqualTo(d)); } diff --git a/Tests/WhereTests.cs b/Tests/WhereTests.cs index b188616..e04c28a 100644 --- a/Tests/WhereTests.cs +++ b/Tests/WhereTests.cs @@ -2,6 +2,7 @@ using JM.LinqFaster; using System.Linq; using System; +using System.Collections.Generic; using static Tests.Test; namespace Tests @@ -13,13 +14,13 @@ class WhereTests [Test] public void WhereEmpty() { - var emptyArray = new int[0]; + int[] emptyArray = new int[0]; Assert.DoesNotThrow(() => { - var a = emptyArray.WhereF(x => x == 0); - var emptyList = new System.Collections.Generic.List(0); - var b = emptyList.WhereF(x => x == 0); + int[] a = emptyArray.WhereF(x => x == 0); + List emptyList = new System.Collections.Generic.List(0); + List b = emptyList.WhereF(x => x == 0); }); } @@ -29,12 +30,12 @@ public void WhereEmpty() public void WhereArray() { Func lambda1 = ((x, i) => x + i % 2 == 0); - var a = intArray.WhereF(lambda1); - var b = intArray.Where(lambda1); + int[] a = intArray.WhereF(lambda1); + IEnumerable b = intArray.Where(lambda1); Assert.That(a, Is.EqualTo(b)); - var c = stringArray.WhereF(x => x == "no matches"); - var d = stringArray.Where(x => x == "no matches"); + string[] c = stringArray.WhereF(x => x == "no matches"); + IEnumerable d = stringArray.Where(x => x == "no matches"); } @@ -42,13 +43,13 @@ public void WhereArray() public void WhereList() { Func lambda1 = ((x, i) => x + i % 2 == 0); - var a = intList.WhereF(lambda1); - var b = intList.Where(lambda1); + List a = intList.WhereF(lambda1); + IEnumerable b = intList.Where(lambda1); Assert.That(a, Is.EqualTo(b)); - var c = stringList.WhereF(x => x == "no matches"); - var d = stringList.Where(x => x == "no matches"); + List c = stringList.WhereF(x => x == "no matches"); + IEnumerable d = stringList.Where(x => x == "no matches"); } diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 995556c..1c0f62c 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -612,6 +612,14 @@ A number that represents how many elements in the list satisfy the condition in the predicate function. + + + Returns source or (if needed) an array (For speed) with a single value set to default{T} + + + + source or new array{1} + Removes duplicate elements from source, does not maintain order. Elements will be @@ -972,6 +980,10 @@ A sequence of values to determine the maximum of. The maximum value in the sequence + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + @@ -980,6 +992,10 @@ A sequence of values to determine the maximum value of. A transform function to apply to each element. The maximum value in the transform of the sequence. + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + @@ -987,6 +1003,10 @@ A sequence of values to determine the maximum of. The maximum value in the sequence + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + @@ -995,6 +1015,10 @@ A sequence of values to determine the maximum value of. A transform function to apply to each element. The maximum value in the transform of the sequence. + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + @@ -1002,6 +1026,9 @@ A sequence of values to determine the maximum of. The maximum value in the sequence + + Special case to deal with NAN's + @@ -1010,6 +1037,9 @@ A sequence of values to determine the maximum value of. A transform function to apply to each element. The maximum value in the transform of the sequence. + + Special case to deal with NAN's + @@ -1017,6 +1047,9 @@ A sequence of values to determine the maximum of. The maximum value in the sequence + + Special case to deal with NAN's + @@ -1025,6 +1058,9 @@ A sequence of values to determine the maximum value of. A transform function to apply to each element. The maximum value in the transform of the sequence. + + Special case to deal with NAN's + @@ -1041,6 +1077,186 @@ A transform function to apply to each element. The maximum value in the transform of the sequence. + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + Returns the maximum value in a sequence of values. @@ -1131,14 +1347,14 @@ A transform function to apply to each element. The maximum value in the transform of the sequence. - + Returns the maximum value in a sequence of values. A sequence of values to determine the maximum of. The maximum value in the sequence - + Invokes a transform function on each element of a sequence and returns the maximum value. @@ -1146,14 +1362,14 @@ A transform function to apply to each element. The maximum value in the transform of the sequence. - + Returns the maximum value in a sequence of values. A sequence of values to determine the maximum of. The maximum value in the sequence - + Invokes a transform function on each element of a sequence and returns the maximum value. @@ -1161,14 +1377,14 @@ A transform function to apply to each element. The maximum value in the transform of the sequence. - + Returns the maximum value in a sequence of values. A sequence of values to determine the maximum of. The maximum value in the sequence - + Invokes a transform function on each element of a sequence and returns the maximum value. @@ -1176,14 +1392,14 @@ A transform function to apply to each element. The maximum value in the transform of the sequence. - + Returns the maximum value in a sequence of values. A sequence of values to determine the maximum of. The maximum value in the sequence - + Invokes a transform function on each element of a sequence and returns the maximum value. @@ -1191,14 +1407,14 @@ A transform function to apply to each element. The maximum value in the transform of the sequence. - + Returns the maximum value in a sequence of values. A sequence of values to determine the maximum of. The maximum value in the sequence - + Invokes a transform function on each element of a sequence and returns the maximum value. @@ -1206,14 +1422,14 @@ A transform function to apply to each element. The maximum value in the transform of the sequence. - + Returns the maximum value in a sequence of values. A sequence of values to determine the maximum of. The maximum value in the sequence - + Invokes a transform function on each element of a sequence and returns the maximum value. From 54e72fac8a16dd70068f46a2ccd8ebca9e05ff87 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Tue, 6 Aug 2019 09:40:41 +0100 Subject: [PATCH 18/30] MinF's for #15 : [Enhancement] Can these API's also work on IReadOnlyList - Split MinF's out into seperate files - Change to NameOf for Selector parameter --- Benchmarks/Benchmarks.csproj | 1 + Benchmarks/BenchmarksMax.cs | 306 +++---- Benchmarks/BenchmarksMin.cs | 163 ++++ LinqFaster/MaxArray.cs | 10 +- LinqFaster/MaxList.cs | 16 +- LinqFaster/MaxSpan.cs | 32 +- LinqFaster/Min.cs | 1063 ------------------------- LinqFaster/MinArray.cs | 483 +++++++++++ LinqFaster/MinList.cs | 871 ++++++++++++++++++++ LinqFaster/MinSpan.cs | 860 ++++++++++++++++++++ LinqFaster/Select.cs | 24 +- LinqFaster/SelectMany.cs | 12 +- LinqFaster/SumArrays.cs | 4 +- LinqFaster/SumList.cs | 8 +- LinqFaster/SumSpan.cs | 8 +- LinqFaster/WhereSum.cs | 30 +- LinqFaster/Zip.cs | 6 +- LinqFasterParallel/AverageParallel.cs | 20 +- LinqFasterParallel/SelectParallel.cs | 18 +- LinqFasterParallel/SumParallel.cs | 20 +- Tests/MinTests.cs | 4 + docs/linqfaster.xml | 454 ++++++++--- 22 files changed, 2974 insertions(+), 1439 deletions(-) create mode 100644 Benchmarks/BenchmarksMin.cs delete mode 100644 LinqFaster/Min.cs create mode 100644 LinqFaster/MinArray.cs create mode 100644 LinqFaster/MinList.cs create mode 100644 LinqFaster/MinSpan.cs diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 173aa9f..291890b 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -199,6 +199,7 @@ + diff --git a/Benchmarks/BenchmarksMax.cs b/Benchmarks/BenchmarksMax.cs index 7d34f7e..7f24226 100644 --- a/Benchmarks/BenchmarksMax.cs +++ b/Benchmarks/BenchmarksMax.cs @@ -7,157 +7,157 @@ namespace Tests { - public partial class Benchmarks - { - private static readonly Func MaxInts = (x) => x + 1; - - [Benchmark] - public double IntArrayMaxLinq() - { - return intArray.Max(); - } - - [Benchmark] - public double IntArrayMaxFast() - { - return intArray.MaxF(); - } - - [Benchmark] - public double IntSpanMaxForEach() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - int max = int.MinValue; - foreach (int i in asSpan) - { - if (max > i) - { - max = i; - } - } - - return max; - } - - [Benchmark] - public double IntSpanMaxFast() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - return asSpan.MaxF(); - } - - [Benchmark] - public double IntListMaxLinq() - { - return intList.Max(); - } - - [Benchmark] - public double IntListMaxFast() - { - return intList.MaxF(); - } - - [Benchmark] - public double IntAsListReadOnlyMaxLinq() - { - return intList.AsReadOnly().Max(); - } - - [Benchmark] - public double IntAsListReadOnlyMaxFast() - { - return intList.AsReadOnly().MaxF(); - } - - [Benchmark] - public double IntArrayAsReadOnlyMaxLinq() - { - return Array.AsReadOnly(intArray).Max(); - } - - [Benchmark] - public double IntArrayAsReadOnlyMaxFast() - { - return Array.AsReadOnly(intArray).MaxF(); - } - - - [Benchmark] - public double IntArrayMaxLinqSelector() - { - return intArray.Max(MaxInts); - } - - [Benchmark] - public double IntArrayMaxFastSelector() - { - return intArray.MaxF(MaxInts); - } - - [Benchmark] - public double IntSpanMaxForEachSelector() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - int max = int.MinValue; - foreach (int i in asSpan) - { - int l = MaxInts(i); - if (max > l) - { - max = l; - } - } - - return max; - } - - [Benchmark] - public double IntSpanMaxFastSelector() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - return asSpan.MaxF(MaxInts); - } - - [Benchmark] - public double IntListMaxLinqSelector() - { - return intList.Max(MaxInts); - } - - [Benchmark] - public double IntListMaxFastSelector() - { - return intList.MaxF(MaxInts); - } - - [Benchmark] - public double IntAsListReadOnlyMaxLinqSelector() - { - return intList.AsReadOnly().Max(MaxInts); - } - - [Benchmark] - public double IntAsListReadOnlyMaxFastSelector() - { - return intList.AsReadOnly().MaxF(MaxInts); - } - - [Benchmark] - public double IntArrayAsReadOnlyMaxLinqSelector() - { - return Array.AsReadOnly(intArray).Max(MaxInts); - } - - [Benchmark] - public double IntArrayAsReadOnlyMaxFastSelector() - { - return Array.AsReadOnly(intArray).MaxF(MaxInts); - } - - } + //public partial class Benchmarks + //{ + // private static readonly Func MaxInts = (x) => x + 1; + + // [Benchmark] + // public double IntArrayMaxLinq() + // { + // return intArray.Max(); + // } + + // [Benchmark] + // public double IntArrayMaxFast() + // { + // return intArray.MaxF(); + // } + + // [Benchmark] + // public double IntSpanMaxForEach() + // { + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // int max = int.MinValue; + // foreach (int i in asSpan) + // { + // if (max > i) + // { + // max = i; + // } + // } + + // return max; + // } + + // [Benchmark] + // public double IntSpanMaxFast() + // { + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // return asSpan.MaxF(); + // } + + // [Benchmark] + // public double IntListMaxLinq() + // { + // return intList.Max(); + // } + + // [Benchmark] + // public double IntListMaxFast() + // { + // return intList.MaxF(); + // } + + // [Benchmark] + // public double IntAsListReadOnlyMaxLinq() + // { + // return intList.AsReadOnly().Max(); + // } + + // [Benchmark] + // public double IntAsListReadOnlyMaxFast() + // { + // return intList.AsReadOnly().MaxF(); + // } + + // [Benchmark] + // public double IntArrayAsReadOnlyMaxLinq() + // { + // return Array.AsReadOnly(intArray).Max(); + // } + + // [Benchmark] + // public double IntArrayAsReadOnlyMaxFast() + // { + // return Array.AsReadOnly(intArray).MaxF(); + // } + + + // [Benchmark] + // public double IntArrayMaxLinqSelector() + // { + // return intArray.Max(MaxInts); + // } + + // [Benchmark] + // public double IntArrayMaxFastSelector() + // { + // return intArray.MaxF(MaxInts); + // } + + // [Benchmark] + // public double IntSpanMaxForEachSelector() + // { + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // int max = int.MinValue; + // foreach (int i in asSpan) + // { + // int l = MaxInts(i); + // if (max > l) + // { + // max = l; + // } + // } + + // return max; + // } + + // [Benchmark] + // public double IntSpanMaxFastSelector() + // { + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // return asSpan.MaxF(MaxInts); + // } + + // [Benchmark] + // public double IntListMaxLinqSelector() + // { + // return intList.Max(MaxInts); + // } + + // [Benchmark] + // public double IntListMaxFastSelector() + // { + // return intList.MaxF(MaxInts); + // } + + // [Benchmark] + // public double IntAsListReadOnlyMaxLinqSelector() + // { + // return intList.AsReadOnly().Max(MaxInts); + // } + + // [Benchmark] + // public double IntAsListReadOnlyMaxFastSelector() + // { + // return intList.AsReadOnly().MaxF(MaxInts); + // } + + // [Benchmark] + // public double IntArrayAsReadOnlyMaxLinqSelector() + // { + // return Array.AsReadOnly(intArray).Max(MaxInts); + // } + + // [Benchmark] + // public double IntArrayAsReadOnlyMaxFastSelector() + // { + // return Array.AsReadOnly(intArray).MaxF(MaxInts); + // } + + //} } diff --git a/Benchmarks/BenchmarksMin.cs b/Benchmarks/BenchmarksMin.cs new file mode 100644 index 0000000..0ce5b52 --- /dev/null +++ b/Benchmarks/BenchmarksMin.cs @@ -0,0 +1,163 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; + +namespace Tests +{ + public partial class Benchmarks + { + private static readonly Func MinInts = (x) => x + 1; + + [Benchmark] + public double IntArrayMinLinq() + { + return intArray.Min(); + } + + [Benchmark] + public double IntArrayMinFast() + { + return intArray.MinF(); + } + + [Benchmark] + public double IntSpanMinForEach() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + int Min = int.MinValue; + foreach (int i in asSpan) + { + if (Min > i) + { + Min = i; + } + } + + return Min; + } + + [Benchmark] + public double IntSpanMinFast() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.MinF(); + } + + [Benchmark] + public double IntListMinLinq() + { + return intList.Min(); + } + + [Benchmark] + public double IntListMinFast() + { + return intList.MinF(); + } + + [Benchmark] + public double IntAsListReadOnlyMinLinq() + { + return intList.AsReadOnly().Min(); + } + + [Benchmark] + public double IntAsListReadOnlyMinFast() + { + return intList.AsReadOnly().MinF(); + } + + [Benchmark] + public double IntArrayAsReadOnlyMinLinq() + { + return Array.AsReadOnly(intArray).Min(); + } + + [Benchmark] + public double IntArrayAsReadOnlyMinFast() + { + return Array.AsReadOnly(intArray).MinF(); + } + + + [Benchmark] + public double IntArrayMinLinqSelector() + { + return intArray.Min(MinInts); + } + + [Benchmark] + public double IntArrayMinFastSelector() + { + return intArray.MinF(MinInts); + } + + [Benchmark] + public double IntSpanMinForEachSelector() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + int Min = int.MinValue; + foreach (int i in asSpan) + { + int l = MinInts(i); + if (Min > l) + { + Min = l; + } + } + + return Min; + } + + [Benchmark] + public double IntSpanMinFastSelector() + { + int[] localArray = intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.MinF(MinInts); + } + + [Benchmark] + public double IntListMinLinqSelector() + { + return intList.Min(MinInts); + } + + [Benchmark] + public double IntListMinFastSelector() + { + return intList.MinF(MinInts); + } + + [Benchmark] + public double IntAsListReadOnlyMinLinqSelector() + { + return intList.AsReadOnly().Min(MinInts); + } + + [Benchmark] + public double IntAsListReadOnlyMinFastSelector() + { + return intList.AsReadOnly().MinF(MinInts); + } + + [Benchmark] + public double IntArrayAsReadOnlyMinLinqSelector() + { + return Array.AsReadOnly(intArray).Min(MinInts); + } + + [Benchmark] + public double IntArrayAsReadOnlyMinFastSelector() + { + return Array.AsReadOnly(intArray).MinF(MinInts); + } + + } +} diff --git a/LinqFaster/MaxArray.cs b/LinqFaster/MaxArray.cs index 3632288..f928bfa 100644 --- a/LinqFaster/MaxArray.cs +++ b/LinqFaster/MaxArray.cs @@ -176,7 +176,7 @@ public static int MaxF(this T[] source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int r = selector(source[0]); @@ -246,7 +246,7 @@ public static long MaxF(this T[] source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long r = selector(source[0]); @@ -317,7 +317,7 @@ public static float MaxF(this T[] source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } float r = selector(source[0]); @@ -393,7 +393,7 @@ public static double MaxF(this T[] source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double r = selector(source[0]); @@ -461,7 +461,7 @@ public static decimal MaxF(this T[] source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } decimal r = selector(source[0]); for (int i = 0; i < source.Length; i++) diff --git a/LinqFaster/MaxList.cs b/LinqFaster/MaxList.cs index e0c04a9..668d3b3 100644 --- a/LinqFaster/MaxList.cs +++ b/LinqFaster/MaxList.cs @@ -80,7 +80,7 @@ public static T MaxF(this List source) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int sourceCount = source.Count; @@ -162,7 +162,7 @@ public static int MaxF(this List source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int r = selector(source[0]); @@ -290,7 +290,7 @@ public static float MaxF(this List source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } float r = selector(source[0]); int startIndex = 0; @@ -365,7 +365,7 @@ public static double MaxF(this List source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double r = selector(source[0]); int startIndex = 0; @@ -502,7 +502,7 @@ public static T MaxF(this IReadOnlyList source) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int sourceCount = source.Count; @@ -584,7 +584,7 @@ public static int MaxF(this IReadOnlyList source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int r = selector(source[0]); @@ -712,7 +712,7 @@ public static float MaxF(this IReadOnlyList source, Func selecto } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } float r = selector(source[0]); int startIndex = 0; @@ -787,7 +787,7 @@ public static double MaxF(this IReadOnlyList source, Func selec } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double r = selector(source[0]); int startIndex = 0; diff --git a/LinqFaster/MaxSpan.cs b/LinqFaster/MaxSpan.cs index a7c8e11..2808f79 100644 --- a/LinqFaster/MaxSpan.cs +++ b/LinqFaster/MaxSpan.cs @@ -56,7 +56,11 @@ public static T MaxF(this Span source) { for (int i = 1; i < source.Length; i++) { - if (comparer.Compare(source[i], r) > 0) r = source[i]; + T item = source[i]; + if (item.CompareTo(r) > 0) + { + r = item; + } } } return r; @@ -159,7 +163,7 @@ public static int MaxF(this Span source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int r = selector(source[0]); @@ -217,7 +221,7 @@ public static long MaxF(this Span source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long r = selector(source[0]); @@ -281,7 +285,7 @@ public static float MaxF(this Span source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } float r = selector(source[0]); @@ -353,7 +357,7 @@ public static double MaxF(this Span source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double r = selector(source[0]); @@ -421,7 +425,7 @@ public static decimal MaxF(this Span source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } decimal r = selector(source[0]); for (int i = 1; i < source.Length; i++) @@ -471,7 +475,11 @@ public static T MaxF(this ReadOnlySpan source) { for (int i = 1; i < source.Length; i++) { - if (comparer.Compare(source[i], r) > 0) r = source[i]; + T item = source[i]; + if (item.CompareTo(r) > 0) + { + r = item; + } } } return r; @@ -574,7 +582,7 @@ public static int MaxF(this ReadOnlySpan source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int r = selector(source[0]); @@ -632,7 +640,7 @@ public static long MaxF(this ReadOnlySpan source, Func selector) } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long r = selector(source[0]); @@ -696,7 +704,7 @@ public static float MaxF(this ReadOnlySpan source, Func selector } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } float r = selector(source[0]); @@ -768,7 +776,7 @@ public static double MaxF(this ReadOnlySpan source, Func select } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double r = selector(source[0]); @@ -836,7 +844,7 @@ public static decimal MaxF(this ReadOnlySpan source, Func sele } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } decimal r = selector(source[0]); for (int i = 1; i < source.Length; i++) diff --git a/LinqFaster/Min.cs b/LinqFaster/Min.cs deleted file mode 100644 index 258ad6d..0000000 --- a/LinqFaster/Min.cs +++ /dev/null @@ -1,1063 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace JM.LinqFaster -{ - //int, long, float,double, decimal - public static partial class LinqFaster - { - // -------------------------- ARRAYS -------------------------------------------- - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static T MinF(this T[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - T r = default(T); - if (r == null) - { - r = source[0]; - for (int i = 1; i < source.Length; i++) - { - if (source[i] != null && comparer.Compare(source[i], r) < 0) r = source[i]; - } - } - else - { - r = source[0]; - for (int i = 1; i < source.Length; i++) - { - if (comparer.Compare(source[i], r) < 0) r = source[i]; - } - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static TResult MinF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - TResult r = default(TResult); - if (r == null) - { - r = selector(source[0]); - for (int i = 1; i < source.Length; i++) - { - TResult v = selector(source[i]); - if (v != null && comparer.Compare(v, r) < 0) r = v; - } - } - else - { - r = selector(source[0]); - for (int i = 1; i < source.Length; i++) - { - TResult v = selector(source[i]); - if (comparer.Compare(v, r) < 0) r = v; - } - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static int MinF(this int[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - int r = int.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static int MinF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - int r = int.MaxValue; - for (int i = 0; i < source.Length; i++) - { - int v = selector(source[i]); - if (v < r) r = v; - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static long MinF(this long[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - long r = long.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static long MinF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long r = long.MaxValue; - for (int i = 0; i < source.Length; i++) - { - long v = selector(source[i]); - if (v < r) r = v; - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static float MinF(this float[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - float r = float.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - else if (float.IsNaN(source[i])) return source[i]; - - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static float MinF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - float r = float.MaxValue; - for (int i = 0; i < source.Length; i++) - { - float v = selector(source[i]); - if (v < r) r = v; - else if (float.IsNaN(v)) return v; - - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static double MinF(this double[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - double r = double.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - else if (double.IsNaN(source[i])) return source[i]; - } - - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static double MinF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - double r = double.MaxValue; - for (int i = 0; i < source.Length; i++) - { - double v = selector(source[i]); - if (v < r) r = v; - else if (double.IsNaN(v)) return v; - - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static decimal MinF(this decimal[] source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - decimal r = decimal.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - } - return r; - } - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static decimal MinF(this T[] source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - decimal r = decimal.MaxValue; - for (int i = 0; i < source.Length; i++) - { - decimal v = selector(source[i]); - if (v < r) r = v; - } - return r; - } - // -------------------------- this Spans -------------------------------------------- - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static T MinF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - T r = default(T); - if (r == null) - { - r = source[0]; - for (int i = 1; i < source.Length; i++) - { - if (source[i] != null && comparer.Compare(source[i], r) < 0) r = source[i]; - } - } - else - { - r = source[0]; - for (int i = 1; i < source.Length; i++) - { - if (comparer.Compare(source[i], r) < 0) r = source[i]; - } - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static TResult MinF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - TResult r = default(TResult); - if (r == null) - { - r = selector(source[0]); - for (int i = 1; i < source.Length; i++) - { - TResult v = selector(source[i]); - if (v != null && comparer.Compare(v, r) < 0) r = v; - } - } - else - { - r = selector(source[0]); - for (int i = 1; i < source.Length; i++) - { - TResult v = selector(source[i]); - if (comparer.Compare(v, r) < 0) r = v; - } - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static int MinF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - int r = int.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static int MinF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - int r = int.MaxValue; - for (int i = 0; i < source.Length; i++) - { - int v = selector(source[i]); - if (v < r) r = v; - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static long MinF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - long r = long.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static long MinF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - long r = long.MaxValue; - for (int i = 0; i < source.Length; i++) - { - long v = selector(source[i]); - if (v < r) r = v; - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static float MinF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - float r = float.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - else if (float.IsNaN(source[i])) return source[i]; - - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static float MinF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - float r = float.MaxValue; - for (int i = 0; i < source.Length; i++) - { - float v = selector(source[i]); - if (v < r) r = v; - else if (float.IsNaN(v)) return v; - - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static double MinF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - double r = double.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - else if (double.IsNaN(source[i])) return source[i]; - } - - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static double MinF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - double r = double.MaxValue; - for (int i = 0; i < source.Length; i++) - { - double v = selector(source[i]); - if (v < r) r = v; - else if (double.IsNaN(v)) return v; - - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static decimal MinF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - decimal r = decimal.MaxValue; - for (int i = 0; i < source.Length; i++) - { - if (source[i] < r) r = source[i]; - } - return r; - } - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static decimal MinF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - decimal r = decimal.MaxValue; - for (int i = 0; i < source.Length; i++) - { - decimal v = selector(source[i]); - if (v < r) r = v; - } - return r; - } - - // -------------------------- LISTS -------------------------------------------- - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static T MinF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - T r = default(T); - if (r == null) - { - r = source[0]; - for (int i = 1; i < source.Count; i++) - { - if (source[i] != null && comparer.Compare(source[i], r) < 0) r = source[i]; - } - } - else - { - r = source[0]; - for (int i = 1; i < source.Count; i++) - { - if (comparer.Compare(source[i], r) < 0) r = source[i]; - } - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static int MinF(this Listsource) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - int r = int.MaxValue; - for (int i = 0; i < source.Count; i++) - { - if (source[i] < r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static int MinF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - int r = int.MaxValue; - for (int i = 0; i < source.Count; i++) - { - int v = selector(source[i]); - if (v < r) r = v; - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static long MinF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - long r = long.MaxValue; - for (int i = 0; i < source.Count; i++) - { - if (source[i] < r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static long MinF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("source"); - } - long r = long.MaxValue; - for (int i = 0; i < source.Count; i++) - { - long v = selector(source[i]); - if (v < r) r = v; - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static float MinF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - float r = float.MaxValue; - for (int i = 0; i < source.Count; i++) - { - if (source[i] < r) r = source[i]; - else if (float.IsNaN(source[i])) return source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static float MinF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - float r = float.MaxValue; - for (int i = 0; i < source.Count; i++) - { - float v = selector(source[i]); - if (v < r) r = v; - else if (float.IsNaN(v)) return v; - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static double MinF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - double r = double.MaxValue; - for (int i = 0; i < source.Count; i++) - { - if (source[i] < r) r = source[i]; - else if (double.IsNaN(source[i])) return source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static double MinF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - double r = double.MaxValue; - for (int i = 0; i < source.Count; i++) - { - double v = selector(source[i]); - if (v < r) r = v; - else if (double.IsNaN(v)) return v; - } - return r; - } - - /// - /// Returns the minimum value in a sequence of values. - /// - /// A sequence of values to determine the minimum of. - /// The minimum value in the sequence - public static decimal MinF(this List source) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - decimal r = decimal.MaxValue; - for (int i = 0; i < source.Count; i++) - { - if (source[i] < r) r = source[i]; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static decimal MinF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - if (source.Count == 0) - { - throw Error.NoElements(); - } - decimal r = decimal.MaxValue; - for (int i = 0; i < source.Count; i++) - { - decimal v = selector(source[i]); - if (v < r) r = v; - } - return r; - } - - /// - /// Invokes a transform function on each element of a sequence and returns the maximum value. - /// - /// A sequence of values to determine the maximum value of. - /// A transform function to apply to each element. - /// The maximum value in the transform of the sequence. - public static TResult MinF(this List source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull("selector"); - } - - if (source.Count == 0) - { - throw Error.NoElements(); - } - - Comparer comparer = Comparer.Default; - TResult r = default(TResult); - if (r == null) - { - r = selector(source[0]); - for (int i = 1; i < source.Count; i++) - { - TResult v = selector(source[i]); - if (v != null && comparer.Compare(v, r) < 0) r = v; - } - } - else - { - r = selector(source[0]); - for (int i = 1; i < source.Count; i++) - { - TResult v = selector(source[i]); - if (comparer.Compare(v, r) < 0) r = v; - } - } - return r; - } - - } -} diff --git a/LinqFaster/MinArray.cs b/LinqFaster/MinArray.cs new file mode 100644 index 0000000..f91485d --- /dev/null +++ b/LinqFaster/MinArray.cs @@ -0,0 +1,483 @@ +using System; +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global +// ReSharper disable LoopCanBeConvertedToQuery + +namespace JM.LinqFaster +{ + // Common types optimised: int, long, float, double, decimal + // Other types will be handled via the templates which are approx 2 time longer than + // the above optimised base types + public static partial class LinqFaster + { + // Note: although there is a lot of shared code in the following + // comparers, we do not incorporate it into a base class for perf + // reasons. Adding another base class (even one with no fields) + // means another generic instantiation, which can be costly esp. + // for value types. + + // -------------------------- ARRAYS -------------------------------------------- + // + // It has been found that by starting the sequence _always_ at zero, then the for loop is optimsed even more ! + // + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MinF(this T[] source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + T r = source[0]; + if (default(T) == null) + { + for (int i = 0; i < source.Length; i++) + { + T item = source[i]; + if ((item != null) + && ((r == null) + || (item.CompareTo(r) < 0) + ) + ) + { + r = item; + } + } + } + else + { + for (int i = 0; i < source.Length; i++) + { + if (source[i].CompareTo(r) < 0) + { + r = source[i]; + } + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MinF(this T[] source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(T) == null) + { + for (int i = 0; i < source.Length; i++) + { + TResult item = selector(source[i]); + if ((item != null) + && ((r == null) + || (item.CompareTo(r) < 0) + ) + ) + { + r = item; + } + } + } + else + { + for (int i = 0; i < source.Length; i++) + { + TResult v = selector(source[i]); + if (v.CompareTo(r) < 0) + { + r = v; + } + } + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + /// + /// This is faster than the templated functions above. + /// Probably because the comparator function os only run once and there is not stack invloved + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this int[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 0; i < source.Length; i++) + { + if (source[i] < r) + { + r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + /// + /// This is faster than the templated functions above. + /// Probably because the comparator function os only run once and there is not stack invloved + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int r = selector(source[0]); + for (int i = 0; i < source.Length; i++) + { + int v = selector(source[i]); + if (v < r) + { + r = v; + } + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + /// + /// This is faster than the templated functions above. + /// Probably because the comparator function os only run once and there is not stack invloved + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this long[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 0; i < source.Length; i++) + { + if (source[i] < r) + { + r = source[i]; + } + } + return r; + } + + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + /// + /// This is faster than the templated functions above. + /// Probably because the comparator function os only run once and there is not stack invloved + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + long r = selector(source[0]); + for (int i = 0; i < source.Length; i++) + { + long v = selector(source[i]); + if (v < r) + { + r = v; + } + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + /// + /// Special case to deal with NAN's + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this float[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + /// + /// Special case to deal with NAN's + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + float v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + /// + /// Special case to deal with NAN's + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this double[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + /// + /// Special case to deal with NAN's + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + double v = selector(source[startIndex]); + if (double.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + double v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this decimal[] source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 0; i < source.Length; i++) + { + if (source[i] < r) + { + r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this T[] source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + decimal r = selector(source[0]); + for (int i = 0; i < source.Length; i++) + { + decimal v = selector(source[i]); + if (v < r) + { + r = v; + } + } + return r; + } + + + } +} diff --git a/LinqFaster/MinList.cs b/LinqFaster/MinList.cs new file mode 100644 index 0000000..85649b6 --- /dev/null +++ b/LinqFaster/MinList.cs @@ -0,0 +1,871 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global +// ReSharper disable LoopCanBeConvertedToQuery + +namespace JM.LinqFaster +{ + // Common types optimised: int, long, float, double, decimal + // Other types will be handled via the templates which are approx 2 time longer than + // the above optimised base types + public static partial class LinqFaster + { + // Note: although there is a lot of shared code in the following + // comparers, we do not incorporate it into a base class for perf + // reasons. Adding another base class (even one with no fields) + // means another generic instantiation, which can be costly esp. + // for value types. + + // -------------------------- LISTS -------------------------------------------- + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MinF(this List source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + + T r = source[0]; + if (default(T) == null) + { + for (int i = 1; i < sourceCount; i++) + { + T item = source[i]; + if (item != null + && item.CompareTo(r) < 0) + r = item; + } + } + else + { + for (int i = 1; i < sourceCount; i++) + { + T item = source[i]; + if (item.CompareTo(r) < 0) + r = item; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MinF(this List source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(TResult) == null) + { + for (int i = 1; i < sourceCount; i++) + { + TResult item = selector(source[i]); + if (item != null + && item.CompareTo(r) < 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < sourceCount; i++) + { + TResult item = selector(source[i]); + if (item.CompareTo(r) < 0) + r = item; + } + } + return r; + } + + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + int v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(source)); + } + long r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + long v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + float v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + double v = selector(source[startIndex]); + if (double.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + double v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this List source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this List source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + decimal r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + decimal v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + // -------------------------- IReadOnlyList -------------------------------------------- + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MinF(this IReadOnlyList source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + + T r = source[0]; + if (default(T) == null) + { + for (int i = 1; i < sourceCount; i++) + { + T item = source[i]; + if (item != null + && item.CompareTo(r) > 0) + r = item; + } + } + else + { + for (int i = 1; i < sourceCount; i++) + { + T item = source[i]; + if (item.CompareTo(r) < 0) + r = item; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MinF(this IReadOnlyList source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(TResult) == null) + { + for (int i = 1; i < sourceCount; i++) + { + TResult item = selector(source[i]); + if (item != null + && item.CompareTo(r) < 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < sourceCount; i++) + { + TResult item = selector(source[i]); + if (item.CompareTo(r) < 0) + r = item; + } + } + return r; + } + + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + int v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(source)); + } + long r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + long v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + float v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < sourceCount; startIndex++) + { + double v = selector(source[startIndex]); + if (double.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < sourceCount; i++) + { + double v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this IReadOnlyList source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 1; i < sourceCount; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this IReadOnlyList source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + int sourceCount = source.Count; + if (sourceCount == 0) + { + throw Error.NoElements(); + } + decimal r = selector(source[0]); + for (int i = 1; i < sourceCount; i++) + { + decimal v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + + } +} diff --git a/LinqFaster/MinSpan.cs b/LinqFaster/MinSpan.cs new file mode 100644 index 0000000..ca467b2 --- /dev/null +++ b/LinqFaster/MinSpan.cs @@ -0,0 +1,860 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global +// ReSharper disable LoopCanBeConvertedToQuery + +namespace JM.LinqFaster +{ + // Common types optimised: int, long, float, double, decimal + // Other types will be handled via the templates which are approx 2 time longer than + // the above optimised base types + public static partial class LinqFaster + { + // Note: although there is a lot of shared code in the following + // comparers, we do not incorporate it into a base class for perf + // reasons. Adding another base class (even one with no fields) + // means another generic instantiation, which can be costly esp. + // for value types. + + // -------------------------- this Spans -------------------------------------------- + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MinF(this Span source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + Comparer comparer = Comparer.Default; + T r = source[0]; + if (default(T) == null) + { + for (int i = 1; i < source.Length; i++) + { + T item = source[i]; + if (item != null + && item.CompareTo(r) < 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < source.Length; i++) + { + T item = source[i]; + if ( item.CompareTo(r) < 0) + { + r = item; + } + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MinF(this Span source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(TResult) == null) + { + for (int i = 1; i < source.Length; i++) + { + TResult item = selector(source[i]); + if (item != null + && item.CompareTo(r) < 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < source.Length; i++) + { + TResult item = selector(source[i]); + if (item.CompareTo(r) < 0) + { + r = item; + } + + } + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] < r) + { + r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + int v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + long r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + long v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + float v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + double v = selector(source[startIndex]); + if (!double.IsNaN(v)) + { + r = v; + break; + } + } + for (int i = startIndex; i < source.Length; i++) + { + double v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + decimal r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + decimal v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + // -------------------------- ReadOnlySpans -------------------------------------------- + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MinF(this ReadOnlySpan source) + where T : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + T r = source[0]; + if (default(T) == null) + { + for (int i = 1; i < source.Length; i++) + { + T item = source[i]; + if (item != null + && item.CompareTo(r) < 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < source.Length; i++) + { + T item = source[i]; + if (item.CompareTo(r) < 0) + { + r = item; + } + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult MinF(this ReadOnlySpan source, Func selector) + where TResult : IComparable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + + TResult r = selector(source[0]); + if (default(TResult) == null) + { + for (int i = 1; i < source.Length; i++) + { + TResult item = selector(source[i]); + if (item != null + && item.CompareTo(r) < 0) + { + r = item; + } + } + } + else + { + for (int i = 1; i < source.Length; i++) + { + TResult item = selector(source[i]); + if (item.CompareTo(r) < 0) + { + r = item; + } + + } + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + int r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] < r) + { + r = source[i]; + } + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + int v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + long r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long MinF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + long r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + long v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + float r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (float.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float MinF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + float r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + float v = selector(source[startIndex]); + if (float.IsNaN(v)) continue; + r = v; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + float v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + double r = source[0]; + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + if (double.IsNaN(source[startIndex])) continue; + r = source[startIndex]; + break; + } + for (int i = startIndex; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + double r = selector(source[0]); + int startIndex = 0; + for (; startIndex < source.Length; startIndex++) + { + double v = selector(source[startIndex]); + if (!double.IsNaN(v)) + { + r = v; + break; + } + } + for (int i = startIndex; i < source.Length; i++) + { + double v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + + /// + /// Returns the Minimum value in a sequence of values. + /// + /// A sequence of values to determine the Minimum of. + /// The Minimum value in the sequence + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + decimal r = source[0]; + for (int i = 1; i < source.Length; i++) + { + if (source[i] < r) + r = source[i]; + } + return r; + } + + /// + /// Invokes a transform function on each element of a sequence and returns the Minimum value. + /// + /// A sequence of values to determine the Minimum value of. + /// A transform function to apply to each element. + /// The Minimum value in the transform of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal MinF(this ReadOnlySpan source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + decimal r = selector(source[0]); + for (int i = 1; i < source.Length; i++) + { + decimal v = selector(source[i]); + if (v < r) + r = v; + } + return r; + } + + + } +} \ No newline at end of file diff --git a/LinqFaster/Select.cs b/LinqFaster/Select.cs index 0a48abf..6b70bd2 100644 --- a/LinqFaster/Select.cs +++ b/LinqFaster/Select.cs @@ -23,7 +23,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } for (int i = 0; i < source.Length; i++) @@ -46,7 +46,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } for (int i = 0; i < source.Length; i++) @@ -71,7 +71,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } TResult[] r = new TResult[source.Length]; @@ -99,7 +99,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } TResult[] r = new TResult[source.Length]; for (int i = 0; i < source.Length; i++) @@ -125,7 +125,7 @@ public static void SelectInPlaceF(this Span source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } for (int i = 0; i < source.Length; i++) @@ -148,7 +148,7 @@ public static void SelectInPlaceF(this Span source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } for (int i = 0; i < source.Length; i++) @@ -173,7 +173,7 @@ public static void SelectInPlaceF(this Span source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } TResult[] r = new TResult[source.Length]; @@ -201,7 +201,7 @@ public static void SelectInPlaceF(this Span source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } TResult[] r = new TResult[source.Length]; for (int i = 0; i < source.Length; i++) @@ -227,7 +227,7 @@ public static void SelectInPlaceF(this List source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } for (int i = 0; i < source.Count; i++) @@ -250,7 +250,7 @@ public static void SelectInPlaceF(this List source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } for (int i = 0; i < source.Count; i++) @@ -275,7 +275,7 @@ public static void SelectInPlaceF(this List source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } List r = new List(source.Count); @@ -304,7 +304,7 @@ public static void SelectInPlaceF(this List source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } List r = new List(source.Count); diff --git a/LinqFaster/SelectMany.cs b/LinqFaster/SelectMany.cs index 3f4a156..63220f4 100644 --- a/LinqFaster/SelectMany.cs +++ b/LinqFaster/SelectMany.cs @@ -23,7 +23,7 @@ public static partial class LinqFaster if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } List result = new List(source.Length); @@ -54,7 +54,7 @@ public static partial class LinqFaster if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } List result = new List(source.Length); @@ -87,7 +87,7 @@ public static partial class LinqFaster if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } List result = new List(source.Length); @@ -118,7 +118,7 @@ public static partial class LinqFaster if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } List result = new List(source.Length); @@ -150,7 +150,7 @@ public static partial class LinqFaster if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } List result = new List(source.Count); @@ -181,7 +181,7 @@ public static partial class LinqFaster if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } List result = new List(source.Count); diff --git a/LinqFaster/SumArrays.cs b/LinqFaster/SumArrays.cs index e09b27b..d7337f1 100644 --- a/LinqFaster/SumArrays.cs +++ b/LinqFaster/SumArrays.cs @@ -132,7 +132,7 @@ public static T2 SumF(this float[] source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } INumericPolicy p = NumericPolicies.Instance; @@ -186,7 +186,7 @@ public static decimal SumF(this decimal[] source) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } T2 a = default(T2); diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index 4de9bb9..3b2a1de 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -278,7 +278,7 @@ public static T2 SumF(this List source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } INumericPolicy p = NumericPolicies.Instance; @@ -364,7 +364,7 @@ public static decimal SumF(this IReadOnlyList source) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int sourceCount = source.Count; @@ -401,7 +401,7 @@ public static decimal SumF(this IReadOnlyList source) { if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int sourceCount = source.Count; @@ -729,7 +729,7 @@ public static T2 SumF(this List source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int sourceCount = source.Count; diff --git a/LinqFaster/SumSpan.cs b/LinqFaster/SumSpan.cs index 0608787..b9b1cbb 100644 --- a/LinqFaster/SumSpan.cs +++ b/LinqFaster/SumSpan.cs @@ -136,7 +136,7 @@ public static T2 SumF(this Span source, Func selector) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } INumericPolicy p = NumericPolicies.Instance; @@ -190,7 +190,7 @@ public static decimal SumF(this Span source) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } T2 a = default(T2); @@ -370,7 +370,7 @@ public static T2 SumF(this ReadOnlySpan source, Func selec if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } INumericPolicy p = NumericPolicies.Instance; @@ -424,7 +424,7 @@ public static decimal SumF(this ReadOnlySpan source) if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } T2 a = default(T2); diff --git a/LinqFaster/WhereSum.cs b/LinqFaster/WhereSum.cs index c0ed746..91d4d2b 100644 --- a/LinqFaster/WhereSum.cs +++ b/LinqFaster/WhereSum.cs @@ -50,7 +50,7 @@ public static int WhereSumF(this T[] source,Func predicate, Func(this T[] source,Func predicate, Func(this T[] source, Func predicate,Func(this T[] source, Func predicate,Func(this T[] source,Func predicate, Func< if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } decimal sum = 0; @@ -337,7 +337,7 @@ public static int WhereSumF(this Span source, Func predicate, Fun if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int sum = 0; @@ -396,7 +396,7 @@ public static long WhereSumF(this Span source, Func predicate, Fu if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long sum = 0; @@ -454,7 +454,7 @@ public static float WhereSumF(this Span source, Func predicate, F if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -509,7 +509,7 @@ public static double WhereSumF(this Span source, Func predicate, if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -565,7 +565,7 @@ public static decimal WhereSumF(this Span source, Func predicate, if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } decimal sum = 0; @@ -625,7 +625,7 @@ public static int WhereSumF(this List source, Func predicate, Func if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int sum = 0; @@ -686,7 +686,7 @@ public static long WhereSumF(this List source, Func predicate, Fun if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long sum = 0; @@ -746,7 +746,7 @@ public static float WhereSumF(this List source, Func predicate,Fun if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -803,7 +803,7 @@ public static double WhereSumF(this List source,Func predicate, Fu if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -861,7 +861,7 @@ public static decimal WhereSumF(this List source, Func predicate,F if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } decimal sum = 0; diff --git a/LinqFaster/Zip.cs b/LinqFaster/Zip.cs index 380773a..b6d59f7 100644 --- a/LinqFaster/Zip.cs +++ b/LinqFaster/Zip.cs @@ -25,7 +25,7 @@ public static partial class LinqFaster } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } //maintain array bounds elision @@ -70,7 +70,7 @@ public static partial class LinqFaster } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } //maintain array bounds elision @@ -115,7 +115,7 @@ public static partial class LinqFaster } if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } //maintain array bounds elision diff --git a/LinqFasterParallel/AverageParallel.cs b/LinqFasterParallel/AverageParallel.cs index b6a1bfd..7c4915b 100644 --- a/LinqFasterParallel/AverageParallel.cs +++ b/LinqFasterParallel/AverageParallel.cs @@ -71,7 +71,7 @@ public static double AverageP(this T[] source, Func selector, int? ba if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long sum = 0; @@ -154,7 +154,7 @@ public static double AverageP(this T[] source, Func selector, int? b if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long sum = 0; @@ -235,7 +235,7 @@ public static float AverageP(this T[] source, Func selector, int? b if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -316,7 +316,7 @@ public static double AverageP(this T[] source, Func selector, int? if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -398,7 +398,7 @@ public static decimal AverageP(this T[] source, Func selector, in if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } @@ -484,7 +484,7 @@ public static double AverageP(this List source, Func selector, int if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long sum = 0; @@ -566,7 +566,7 @@ public static double AverageP(this List source, Func selector, in if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long sum = 0; @@ -646,7 +646,7 @@ public static double AverageP(this List source, Func selector, i if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -727,7 +727,7 @@ public static double AverageP(this List source, Func selector, if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -808,7 +808,7 @@ public static decimal AverageP(this List source, Func selector if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } diff --git a/LinqFasterParallel/SelectParallel.cs b/LinqFasterParallel/SelectParallel.cs index bc0d95b..a183ddb 100644 --- a/LinqFasterParallel/SelectParallel.cs +++ b/LinqFasterParallel/SelectParallel.cs @@ -24,7 +24,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, int? if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } @@ -54,7 +54,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, i if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } @@ -84,7 +84,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, i if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } TResult[] r = new TResult[source.Length]; @@ -116,7 +116,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, i if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } TResult[] r = new TResult[source.Length]; OrderablePartitioner> rangePartitioner = MakePartition(source.Length, batchSize); @@ -147,7 +147,7 @@ public static void SelectInPlaceP(this List source, Func selector, i if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } @@ -177,7 +177,7 @@ public static void SelectInPlaceP(this List source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } @@ -207,7 +207,7 @@ public static void SelectInPlaceP(this List source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } TResult[] r = new TResult[source.Count]; @@ -240,7 +240,7 @@ public static void SelectInPlaceP(this List source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } TResult[] r = new TResult[source.Count]; @@ -274,7 +274,7 @@ public static void SelectInPlaceP(this List source, Func select if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } List r = new List(source.Count); diff --git a/LinqFasterParallel/SumParallel.cs b/LinqFasterParallel/SumParallel.cs index 45d5c91..eb1dee0 100644 --- a/LinqFasterParallel/SumParallel.cs +++ b/LinqFasterParallel/SumParallel.cs @@ -59,7 +59,7 @@ public static int SumP(this T[] source, Func selector, int? batchSize if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int sum = 0; @@ -130,7 +130,7 @@ public static long SumP(this T[] source, Func selector, int? batchSi if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long sum = 0; @@ -207,7 +207,7 @@ public static float SumP(this T[] source, Func selector, int? batch if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -289,7 +289,7 @@ public static double SumP(this T[] source, Func selector, int? bat if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; object LOCK = new object(); @@ -370,7 +370,7 @@ public static decimal SumP(this T[] source, Func selector, int? b if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } decimal sum = 0; @@ -447,7 +447,7 @@ public static int SumP(this List source, Func selector, int? batch if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } int sum = 0; @@ -518,7 +518,7 @@ public static long SumP(this List source, Func selector, int? bat if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } long sum = 0; @@ -587,7 +587,7 @@ public static float SumP(this List source, Func selector, int? b if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -655,7 +655,7 @@ public static double SumP(this List source, Func selector, int? if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } double sum = 0; @@ -729,7 +729,7 @@ public static decimal SumP(this List source, Func selector, in if (selector == null) { - throw Error.ArgumentNull("selector"); + throw Error.ArgumentNull(nameof(selector)); } decimal sum = 0; diff --git a/Tests/MinTests.cs b/Tests/MinTests.cs index 81614bb..3de67b5 100644 --- a/Tests/MinTests.cs +++ b/Tests/MinTests.cs @@ -11,6 +11,7 @@ namespace Tests class MinTests { public void HelperMin(T[] array) + where T : IComparable { T a = array.MinF(); T b = array.Min(); @@ -19,6 +20,7 @@ public void HelperMin(T[] array) } public void HelperMin(List list) + where T : IComparable { T a = list.MinF(); T b = list.Min(); @@ -27,6 +29,7 @@ public void HelperMin(List list) } public void HelperMin(T[] array, Func selector) + where U : IComparable { U a = array.MinF(selector); U b = array.Min(selector); @@ -35,6 +38,7 @@ public void HelperMin(List list) } public void HelperMin(List list, Func selector) + where U : IComparable { U a = list.MinF(selector); U b = list.Min(selector); diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 1c0f62c..2fc9b24 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -1439,273 +1439,481 @@ - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + Special case to deal with NAN's + - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. + + Special case to deal with NAN's + - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + Special case to deal with NAN's + - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. + + Special case to deal with NAN's + - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - - - Returns the minimum value in a sequence of values. - - A sequence of values to determine the minimum of. - The minimum value in the sequence - - + - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - + - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - + - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - + - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - + - Returns the minimum value in a sequence of values. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the minimum of. - The minimum value in the sequence + A sequence of values to determine the Minimum of. + The Minimum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the maximum value. + Invokes a transform function on each element of a sequence and returns the Minimum value. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. - + - Invokes a transform function on each element of a sequence and returns the maximum value. + Returns the Minimum value in a sequence of values. - A sequence of values to determine the maximum value of. + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. A transform function to apply to each element. - The maximum value in the transform of the sequence. + The Minimum value in the transform of the sequence. From c3669bf1dbf1aa94f26337bc8bce1e041afd1e64 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Tue, 6 Aug 2019 12:47:37 +0100 Subject: [PATCH 19/30] WhereSumF's for #15 : [Enhancement] Can these API's also work on IReadOnlyList - Replacement to use nameof for source - Split more benchmarks out into seperate relevant files --- Benchmarks/BenchmarkAggregate.cs | 93 ++ Benchmarks/BenchmarkAverage.cs | 50 + Benchmarks/BenchmarkFirst.cs | 95 ++ Benchmarks/BenchmarkLast.cs | 95 ++ Benchmarks/BenchmarkOrderBy.cs | 26 + Benchmarks/BenchmarkSum.cs | 277 +++++ Benchmarks/BenchmarkWhereSum.cs | 307 +++++ Benchmarks/Benchmarks.cs | 599 ---------- Benchmarks/Benchmarks.csproj | 7 + Benchmarks/BenchmarksMin.cs | 307 ++--- LinqFaster/Aggregate.cs | 18 +- LinqFaster/AnyAll.cs | 18 +- LinqFaster/AverageIList.cs | 2 +- LinqFaster/Contains.cs | 6 +- LinqFaster/Count.cs | 6 +- LinqFaster/Distinct.cs | 2 +- LinqFaster/OrderBy.cs | 8 +- LinqFaster/Select.cs | 24 +- LinqFaster/SelectMany.cs | 12 +- LinqFaster/SelectWhere.cs | 12 +- LinqFaster/Single.cs | 24 +- LinqFaster/Skip.cs | 12 +- LinqFaster/SumArrays.cs | 1 + LinqFaster/SumList.cs | 1 - LinqFaster/Take.cs | 18 +- LinqFaster/Where.cs | 12 +- LinqFaster/WhereAggregate.cs | 24 +- LinqFaster/WhereSelect.cs | 12 +- LinqFaster/WhereSum.cs | 881 -------------- LinqFaster/WhereSumArray.cs | 487 ++++++++ LinqFaster/WhereSumList.cs | 1086 ++++++++++++++++++ LinqFaster/WhereSumSpan.cs | 569 +++++++++ LinqFasterParallel/AverageParallel.cs | 40 +- LinqFasterParallel/ContainsParallel.cs | 4 +- LinqFasterParallel/CountParallel.cs | 4 +- LinqFasterParallel/MaxParallel.cs | 48 +- LinqFasterParallel/MinParallel.cs | 48 +- LinqFasterParallel/SelectParallel.cs | 18 +- LinqFasterParallel/SelectWhereParallel.cs | 8 +- LinqFasterParallel/SumParallel.cs | 40 +- LinqFasterParallel/WhereAggregateParallel.cs | 16 +- LinqFasterParallel/WhereParallel.cs | 8 +- LinqFasterParallel/WhereSelectParallel.cs | 8 +- LinqFasterParallelSIMD/SelectSIMDParallel.cs | 2 +- LinqFasterParallelSIMD/SumSIMDParallel.cs | 2 +- LinqFasterSIMD/ContainsSIMD.cs | 2 +- LinqFasterSIMD/MaxSIMD.cs | 2 +- LinqFasterSIMD/MinSIMD.cs | 2 +- LinqFasterSIMD/SelectSIMD.cs | 4 +- LinqFasterSIMD/SumSIMD.cs | 4 +- Tests/AverageTests.cs | 33 +- Tests/SumTests.cs | 31 + docs/linqfaster.xml | 542 +++++++-- 53 files changed, 3995 insertions(+), 1962 deletions(-) create mode 100644 Benchmarks/BenchmarkAggregate.cs create mode 100644 Benchmarks/BenchmarkAverage.cs create mode 100644 Benchmarks/BenchmarkFirst.cs create mode 100644 Benchmarks/BenchmarkLast.cs create mode 100644 Benchmarks/BenchmarkOrderBy.cs create mode 100644 Benchmarks/BenchmarkSum.cs create mode 100644 Benchmarks/BenchmarkWhereSum.cs delete mode 100644 LinqFaster/WhereSum.cs create mode 100644 LinqFaster/WhereSumArray.cs create mode 100644 LinqFaster/WhereSumList.cs create mode 100644 LinqFaster/WhereSumSpan.cs diff --git a/Benchmarks/BenchmarkAggregate.cs b/Benchmarks/BenchmarkAggregate.cs new file mode 100644 index 0000000..2c40a09 --- /dev/null +++ b/Benchmarks/BenchmarkAggregate.cs @@ -0,0 +1,93 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; + +namespace Tests +{ + public partial class Benchmarks + { + private static readonly Func mulXInts = (acc, x) => acc += x * x; + + //[Benchmark] + //public double IntArrayAggregateLinq() + //{ + // return intArray.Aggregate(0.0D, mulXInts); + //} + + //[Benchmark] + //public double IntArrayAggregateFast() + //{ + // return intArray.AggregateF(0.0D, mulXInts); + //} + + //[Benchmark] + //public double IntReadOnlyArrayAggregateLinq() + //{ + // return Array.AsReadOnly(intArray).Aggregate(0.0D, mulXInts); + //} + + //[Benchmark] + //public double IntReadOnlyArrayAggregateFast() + //{ + // return Array.AsReadOnly(intArray).AggregateF(0.0D, mulXInts); + //} + + //[Benchmark] + //public double IntSpanAggregateForEach() + //{ + // //return intArray.AsSpan().Aggregate(0.0, mulXInts); + // double result = 0.0D; + // foreach (var v in intArray.AsSpan()) + // { + // result = mulXInts(result, v); + // } + // return result; + + //} + + //[Benchmark] + //public double IntSpanAggregateFast() + //{ + // return intArray.AsSpan().AggregateF(0.0, mulXInts); + //} + + //[Benchmark] + //public double IntArrayAggregateLinqSelector() + //{ + // return intArray.Aggregate(0.0, mulXInts, acc => acc / intArray.Length); + //} + + //[Benchmark] + //public double IntArrayAggregateFastSelector() + //{ + // return intArray.AggregateF(0.0, mulXInts, acc => acc / intArray.Length); + //} + + //[Benchmark] + //public double IntListAggregateLinq() + //{ + // return intList.Aggregate(0.0, mulXInts); + //} + + //[Benchmark] + //public double IntListAggregateFast() + //{ + // return intList.AggregateF(0.0, mulXInts); + //} + + //[Benchmark] + //public double IntReadOnlyListAggregateLinq() + //{ + // return intList.AsReadOnly().Aggregate(0.0, mulXInts); + //} + + //[Benchmark] + //public double IntReadOnlyListAggregateFast() + //{ + // return intList.AsReadOnly().AggregateF(0.0, mulXInts); + //} + } +} diff --git a/Benchmarks/BenchmarkAverage.cs b/Benchmarks/BenchmarkAverage.cs new file mode 100644 index 0000000..376f69b --- /dev/null +++ b/Benchmarks/BenchmarkAverage.cs @@ -0,0 +1,50 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; + +namespace Tests +{ + public partial class Benchmarks + { + //[Benchmark] + //public double IntArrayAverageLinq() + //{ + // return intArray.Average(); + //} + + //[Benchmark] + //public double IntArrayAverageFast() + //{ + // return intArray.AverageF(); + //} + + //[Benchmark] + //public double IntArrayAverageFastSIMD() + //{ + // return intArray.AverageS(); + //} + + + //[Benchmark] + //public double IntListAverageLinq() + //{ + // return intList.Average(); + //} + + //[Benchmark] + //public double IntListAverageFast() + //{ + // return intList.AverageF(); + //} + + //[Benchmark] + //public double IntListAverageFastSIMD() + //{ + // return intList.AverageS(); + //} + + } +} diff --git a/Benchmarks/BenchmarkFirst.cs b/Benchmarks/BenchmarkFirst.cs new file mode 100644 index 0000000..556dbc7 --- /dev/null +++ b/Benchmarks/BenchmarkFirst.cs @@ -0,0 +1,95 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; + +namespace Tests +{ + public partial class Benchmarks + { + private static readonly Func firstInts = (x) => x > 0; + + //[Benchmark] + //public double IntArrayFirstLinqSelector() + //{ + // return intArray.First(firstInts); + //} + + //[Benchmark] + //public double IntArrayFirstFastSelector() + //{ + // return intArray.FirstF(firstInts); + //} + + //[Benchmark] + //public double IntArrayFirstArrayFindSelector() + //{ + // Predicate predicate = new Predicate(firstInts); + // return Array.Find(intArray, predicate); + //} + + + //[Benchmark] + //public double IntSpanFirstForEachSelector() + //{ + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // foreach (int i in asSpan) + // { + // if (firstInts(i)) + // { + // return i; + // } + // } + + // return 0; + //} + + //[Benchmark] + //public double IntSpanFirstFastSelector() + //{ + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // return asSpan.FirstF(firstInts); + //} + + //[Benchmark] + //public double IntListFirstLinqSelector() + //{ + // return intList.First(firstInts); + //} + + //[Benchmark] + //public double IntListFirstFastSelector() + //{ + // return intList.FirstF(firstInts); + //} + + //[Benchmark] + //public double IntAsListReadOnlyFirstLinqSelector() + //{ + // return intList.AsReadOnly().First(firstInts); + //} + + //[Benchmark] + //public double IntAsListReadOnlyFirstFastSelector() + //{ + // return intList.AsReadOnly().FirstF(firstInts); + //} + + //[Benchmark] + //public double IntArrayAsReadOnlyFirstLinqSelector() + //{ + // return Array.AsReadOnly(intArray).First(firstInts); + //} + + //[Benchmark] + //public double IntArrayAsReadOnlyFirstFastSelector() + //{ + // return Array.AsReadOnly(intArray).FirstF(firstInts); + //} + + } +} diff --git a/Benchmarks/BenchmarkLast.cs b/Benchmarks/BenchmarkLast.cs new file mode 100644 index 0000000..3469f57 --- /dev/null +++ b/Benchmarks/BenchmarkLast.cs @@ -0,0 +1,95 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; + +namespace Tests +{ + public partial class Benchmarks + { + private static readonly Func LastInts = (x) => x > 0; + + + //[Benchmark] + //public double IntArrayLastLinqSelector() + //{ + // return intArray.Last(LastInts); + //} + + //[Benchmark] + //public double IntArrayLastFastSelector() + //{ + // return intArray.LastF(LastInts); + //} + + //[Benchmark] + //public double IntArrayLastArrayFindSelector() + //{ + // Predicate predicate = new Predicate(LastInts); + // return Array.Find(intArray, predicate); + //} + + + //[Benchmark] + //public double IntSpanLastForEachSelector() + //{ + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // foreach (int i in asSpan) + // { + // if (LastInts(i)) + // { + // return i; + // } + // } + + // return 0; + //} + + //[Benchmark] + //public double IntSpanLastFastSelector() + //{ + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // return asSpan.LastF(LastInts); + //} + + //[Benchmark] + //public double IntListLastLinqSelector() + //{ + // return intList.Last(LastInts); + //} + + //[Benchmark] + //public double IntListLastFastSelector() + //{ + // return intList.LastF(LastInts); + //} + + //[Benchmark] + //public double IntAsListReadOnlyLastLinqSelector() + //{ + // return intList.AsReadOnly().Last(LastInts); + //} + + //[Benchmark] + //public double IntAsListReadOnlyLastFastSelector() + //{ + // return intList.AsReadOnly().LastF(LastInts); + //} + + //[Benchmark] + //public double IntArrayAsReadOnlyLastLinqSelector() + //{ + // return Array.AsReadOnly(intArray).Last(LastInts); + //} + + //[Benchmark] + //public double IntArrayAsReadOnlyLastFastSelector() + //{ + // return Array.AsReadOnly(intArray).LastF(LastInts); + //} + } +} diff --git a/Benchmarks/BenchmarkOrderBy.cs b/Benchmarks/BenchmarkOrderBy.cs new file mode 100644 index 0000000..006a335 --- /dev/null +++ b/Benchmarks/BenchmarkOrderBy.cs @@ -0,0 +1,26 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; + +namespace Tests +{ + public partial class Benchmarks + { + private static readonly Func orderBy = (x) => x - 1; + + //[Benchmark] + //public int IntArrayOrderByLinq() + //{ + // return intArray.OrderBy(orderBy).Sum(); + //} + + //[Benchmark] + //public int IntArrayOrderByFast() + //{ + // return intArray.OrderByF(orderBy).Sum(); + //} + } +} diff --git a/Benchmarks/BenchmarkSum.cs b/Benchmarks/BenchmarkSum.cs new file mode 100644 index 0000000..7abe5ef --- /dev/null +++ b/Benchmarks/BenchmarkSum.cs @@ -0,0 +1,277 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; + +namespace Tests +{ + public partial class Benchmarks + { + private static readonly Func sumDivide = (x) => x / 2; + + //[Benchmark] + //public int ByteArraySumLinq() + //{ + // return byteArray.Aggregate(0, (current, b1) => current + b1); + //} + + //[Benchmark] + //public uint ByteArraySumFast() + //{ + // return byteArray.SumF(); + //} + + + //[Benchmark] + //public int ShortArraySumLinq() + //{ + // return shortArray.Aggregate(0, (current, s1) => current + s1); + //} + + //[Benchmark] + //public int ShortArraySumFast() + //{ + // return shortArray.SumF(); + //} + + + //[Benchmark] + //public int IntArraySumLinq() + //{ + // return intArray.Sum(); + //} + + //[Benchmark] + //public int IntArraySumFast() + //{ + // return intArray.SumF(); + //} + + //[Benchmark] + //public int IntSpanSumFor() + //{ + // int val = 0; + // Span span = intArray.AsSpan(); + // for (int index = 0; index < span.Length; index++) + // { + // val += span[index]; + // } + + // return val; + //} + + //[Benchmark] + //public int IntSpanSumFast() + //{ + // return intArray.AsSpan().SumF(); + //} + + //[Benchmark] + //public int IntIArraySumFast() + //{ + // return ((IReadOnlyList)intArray).SumF(); + //} + + //[Benchmark] + //public int IntListSumLinq() + //{ + // return intList.Sum(); + //} + + //[Benchmark] + //public int IntListSumFast() + //{ + // return intList.SumF(); + //} + + //[Benchmark] + //public int IntIReadOnlyListSumLinq() + //{ + // return ((IReadOnlyList)intList).Sum(); + //} + + //[Benchmark] + //public int IntIReadOnlyListSumFast() + //{ + // return ((IReadOnlyList)intList).SumF(); + //} + + + //[Benchmark] + //public int IntArraySumLinqSelect() + //{ + // return intArray.Sum(x => x / 2); + //} + + //[Benchmark] + //public int IntArraySumFastSelect() + //{ + // return intArray.SumF(x => x / 2); + //} + + //[Benchmark] + //public double IntReadOnlyArraySumWithSelectLinq() + //{ + // return Array.AsReadOnly(intArray).Sum(x => x / 2); + //} + + //[Benchmark] + //public double IntReadOnlyArraySumWithSelectFast() + //{ + // return Array.AsReadOnly(intArray).SumF(x => x / 2); + //} + + //[Benchmark] + //public int IntArraySumFastSIMD() + //{ + // return intArray.SumS(); + //} + + //[Benchmark] + //public int? IntNullArraySumLinq() + //{ + // return intNullArray.Sum(); + //} + + //[Benchmark] + //public int? IntNullArraySumFast() + //{ + // return intNullArray.SumF(); + //} + + //[Benchmark] + //public int IntNullArraySumLinqSelect() + //{ + // return intNullArray.Sum(x => x/2 ?? 0); + //} + + //[Benchmark] + //public int IntNullArraySumFastSelect() + //{ + // return intNullArray.SumF(x => x/2 ?? 0); + //} + + //[Benchmark] + //public float FloatArraySumLinq() + //{ + // return floatArray.Sum(); + //} + + //[Benchmark] + //public float FloatArraySumFast() + //{ + // return floatArray.SumF(); + //} + + //[Benchmark] + //public float FloatListSumLinq() + //{ + // return floatList.Sum(); + //} + + //[Benchmark] + //public float FloatListSumFast() + //{ + // return floatList.SumF(); + //} + + //[Benchmark] + //public float FloatArraySumLinqSelect() + //{ + // return floatArray.Sum(x => x / 2); + //} + + //[Benchmark] + //public float FloatArraySumFastSelect() + //{ + // return floatArray.SumF(x => x / 2); + //} + + //[Benchmark] + //public float? FloatNullArraySumLinq() + //{ + // return floatNullArray.Sum(); + //} + + //[Benchmark] + //public float? FloatNullArraySumFast() + //{ + // return floatNullArray.SumF(); + //} + + //[Benchmark] + //public float FloatNullArraySumLinqSelect() + //{ + // return floatNullArray.Sum(x => x / 2 ?? 0); + //} + + //[Benchmark] + //public float FloatNullArraySumFastSelect() + //{ + // return floatNullArray.SumF(x => x / 2 ?? 0); + //} + + + //[Benchmark] + //public double DoubleArraySumLinq() + //{ + // return doubleArray.Sum(); + //} + + //[Benchmark] + //public double DoubleArraySumFast() + //{ + // return doubleArray.SumF(); + //} + + //[Benchmark] + //public double DoubleListSumLinq() + //{ + // return doubleList.Sum(); + //} + + //[Benchmark] + //public double DoubleListSumFast() + //{ + // return doubleList.SumF(); + //} + + //[Benchmark] + //public double DoubleArraySumLinqSelect() + //{ + // return doubleArray.Sum(x => x / 2); + //} + + //[Benchmark] + //public double DoubleArraySumFastSelect() + //{ + // return doubleArray.SumF(x => x / 2); + //} + + //[Benchmark] + //public double? DoubleNullArraySumLinq() + //{ + // return doubleNullArray.Sum(); + //} + + //[Benchmark] + //public double? DoubleNullArraySumFast() + //{ + // return doubleNullArray.SumF(); + //} + + //[Benchmark] + //public double? DoubleNullArraySumLinqSelect() + //{ + // return doubleNullArray.Sum(x => x / 2 ?? 0); + //} + + //[Benchmark] + //public double? DoubleNullArraySumFastSelect() + //{ + // return doubleNullArray.SumF(x => x / 2 ?? 0); + //} + } +} diff --git a/Benchmarks/BenchmarkWhereSum.cs b/Benchmarks/BenchmarkWhereSum.cs new file mode 100644 index 0000000..9ab07f5 --- /dev/null +++ b/Benchmarks/BenchmarkWhereSum.cs @@ -0,0 +1,307 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; +using JM.LinqFaster.SIMD; + +namespace Tests +{ + public partial class Benchmarks + { + + [Benchmark] + public int ByteArrayWhereSumLinq() + { + return byteArray.Where(x=> x>0).Aggregate(0, (current, b1) => current + b1); + } + + [Benchmark] + public uint ByteArrayWhereSumFast() + { + return byteArray.WhereSumF(x => x > 0); + } + + + [Benchmark] + public int ShortArrayWhereSumLinq() + { + return shortArray.Where(x => x > 0).Aggregate(0, (current, s1) => current + s1); + } + + [Benchmark] + public int ShortArrayWhereSumFast() + { + return shortArray.WhereSumF(x => x > 0); + } + + + [Benchmark] + public int IntArrayWhereSumLinq() + { + return intArray.Where(x => x > 0).Sum(); + } + + [Benchmark] + public int IntArrayWhereSumFast() + { + return intArray.WhereSumF(x => x > 0); + } + + [Benchmark] + public int IntSpanWhereSumFor() + { + int val = 0; + Span span = intArray.AsSpan(); + for (int index = 0; index < span.Length; index++) + { + if (span[index] > 0) + { + val += span[index]; + } + } + + return val; + } + + [Benchmark] + public int IntSpanWhereSumFast() + { + return intArray.AsSpan().WhereSumF(x => x > 0); + } + + [Benchmark] + public int IntIArrayWhereSumFast() + { + return ((IReadOnlyList)intArray).WhereSumF(x => x > 0); + } + + [Benchmark] + public int IntListWhereSumLinq() + { + return intList.Where(x => x > 0).Sum(); + } + + [Benchmark] + public int IntListWhereSumFast() + { + return intList.WhereSumF(x => x > 0); + } + + [Benchmark] + public int IntIReadOnlyListWhereSumLinq() + { + return ((IReadOnlyList)intList).Where(x => x > 0).Sum(); + } + + [Benchmark] + public int IntIReadOnlyListWhereSumFast() + { + return ((IReadOnlyList)intList).WhereSumF(x => x > 0); + } + + + [Benchmark] + public int IntArrayWhereSumLinqSelect() + { + return intArray.Where(x => x > 0).Sum(x => x / 2); + } + + [Benchmark] + public int IntArrayWhereSumFastSelect() + { + return intArray.WhereSumF(x => x > 0, x => x / 2); + } + + [Benchmark] + public double IntReadOnlyArraySumWithSelectLinq() + { + return Array.AsReadOnly(intArray).Where(x => x > 0).Sum(x => x / 2); + } + + [Benchmark] + public double IntReadOnlyArraySumWithSelectFast() + { + return Array.AsReadOnly(intArray).WhereSumF(x => x > 0, x => x / 2); + } + + /* + [Benchmark] + public int IntArrayWhereSumFastSIMD() + { + return intArray.WhereSumS(x => x > 0); + } + */ + [Benchmark] + public int? IntNullArrayWhereSumLinq() + { + return intNullArray.Where(x => x > 0).Sum(); + } + + [Benchmark] + public int? IntNullArrayWhereSumFast() + { + return intNullArray.WhereSumF(x => x > 0); + } + + [Benchmark] + public int IntNullArrayWhereSumLinqSelect() + { + return intNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); + } + + [Benchmark] + public int IntNullArrayWhereSumFastSelect() + { + return intNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); + } + + [Benchmark] + public float FloatArrayWhereSumLinq() + { + return floatArray.Where(x => x > 0).Sum(); + } + + [Benchmark] + public float FloatArrayWhereSumFast() + { + return floatArray.WhereSumF(x => x > 0); + } + + [Benchmark] + public float FloatListWhereSumLinq() + { + return floatList.Where(x => x > 0).Sum(); + } + + [Benchmark] + public float FloatListWhereSumFast() + { + return floatList.WhereSumF(x => x > 0); + } + + [Benchmark] + public float FloatArrayWhereSumLinqSelect() + { + return floatArray.Where(x => x > 0).Sum( x => x / 2); + } + + [Benchmark] + public float FloatArrayWhereSumFastSelect() + { + return floatArray.WhereSumF(x => x > 0, x => x / 2); + } + + [Benchmark] + public float? FloatNullArrayWhereSumLinq() + { + return floatNullArray.Where(x => x > 0).Sum(); + } + + [Benchmark] + public float? FloatNullArrayWhereSumFast() + { + return floatNullArray.WhereSumF(x => x > 0); + } + + [Benchmark] + public float FloatNullArrayWhereSumLinqSelect() + { + return floatNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); + } + + [Benchmark] + public float FloatNullArrayWhereSumFastSelect() + { + return floatNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); + } + + + [Benchmark] + public double DoubleArrayWhereSumLinq() + { + return doubleArray.Where(x => x > 0).Sum(); + } + + [Benchmark] + public double DoubleArrayWhereSumFast() + { + return doubleArray.WhereSumF(x => x > 0); + } + + [Benchmark] + public double DoubleListWhereSumLinq() + { + return doubleList.Where(x => x > 0).Sum(); + } + + [Benchmark] + public double DoubleListWhereSumFast() + { + return doubleList.WhereSumF(x => x > 0); + } + + [Benchmark] + public double DoubleArrayWhereSumLinqSelect() + { + return doubleArray.Where(x => x > 0).Sum(x => x / 2); + } + + [Benchmark] + public double DoubleArrayWhereSumFastSelect() + { + return doubleArray.WhereSumF(x => x > 0, x => x / 2); + } + + [Benchmark] + public double? DoubleNullArrayWhereSumLinq() + { + return doubleNullArray.Where(x => x > 0).Sum(); + } + + [Benchmark] + public double? DoubleNullArrayWhereSumFast() + { + return doubleNullArray.WhereSumF(x => x > 0); + } + + [Benchmark] + public double? DoubleNullArrayWhereSumLinqSelect() + { + return doubleNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); + } + + [Benchmark] + public double? DoubleNullArrayWhereSumFastSelect() + { + return doubleNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); + } + + [Benchmark] + public int IntListSumWithSelectLinq() + { + return intList.Where(x => x > 0).Sum(x => x / 2); + } + + [Benchmark] + public int IntListSumWithSelectFast() + { + return intList.WhereSumF(x => x > 0, x => x / 2); + } + + [Benchmark] + public double IntReadOnlyListSumWithSelectLinq() + { + return intList.AsReadOnly().Where(x => x > 0).Sum(x => x / 2); + } + + [Benchmark] + public double IntReadOnlyListSumWithSelectFast() + { + return intList.AsReadOnly().WhereSumF(x => x > 0, x => x / 2); + } + + } +} diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 044e03b..2b89f68 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -34,9 +34,6 @@ public partial class Benchmarks private double?[] doubleNullArray; private string[] strarray; - private static readonly Func mulXInts = (acc, x) => acc += x * x; - private static readonly Func firstInts = (x) => x > 0; - private static readonly Func LastInts = (x) => x > 0; [Params(1000000)] @@ -84,585 +81,7 @@ public void Setup() array2[TEST_SIZE / 2] = 0; } - //[Benchmark] - //public int IntArrayOrderByLinq() - //{ - // return intArray.OrderBy((x => x - 1)).Sum(); - //} - - //[Benchmark] - //public int IntArrayOrderByFast() - //{ - // return intArray.OrderByF((x => x - 1)).Sum(); - //} - - - //[Benchmark] - //public int ByteArraySumLinq() - //{ - // return byteArray.Aggregate(0, (current, b1) => current + b1); - //} - - //[Benchmark] - //public uint ByteArraySumFast() - //{ - // return byteArray.SumF(); - //} - - - //[Benchmark] - //public int ShortArraySumLinq() - //{ - // return shortArray.Aggregate(0, (current, s1) => current + s1); - //} - - //[Benchmark] - //public int ShortArraySumFast() - //{ - // return shortArray.SumF(); - //} - - - //[Benchmark] - //public int IntArraySumLinq() - //{ - // return intArray.Sum(); - //} - - //[Benchmark] - //public int IntArraySumFast() - //{ - // return intArray.SumF(); - //} - - //[Benchmark] - //public int IntSpanSumFor() - //{ - // int val = 0; - // Span span = intArray.AsSpan(); - // for (int index = 0; index < span.Length; index++) - // { - // val += span[index]; - // } - - // return val; - //} - - //[Benchmark] - //public int IntSpanSumFast() - //{ - // return intArray.AsSpan().SumF(); - //} - - //[Benchmark] - //public int IntIArraySumFast() - //{ - // return ((IReadOnlyList)intArray).SumF(); - //} - - //[Benchmark] - //public int IntListSumLinq() - //{ - // return intList.Sum(); - //} - - //[Benchmark] - //public int IntListSumFast() - //{ - // return intList.SumF(); - //} - - //[Benchmark] - //public int IntIReadOnlyListSumLinq() - //{ - // return ((IReadOnlyList)intList).Sum(); - //} - - //[Benchmark] - //public int IntIReadOnlyListSumFast() - //{ - // return ((IReadOnlyList)intList).SumF(); - //} - - - //[Benchmark] - //public int IntArraySumLinqSelect() - //{ - // return intArray.Sum(x => x / 2); - //} - - //[Benchmark] - //public int IntArraySumFastSelect() - //{ - // return intArray.SumF(x => x / 2); - //} - - //[Benchmark] - //public double IntReadOnlyArraySumWithSelectLinq() - //{ - // return Array.AsReadOnly(intArray).Sum(x => x / 2); - //} - - //[Benchmark] - //public double IntReadOnlyArraySumWithSelectFast() - //{ - // return Array.AsReadOnly(intArray).SumF(x => x / 2); - //} - - //[Benchmark] - //public int IntArraySumFastSIMD() - //{ - // return intArray.SumS(); - //} - - //[Benchmark] - //public int? IntNullArraySumLinq() - //{ - // return intNullArray.Sum(); - //} - - //[Benchmark] - //public int? IntNullArraySumFast() - //{ - // return intNullArray.SumF(); - //} - - //[Benchmark] - //public int IntNullArraySumLinqSelect() - //{ - // return intNullArray.Sum(x => x/2 ?? 0); - //} - - //[Benchmark] - //public int IntNullArraySumFastSelect() - //{ - // return intNullArray.SumF(x => x/2 ?? 0); - //} - - //[Benchmark] - //public float FloatArraySumLinq() - //{ - // return floatArray.Sum(); - //} - - //[Benchmark] - //public float FloatArraySumFast() - //{ - // return floatArray.SumF(); - //} - - //[Benchmark] - //public float FloatListSumLinq() - //{ - // return floatList.Sum(); - //} - - //[Benchmark] - //public float FloatListSumFast() - //{ - // return floatList.SumF(); - //} - - //[Benchmark] - //public float FloatArraySumLinqSelect() - //{ - // return floatArray.Sum(x => x / 2); - //} - - //[Benchmark] - //public float FloatArraySumFastSelect() - //{ - // return floatArray.SumF(x => x / 2); - //} - - //[Benchmark] - //public float? FloatNullArraySumLinq() - //{ - // return floatNullArray.Sum(); - //} - - //[Benchmark] - //public float? FloatNullArraySumFast() - //{ - // return floatNullArray.SumF(); - //} - - //[Benchmark] - //public float FloatNullArraySumLinqSelect() - //{ - // return floatNullArray.Sum(x => x / 2 ?? 0); - //} - - //[Benchmark] - //public float FloatNullArraySumFastSelect() - //{ - // return floatNullArray.SumF(x => x / 2 ?? 0); - //} - - - //[Benchmark] - //public double DoubleArraySumLinq() - //{ - // return doubleArray.Sum(); - //} - - //[Benchmark] - //public double DoubleArraySumFast() - //{ - // return doubleArray.SumF(); - //} - - //[Benchmark] - //public double DoubleListSumLinq() - //{ - // return doubleList.Sum(); - //} - - //[Benchmark] - //public double DoubleListSumFast() - //{ - // return doubleList.SumF(); - //} - //[Benchmark] - //public double DoubleArraySumLinqSelect() - //{ - // return doubleArray.Sum(x => x / 2); - //} - - //[Benchmark] - //public double DoubleArraySumFastSelect() - //{ - // return doubleArray.SumF(x => x / 2); - //} - - //[Benchmark] - //public double? DoubleNullArraySumLinq() - //{ - // return doubleNullArray.Sum(); - //} - - //[Benchmark] - //public double? DoubleNullArraySumFast() - //{ - // return doubleNullArray.SumF(); - //} - - //[Benchmark] - //public double? DoubleNullArraySumLinqSelect() - //{ - // return doubleNullArray.Sum(x => x / 2 ?? 0); - //} - - //[Benchmark] - //public double? DoubleNullArraySumFastSelect() - //{ - // return doubleNullArray.SumF(x => x / 2 ?? 0); - //} - - //[Benchmark] - //public double IntArrayAverageLinq() - //{ - // return intArray.Average(); - //} - - //[Benchmark] - //public double IntArrayAverageFast() - //{ - // return intArray.AverageF(); - //} - - //[Benchmark] - //public double IntArrayAverageFastSIMD() - //{ - // return intArray.AverageS(); - //} - - - //[Benchmark] - //public double IntListAverageLinq() - //{ - // return intList.Average(); - //} - - //[Benchmark] - //public double IntListAverageFast() - //{ - // return intList.AverageF(); - //} - - //[Benchmark] - //public double IntListAverageFastSIMD() - //{ - // return intList.AverageS(); - //} - - //[Benchmark] - //public int IntListSumWithSelectLinq() - //{ - // return intList.Sum(x => x / 2); - //} - - //[Benchmark] - //public int IntListSumWithSelectFast() - //{ - // return intList.SumF(x => x / 2); - //} - - //[Benchmark] - //public double IntReadOnlyListSumWithSelectLinq() - //{ - // return intList.AsReadOnly().Sum(x => x / 2); - //} - - //[Benchmark] - //public double IntReadOnlyListSumWithSelectFast() - //{ - // return intList.AsReadOnly().SumF(x => x / 2); - //} - - - - //[Benchmark] - //public double IntArrayAggregateLinq() - //{ - // return intArray.Aggregate(0.0D, mulXInts); - //} - - //[Benchmark] - //public double IntArrayAggregateFast() - //{ - // return intArray.AggregateF(0.0D, mulXInts); - //} - - //[Benchmark] - //public double IntReadOnlyArrayAggregateLinq() - //{ - // return Array.AsReadOnly(intArray).Aggregate(0.0D, mulXInts); - //} - - //[Benchmark] - //public double IntReadOnlyArrayAggregateFast() - //{ - // return Array.AsReadOnly(intArray).AggregateF(0.0D, mulXInts); - //} - - //[Benchmark] - //public double IntSpanAggregateForEach() - //{ - // //return intArray.AsSpan().Aggregate(0.0, mulXInts); - // double result = 0.0D; - // foreach (var v in intArray.AsSpan()) - // { - // result = mulXInts(result, v); - // } - // return result; - - //} - - //[Benchmark] - //public double IntSpanAggregateFast() - //{ - // return intArray.AsSpan().AggregateF(0.0, mulXInts); - //} - - //[Benchmark] - //public double IntArrayAggregateLinqSelector() - //{ - // return intArray.Aggregate(0.0, mulXInts, acc => acc / intArray.Length); - //} - - //[Benchmark] - //public double IntArrayAggregateFastSelector() - //{ - // return intArray.AggregateF(0.0, mulXInts, acc => acc / intArray.Length); - //} - - //[Benchmark] - //public double IntListAggregateLinq() - //{ - // return intList.Aggregate(0.0, mulXInts); - //} - - //[Benchmark] - //public double IntListAggregateFast() - //{ - // return intList.AggregateF(0.0, mulXInts); - //} - - //[Benchmark] - //public double IntReadOnlyListAggregateLinq() - //{ - // return intList.AsReadOnly().Aggregate(0.0, mulXInts); - //} - - //[Benchmark] - //public double IntReadOnlyListAggregateFast() - //{ - // return intList.AsReadOnly().AggregateF(0.0, mulXInts); - //} - - - //[Benchmark] - //public double IntArrayFirstLinqSelector() - //{ - // return intArray.First(firstInts); - //} - - //[Benchmark] - //public double IntArrayFirstFastSelector() - //{ - // return intArray.FirstF(firstInts); - //} - - //[Benchmark] - //public double IntArrayFirstArrayFindSelector() - //{ - // Predicate predicate = new Predicate(firstInts); - // return Array.Find(intArray, predicate); - //} - - - //[Benchmark] - //public double IntSpanFirstForEachSelector() - //{ - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // foreach (int i in asSpan) - // { - // if (firstInts(i)) - // { - // return i; - // } - // } - - // return 0; - //} - - //[Benchmark] - //public double IntSpanFirstFastSelector() - //{ - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // return asSpan.FirstF(firstInts); - //} - - //[Benchmark] - //public double IntListFirstLinqSelector() - //{ - // return intList.First(firstInts); - //} - - //[Benchmark] - //public double IntListFirstFastSelector() - //{ - // return intList.FirstF(firstInts); - //} - - //[Benchmark] - //public double IntAsListReadOnlyFirstLinqSelector() - //{ - // return intList.AsReadOnly().First(firstInts); - //} - - //[Benchmark] - //public double IntAsListReadOnlyFirstFastSelector() - //{ - // return intList.AsReadOnly().FirstF(firstInts); - //} - - //[Benchmark] - //public double IntArrayAsReadOnlyFirstLinqSelector() - //{ - // return Array.AsReadOnly(intArray).First(firstInts); - //} - - //[Benchmark] - //public double IntArrayAsReadOnlyFirstFastSelector() - //{ - // return Array.AsReadOnly(intArray).FirstF(firstInts); - //} - - - //[Benchmark] - //public double IntArrayLastLinqSelector() - //{ - // return intArray.Last(LastInts); - //} - - //[Benchmark] - //public double IntArrayLastFastSelector() - //{ - // return intArray.LastF(LastInts); - //} - - //[Benchmark] - //public double IntArrayLastArrayFindSelector() - //{ - // Predicate predicate = new Predicate(LastInts); - // return Array.Find(intArray, predicate); - //} - - - //[Benchmark] - //public double IntSpanLastForEachSelector() - //{ - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // foreach (int i in asSpan) - // { - // if (LastInts(i)) - // { - // return i; - // } - // } - - // return 0; - //} - - //[Benchmark] - //public double IntSpanLastFastSelector() - //{ - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // return asSpan.LastF(LastInts); - //} - - //[Benchmark] - //public double IntListLastLinqSelector() - //{ - // return intList.Last(LastInts); - //} - - //[Benchmark] - //public double IntListLastFastSelector() - //{ - // return intList.LastF(LastInts); - //} - - //[Benchmark] - //public double IntAsListReadOnlyLastLinqSelector() - //{ - // return intList.AsReadOnly().Last(LastInts); - //} - - //[Benchmark] - //public double IntAsListReadOnlyLastFastSelector() - //{ - // return intList.AsReadOnly().LastF(LastInts); - //} - - //[Benchmark] - //public double IntArrayAsReadOnlyLastLinqSelector() - //{ - // return Array.AsReadOnly(intArray).Last(LastInts); - //} - - //[Benchmark] - //public double IntArrayAsReadOnlyLastFastSelector() - //{ - // return Array.AsReadOnly(intArray).LastF(LastInts); - //} //[Benchmark] @@ -722,24 +141,6 @@ public void Setup() // return LinqFasterSIMD.RepeatSB(5, TEST_SIZE); //} - //[Benchmark] - //public int IntArrayMinLinq() - //{ - // return intArray.Min(); - //} - - //[Benchmark] - //public int IntArrayMinFast() - //{ - // return intArray.MinF(); - //} - - //[Benchmark] - //public int IntArrayMinFastSIMD() - //{ - // return intArray.MinS(); - //} - //[Benchmark] //public bool IntArraySequenceEqual() //{ diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 291890b..e002907 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -198,9 +198,16 @@ + + + + + + + diff --git a/Benchmarks/BenchmarksMin.cs b/Benchmarks/BenchmarksMin.cs index 0ce5b52..5fb1465 100644 --- a/Benchmarks/BenchmarksMin.cs +++ b/Benchmarks/BenchmarksMin.cs @@ -1,163 +1,166 @@ using System; using System.Linq; - using BenchmarkDotNet.Attributes; -using JM.LinqFaster; - namespace Tests { public partial class Benchmarks { - private static readonly Func MinInts = (x) => x + 1; - - [Benchmark] - public double IntArrayMinLinq() - { - return intArray.Min(); - } - - [Benchmark] - public double IntArrayMinFast() - { - return intArray.MinF(); - } - - [Benchmark] - public double IntSpanMinForEach() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - int Min = int.MinValue; - foreach (int i in asSpan) - { - if (Min > i) - { - Min = i; - } - } - - return Min; - } - - [Benchmark] - public double IntSpanMinFast() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - return asSpan.MinF(); - } - - [Benchmark] - public double IntListMinLinq() - { - return intList.Min(); - } - - [Benchmark] - public double IntListMinFast() - { - return intList.MinF(); - } - - [Benchmark] - public double IntAsListReadOnlyMinLinq() - { - return intList.AsReadOnly().Min(); - } - - [Benchmark] - public double IntAsListReadOnlyMinFast() - { - return intList.AsReadOnly().MinF(); - } - - [Benchmark] - public double IntArrayAsReadOnlyMinLinq() - { - return Array.AsReadOnly(intArray).Min(); - } - - [Benchmark] - public double IntArrayAsReadOnlyMinFast() - { - return Array.AsReadOnly(intArray).MinF(); - } - - - [Benchmark] - public double IntArrayMinLinqSelector() - { - return intArray.Min(MinInts); - } - - [Benchmark] - public double IntArrayMinFastSelector() - { - return intArray.MinF(MinInts); - } - - [Benchmark] - public double IntSpanMinForEachSelector() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - int Min = int.MinValue; - foreach (int i in asSpan) - { - int l = MinInts(i); - if (Min > l) - { - Min = l; - } - } - - return Min; - } - - [Benchmark] - public double IntSpanMinFastSelector() - { - int[] localArray = intArray; - Span asSpan = localArray.AsSpan(); - return asSpan.MinF(MinInts); - } - - [Benchmark] - public double IntListMinLinqSelector() - { - return intList.Min(MinInts); - } - - [Benchmark] - public double IntListMinFastSelector() - { - return intList.MinF(MinInts); - } - - [Benchmark] - public double IntAsListReadOnlyMinLinqSelector() - { - return intList.AsReadOnly().Min(MinInts); - } - - [Benchmark] - public double IntAsListReadOnlyMinFastSelector() - { - return intList.AsReadOnly().MinF(MinInts); - } - - [Benchmark] - public double IntArrayAsReadOnlyMinLinqSelector() - { - return Array.AsReadOnly(intArray).Min(MinInts); - } - - [Benchmark] - public double IntArrayAsReadOnlyMinFastSelector() - { - return Array.AsReadOnly(intArray).MinF(MinInts); - } + private static readonly Func MinInts = (x) => x + 1; + + //[Benchmark] + //public double IntArrayMinLinq() + //{ + // return intArray.Min(); + //} + + // [Benchmark] + // public double IntArrayMinFast() + // { + // return intArray.MinF(); + // } + + //[Benchmark] + //public int IntArrayMinFastSIMD() + //{ + // return intArray.MinS(); + //} + + // [Benchmark] + // public double IntSpanMinForEach() + // { + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // int Min = int.MinValue; + // foreach (int i in asSpan) + // { + // if (Min > i) + // { + // Min = i; + // } + // } + + // return Min; + // } + + // [Benchmark] + // public double IntSpanMinFast() + // { + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // return asSpan.MinF(); + // } + + // [Benchmark] + // public double IntListMinLinq() + // { + // return intList.Min(); + // } + + // [Benchmark] + // public double IntListMinFast() + // { + // return intList.MinF(); + // } + + // [Benchmark] + // public double IntAsListReadOnlyMinLinq() + // { + // return intList.AsReadOnly().Min(); + // } + + // [Benchmark] + // public double IntAsListReadOnlyMinFast() + // { + // return intList.AsReadOnly().MinF(); + // } + + // [Benchmark] + // public double IntArrayAsReadOnlyMinLinq() + // { + // return Array.AsReadOnly(intArray).Min(); + // } + + // [Benchmark] + // public double IntArrayAsReadOnlyMinFast() + // { + // return Array.AsReadOnly(intArray).MinF(); + // } + + + // [Benchmark] + // public double IntArrayMinLinqSelector() + // { + // return intArray.Min(MinInts); + // } + + // [Benchmark] + // public double IntArrayMinFastSelector() + // { + // return intArray.MinF(MinInts); + // } + + // [Benchmark] + // public double IntSpanMinForEachSelector() + // { + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // int Min = int.MinValue; + // foreach (int i in asSpan) + // { + // int l = MinInts(i); + // if (Min > l) + // { + // Min = l; + // } + // } + + // return Min; + // } + + // [Benchmark] + // public double IntSpanMinFastSelector() + // { + // int[] localArray = intArray; + // Span asSpan = localArray.AsSpan(); + // return asSpan.MinF(MinInts); + // } + + // [Benchmark] + // public double IntListMinLinqSelector() + // { + // return intList.Min(MinInts); + // } + + // [Benchmark] + // public double IntListMinFastSelector() + // { + // return intList.MinF(MinInts); + // } + + // [Benchmark] + // public double IntAsListReadOnlyMinLinqSelector() + // { + // return intList.AsReadOnly().Min(MinInts); + // } + + // [Benchmark] + // public double IntAsListReadOnlyMinFastSelector() + // { + // return intList.AsReadOnly().MinF(MinInts); + // } + + // [Benchmark] + // public double IntArrayAsReadOnlyMinLinqSelector() + // { + // return Array.AsReadOnly(intArray).Min(MinInts); + // } + + // [Benchmark] + // public double IntArrayAsReadOnlyMinFastSelector() + // { + // return Array.AsReadOnly(intArray).MinF(MinInts); + // } } } diff --git a/LinqFaster/Aggregate.cs b/LinqFaster/Aggregate.cs index eac5b48..0f016ad 100644 --- a/LinqFaster/Aggregate.cs +++ b/LinqFaster/Aggregate.cs @@ -26,7 +26,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -80,7 +80,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -132,7 +132,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -186,7 +186,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -221,7 +221,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -255,7 +255,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -292,7 +292,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -327,7 +327,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -361,7 +361,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) diff --git a/LinqFaster/AnyAll.cs b/LinqFaster/AnyAll.cs index 56363c2..75996e8 100644 --- a/LinqFaster/AnyAll.cs +++ b/LinqFaster/AnyAll.cs @@ -19,7 +19,7 @@ public static bool AnyF(this IReadOnlyList source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } return source.Count > 0; } @@ -37,7 +37,7 @@ public static bool AnyF(this TSource[] source, Predicate predi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -61,7 +61,7 @@ public static bool AllF(this TSource[] source, Predicate predi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -84,7 +84,7 @@ public static bool AnyF(this Span source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } return source.Length > 0; } @@ -102,7 +102,7 @@ public static bool AnyF(this Span source, Predicate p { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -130,7 +130,7 @@ public static bool AllF(this Span source, Predicate p { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -158,7 +158,7 @@ public static bool AnyF(this List source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } return source.Count > 0; } @@ -173,7 +173,7 @@ public static bool AnyF(this List source, Predicate p { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -195,7 +195,7 @@ public static bool AllF(this List source, Predicate p { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) diff --git a/LinqFaster/AverageIList.cs b/LinqFaster/AverageIList.cs index 3ce0bf7..8796056 100644 --- a/LinqFaster/AverageIList.cs +++ b/LinqFaster/AverageIList.cs @@ -182,7 +182,7 @@ public static float AverageF(this IReadOnlyList source) { return 0; } - return (float)SumF(source) / source.Count; + return SumF(source) / (float)source.Count; } /// diff --git a/LinqFaster/Contains.cs b/LinqFaster/Contains.cs index 79e9787..d1e8d19 100644 --- a/LinqFaster/Contains.cs +++ b/LinqFaster/Contains.cs @@ -20,7 +20,7 @@ public static bool ContainsF(this TSource[] source, TSource value, IEqu { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (comparer == null) @@ -54,7 +54,7 @@ public static bool ContainsF(this Span source, TSource value, { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (comparer == null) @@ -89,7 +89,7 @@ public static bool ContainsF(this List source, TSource value, { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (comparer == null) diff --git a/LinqFaster/Count.cs b/LinqFaster/Count.cs index a65b957..8c6115f 100644 --- a/LinqFaster/Count.cs +++ b/LinqFaster/Count.cs @@ -20,7 +20,7 @@ public static int CountF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -57,7 +57,7 @@ public static int CountF(this Span source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -95,7 +95,7 @@ public static int CountF(this List source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) diff --git a/LinqFaster/Distinct.cs b/LinqFaster/Distinct.cs index c4bd673..ca5892a 100644 --- a/LinqFaster/Distinct.cs +++ b/LinqFaster/Distinct.cs @@ -21,7 +21,7 @@ public static void DistinctInPlaceF(this List source, IEqualit { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (comparer == null) diff --git a/LinqFaster/OrderBy.cs b/LinqFaster/OrderBy.cs index 456c5b8..699771d 100644 --- a/LinqFaster/OrderBy.cs +++ b/LinqFaster/OrderBy.cs @@ -19,7 +19,7 @@ public static partial class LinqFaster if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (keySelector == null) @@ -52,7 +52,7 @@ public static partial class LinqFaster /// A sequence whose elements are ordered according to a key public static TSource[] OrderByDescendingF(this TSource[] source, Func keySelector, IComparer comparer = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (keySelector == null) { @@ -87,7 +87,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (keySelector == null) @@ -116,7 +116,7 @@ public static partial class LinqFaster /// A sequence whose elements are ordered according to a key public static List OrderByDescendingF(this List source, Func keySelector, IComparer comparer = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (keySelector == null) { diff --git a/LinqFaster/Select.cs b/LinqFaster/Select.cs index 6b70bd2..6fce614 100644 --- a/LinqFaster/Select.cs +++ b/LinqFaster/Select.cs @@ -18,7 +18,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -41,7 +41,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -66,7 +66,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -94,7 +94,7 @@ public static void SelectInPlaceF(this T[] source, Func selector) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -120,7 +120,7 @@ public static void SelectInPlaceF(this Span source, Func selector) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -143,7 +143,7 @@ public static void SelectInPlaceF(this Span source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -168,7 +168,7 @@ public static void SelectInPlaceF(this Span source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -196,7 +196,7 @@ public static void SelectInPlaceF(this Span source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -222,7 +222,7 @@ public static void SelectInPlaceF(this List source, Func selector) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -245,7 +245,7 @@ public static void SelectInPlaceF(this List source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -270,7 +270,7 @@ public static void SelectInPlaceF(this List source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -299,7 +299,7 @@ public static void SelectInPlaceF(this List source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) diff --git a/LinqFaster/SelectMany.cs b/LinqFaster/SelectMany.cs index 63220f4..6ec71a1 100644 --- a/LinqFaster/SelectMany.cs +++ b/LinqFaster/SelectMany.cs @@ -18,7 +18,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -49,7 +49,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -82,7 +82,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -113,7 +113,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -145,7 +145,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -176,7 +176,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) diff --git a/LinqFaster/SelectWhere.cs b/LinqFaster/SelectWhere.cs index e697b04..c52fc97 100644 --- a/LinqFaster/SelectWhere.cs +++ b/LinqFaster/SelectWhere.cs @@ -20,7 +20,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -55,7 +55,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -92,7 +92,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -127,7 +127,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -164,7 +164,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -193,7 +193,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) diff --git a/LinqFaster/Single.cs b/LinqFaster/Single.cs index 573e41a..14ce32f 100644 --- a/LinqFaster/Single.cs +++ b/LinqFaster/Single.cs @@ -16,7 +16,7 @@ public static T SingleF(this T[] source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -40,7 +40,7 @@ public static T SingleOrDefaultF(this T[] source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -65,7 +65,7 @@ public static T SingleF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -110,7 +110,7 @@ public static T SingleOrDefaultF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -149,7 +149,7 @@ public static T SingleF(this Span source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -174,7 +174,7 @@ public static T SingleOrDefaultF(this Span source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -200,7 +200,7 @@ public static T SingleF(this Span source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -245,7 +245,7 @@ public static T SingleOrDefaultF(this Span source, Func predicate { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -284,7 +284,7 @@ public static T SingleF(this List source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -308,7 +308,7 @@ public static T SingleOrDefaultF(this List source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -333,7 +333,7 @@ public static T SingleF(this List source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -378,7 +378,7 @@ public static T SingleOrDefaultF(this List source, Func predicate { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) diff --git a/LinqFaster/Skip.cs b/LinqFaster/Skip.cs index f45fb8b..f4f46bc 100644 --- a/LinqFaster/Skip.cs +++ b/LinqFaster/Skip.cs @@ -16,7 +16,7 @@ public static T[] SkipF(this T[] source, int count) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (count < 0) { @@ -42,7 +42,7 @@ public static T[] SkipWhileF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { @@ -71,7 +71,7 @@ public static T[] SkipF(this Span source, int count) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (count < 0) { @@ -100,7 +100,7 @@ public static T[] SkipWhileF(this Span source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { @@ -135,7 +135,7 @@ public static List SkipF(this List source, int count) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (count < 0) { @@ -164,7 +164,7 @@ public static List SkipWhileF(this List source, Func predicate { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { diff --git a/LinqFaster/SumArrays.cs b/LinqFaster/SumArrays.cs index d7337f1..a1c2162 100644 --- a/LinqFaster/SumArrays.cs +++ b/LinqFaster/SumArrays.cs @@ -5,6 +5,7 @@ using JM.LinqFaster.Utils; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global +// ReSharper disable LoopCanBeConvertedToQuery namespace JM.LinqFaster diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index 3b2a1de..8b365ef 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Runtime.CompilerServices; using JM.LinqFaster.Utils; diff --git a/LinqFaster/Take.cs b/LinqFaster/Take.cs index 7a2543a..9aa2dfc 100644 --- a/LinqFaster/Take.cs +++ b/LinqFaster/Take.cs @@ -16,7 +16,7 @@ public static T[] TakeF(this T[] source, int count) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (count < 0) { @@ -42,7 +42,7 @@ public static T[] TakeWhileF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { @@ -70,7 +70,7 @@ public static T[] TakeWhileF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { @@ -99,7 +99,7 @@ public static T[] TakeF(this Span source, int count) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (count < 0) { @@ -129,7 +129,7 @@ public static T[] TakeWhileF(this Span source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { @@ -160,7 +160,7 @@ public static T[] TakeWhileF(this Span source, Func predicat { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { @@ -194,7 +194,7 @@ public static List TakeF(this List source, int count) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (count < 0) { @@ -223,7 +223,7 @@ public static List TakeWhileF(this List source, Func predicate { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { @@ -256,7 +256,7 @@ public static List TakeWhileF(this List source, Func pred { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) { diff --git a/LinqFaster/Where.cs b/LinqFaster/Where.cs index a1102ed..afe6ad4 100644 --- a/LinqFaster/Where.cs +++ b/LinqFaster/Where.cs @@ -18,7 +18,7 @@ public static T[] WhereF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -50,7 +50,7 @@ public static T[] WhereF(this T[] source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -85,7 +85,7 @@ public static T[] WhereF(this Span source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -117,7 +117,7 @@ public static T[] WhereF(this Span source, Func predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -152,7 +152,7 @@ public static List WhereF(this List source, Predicate predicate) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -174,7 +174,7 @@ public static List WhereF(this List source, Func predicat { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) diff --git a/LinqFaster/WhereAggregate.cs b/LinqFaster/WhereAggregate.cs index b40de3a..c22a199 100644 --- a/LinqFaster/WhereAggregate.cs +++ b/LinqFaster/WhereAggregate.cs @@ -19,7 +19,7 @@ public static T WhereAggregateF(this T[] source, Func predicate, Fun { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -64,7 +64,7 @@ public static T WhereAggregateF(this T[] source, Func predicate { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -106,7 +106,7 @@ public static T WhereAggregateF(this T[] source, Func predicate { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -141,7 +141,7 @@ public static T WhereAggregateF(this T[] source, Func predicate { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -184,7 +184,7 @@ public static T WhereAggregateF(this Span source, Func predicate, { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -229,7 +229,7 @@ public static T WhereAggregateF(this Span source, Func predi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -271,7 +271,7 @@ public static T WhereAggregateF(this Span source, Func predi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -306,7 +306,7 @@ public static T WhereAggregateF(this Span source, Func predi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -351,7 +351,7 @@ public static T WhereAggregateF(this List source, Func predicate, { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -397,7 +397,7 @@ public static T WhereAggregateF(this List source, Func predi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -439,7 +439,7 @@ public static T WhereAggregateF(this List source, Func predi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) @@ -475,7 +475,7 @@ public static T WhereAggregateF(this List source, Func predi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (func == null) diff --git a/LinqFaster/WhereSelect.cs b/LinqFaster/WhereSelect.cs index 10e081f..9456a29 100644 --- a/LinqFaster/WhereSelect.cs +++ b/LinqFaster/WhereSelect.cs @@ -20,7 +20,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -59,7 +59,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -101,7 +101,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -140,7 +140,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -181,7 +181,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -214,7 +214,7 @@ public static partial class LinqFaster { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) diff --git a/LinqFaster/WhereSum.cs b/LinqFaster/WhereSum.cs deleted file mode 100644 index 91d4d2b..0000000 --- a/LinqFaster/WhereSum.cs +++ /dev/null @@ -1,881 +0,0 @@ -using System; -using System.Collections.Generic; - - -namespace JM.LinqFaster -{ - public static partial class LinqFaster - { - // -------------------------- ARRAYS -------------------------------------------- - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static int WhereSumF(this int[] source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - int sum = 0; - checked - { - foreach (int v in source) - { - if (predicate(v)) - { - sum += v; - } - } - } - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static int WhereSumF(this T[] source,Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - int sum = 0; - checked - { - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - } - return sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static long WhereSumF(this long[] source,Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - long sum = 0; - checked - { - foreach (long v in source) - { - if (predicate(v)) - { - sum += v; - } - } - } - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static long WhereSumF(this T[] source,Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - long sum = 0; - checked - { - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - } - return sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static float WhereSumF(this float[] source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - - foreach (float v in source) - { - if (predicate(v)) - { - sum += v; - } - } - - return (float)sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static float WhereSumF(this T[] source, Func predicate,Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - double sum = 0; - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - - return (float)sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static double WhereSumF(this double[] source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - foreach (double v in source) - { - if (predicate(v)) - { - sum += v; - } - } - - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static double WhereSumF(this T[] source, Func predicate,Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - double sum = 0; - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - - return sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static decimal WhereSumF(this decimal[] source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - decimal sum = 0; - - foreach (decimal v in source) - { - if (predicate(v)) - { - sum += v; - } - } - - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static decimal WhereSumF(this T[] source,Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - decimal sum = 0; - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - - return sum; - } - - // -------------------------- SPANS -------------------------------------------- - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static int WhereSumF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - int sum = 0; - checked - { - foreach (int v in source) - { - if (predicate(v)) - { - sum += v; - } - } - } - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static int WhereSumF(this Span source, Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - int sum = 0; - checked - { - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - } - return sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static long WhereSumF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - long sum = 0; - checked - { - foreach (long v in source) - { - if (predicate(v)) - { - sum += v; - } - } - } - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static long WhereSumF(this Span source, Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - long sum = 0; - checked - { - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - } - return sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static float WhereSumF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - - foreach (float v in source) - { - if (predicate(v)) - { - sum += v; - } - } - - return (float)sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static float WhereSumF(this Span source, Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - double sum = 0; - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - - return (float)sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static double WhereSumF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - foreach (double v in source) - { - if (predicate(v)) - { - sum += v; - } - } - - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static double WhereSumF(this Span source, Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - double sum = 0; - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - - return sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static decimal WhereSumF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - decimal sum = 0; - - foreach (decimal v in source) - { - if (predicate(v)) - { - sum += v; - } - } - - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static decimal WhereSumF(this Span source, Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - decimal sum = 0; - foreach (T v in source) - { - if (predicate(v)) - { - sum += selector(v); - } - } - - return sum; - } - - // -------------------------- LISTS -------------------------------------------- - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static int WhereSumF(this List source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - int sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - int s = source[i]; - if (predicate(s)) - { - sum += s; - } - } - } - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static int WhereSumF(this List source, Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - int sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - T s = source[i]; - if (predicate(s)) - { - sum += selector(s); - } - } - } - return sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static long WhereSumF(this List source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - long sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - long s = source[i]; - if (predicate(s)) - { - sum += s; - } - } - } - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static long WhereSumF(this List source, Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - long sum = 0; - checked - { - for (int i = 0; i < source.Count; i++) - { - T s = source[i]; - if (predicate(s)) - { - sum += selector(s); - } - } - } - return sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static float WhereSumF(this List source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - - for (int i = 0; i < source.Count; i++) - { - float s = source[i]; - if (predicate(s)) - { - sum += s; - } - } - - return (float)sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static float WhereSumF(this List source, Func predicate,Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - double sum = 0; - for (int i = 0; i < source.Count; i++) - { - T s = source[i]; - if (predicate(s)) - { - sum += selector(s); - } - } - - return (float)sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static double WhereSumF(this List source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - double sum = 0; - for (int i = 0; i < source.Count; i++) - { - double s = source[i]; - if (predicate(s)) - { - sum += s; - } - } - - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static double WhereSumF(this List source,Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - double sum = 0; - for (int i = 0; i < source.Count; i++) - { - T s = source[i]; - if (predicate(s)) - { - sum += selector(s); - } - } - - return sum; - } - - /// - /// Adds the values in the sequence that match the where predicate. - /// - /// The sequence to add. - /// A function to filter the sequence with before summing. - /// The sum of the sequence. - public static decimal WhereSumF(this List source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - decimal sum = 0; - - for (int i = 0; i < source.Count; i++) - { - decimal s = source[i]; - if (predicate(s)) - { - sum += s; - } - } - - return sum; - } - - /// - /// Performs a filter with the where predicate, then sums the transformed values. - /// - /// The sequence of values to transform then sum. - /// A function to filter the sequence with before summing. - /// A transformation function. - /// The sum of the transformed elements. - public static decimal WhereSumF(this List source, Func predicate,Func selector) - { - if (source == null) - { - throw Error.ArgumentNull("source"); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - decimal sum = 0; - for (int i = 0; i < source.Count; i++) - { - T s = source[i]; - if (predicate(s)) - { - sum += selector(s); - } - } - - return sum; - } - - } -} diff --git a/LinqFaster/WhereSumArray.cs b/LinqFaster/WhereSumArray.cs new file mode 100644 index 0000000..d155975 --- /dev/null +++ b/LinqFaster/WhereSumArray.cs @@ -0,0 +1,487 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Runtime.CompilerServices; +using JM.LinqFaster.Utils; + +// ReSharper disable UnusedMember.Global +// ReSharper disable LoopCanBeConvertedToQuery +// ReSharper disable ConvertToCompoundAssignment +// ReSharper disable ForCanBeConvertedToForeach + + +namespace JM.LinqFaster +{ + public static partial class LinqFaster + { + // -------------------------- ARRAYS -------------------------------------------- + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this byte[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this sbyte[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this ushort[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this short[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this uint[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this int[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong WhereSumF(this ulong[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long WhereSumF(this long[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float WhereSumF(this float[] source, Func predicate) + { + return (float)NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this float[] source, Func predicate, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + foreach (float b in source) + { + if (predicate(b)) + { + a = p.Add(a, selector(b).ToDouble(CultureInfo.InvariantCulture)); + } + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double WhereSumF(this double[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal WhereSumF(this decimal[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this T[] source, Func predicate, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + T2 a = default(T2); + checked + { + foreach (T b in source) + { + if (predicate(b)) + { + a = GenericOperators.Add(a, selector(b)); + } + } + } + + return a; + } + + #region Nullable types + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? WhereSumF(this byte?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? WhereSumF(this sbyte?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? WhereSumF(this ushort?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? WhereSumF(this short?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? WhereSumF(this uint?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? WhereSumF(this int?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong? WhereSumF(this ulong?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long? WhereSumF(this long?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float? WhereSumF(this float?[] source, Func predicate) + { + return (float)NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double? WhereSumF(this double?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal? WhereSumF(this decimal?[] source, Func predicate) + { + return NumericPolicies.Instance.WhereSumFNullable(source, predicate); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 WhereSumF(this P p, T1[] source, Func predicate) + where P : INumericPolicy + where T1 : IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + T2 a = p.Zero(); + checked + { + foreach (T1 b in source) + { + if (predicate(b)) + { + a = p.Add(a, b); + } + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T WhereSumF(this P p, T[] source, Func predicate) + where P : INumericPolicy + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + T a = p.Zero(); + checked + { + foreach (T b in source) + { + if (predicate(b)) + { + a = p.Add(a, b); + } + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 WhereSumFNullable(this P p, T1?[] source, Func predicate) + where P : INullableNumericPolicy + where T1 : struct, IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + T2 a = p.Zero(); + checked + { + foreach (T1? b in source) + { + if (predicate(b)) + { + a = p.Add(a, b); + } + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T WhereSumFNullable(this P p, T?[] source, Func predicate) + where P : INullableNumericPolicy + where T : struct + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + T a = p.Zero(); + checked + { + foreach (T? b in source) + { + if (predicate(b)) + { + a = p.Add(a, b); + } + } + } + + return a; + } + + #endregion Nullable types + + + } +} diff --git a/LinqFaster/WhereSumList.cs b/LinqFaster/WhereSumList.cs new file mode 100644 index 0000000..66fe3a8 --- /dev/null +++ b/LinqFaster/WhereSumList.cs @@ -0,0 +1,1086 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Runtime.CompilerServices; + +using JM.LinqFaster.Utils; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global + + +namespace JM.LinqFaster +{ + public static partial class LinqFaster + { + // -------------------------- Lists -------------------------------------------- + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case byte[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + uint sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case sbyte[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + int sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case ushort[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + uint sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case short[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + int sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case uint[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + uint sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case int[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + int sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case ulong[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + ulong sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case long[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + long sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case float[] sa: + return sa.WhereSumF(predicate); + case List sl: + return (float)NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + double sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return (float)sum; + } + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this List source, Func predicate, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + foreach (float b in source) + { + if (predicate(b)) + { + a = p.Add(a, selector(b).ToDouble(CultureInfo.InvariantCulture)); + } + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case double[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + double sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case decimal[] sa: + return sa.WhereSumF(predicate); + case List sl: + return NumericPolicies.Instance.WhereSumF(sl, predicate); + default: + int sourceCount = source.Count; + decimal sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i]; + } + } + return sum; + } + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this List source, Func predicate, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int sourceCount = source.Count; + T2 a = default(T2); + checked + { + for (int index = 0; index < sourceCount; index++) + { + if (predicate(source[index])) + { + a = GenericOperators.Add(a, selector(source[index])); + } + } + } + + return a; + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this IReadOnlyList source, Func predicate, Func selector) + { + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case T[] sa: + return sa.WhereSumF(predicate, selector); + case List sl: + return sl.WhereSumF(predicate, selector); + default: + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int sourceCount = source.Count; + T2 a = default(T2); + checked + { + for (int index = 0; index < sourceCount; index++) + { + if (predicate(source[index])) + { + a = GenericOperators.Add(a, selector(source[index])); + } + } + } + + return a; + } + } + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 WhereSumF(this P p, List source, Func predicate) + where P : INumericPolicy + where T1 : IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + int sourceCount = source.Count; + T2 a = p.Zero(); + checked + { + for (int index = 0; index < sourceCount; index++) + { + if (predicate(source[index])) + { + a = p.Add(a, source[index]); + } + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T WhereSumF(this P p, List source, Func predicate) + where P : INumericPolicy + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + int sourceCount = source.Count; + T a = p.Zero(); + checked + { + for (int index = 0; index < sourceCount; index++) + { + if (predicate(source[index])) + { + a = p.Add(a, source[index]); + } + } + } + + return a; + } + + #region Nullable types + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case byte?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + uint sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case sbyte?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + int sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case ushort?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + uint sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case short?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + int sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case uint?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + uint sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case int?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + int sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case ulong?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + ulong sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case long?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + long sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case float?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return (float?)NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + double sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return (float?)sum; + } + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this List source, Func predicate, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + int sourceCount = source.Count; + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + for (int index = 0; index < sourceCount; index++) + { + if (predicate(source[index])) + { + a = p.Add(a, selector(source[index]).ToDouble(CultureInfo.InvariantCulture)); + } + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case double?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + double sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal? WhereSumF(this IReadOnlyList source, Func predicate) + { + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + switch (source) + { + case null: + throw Error.ArgumentNull(nameof(source)); + case decimal?[] sa: + return WhereSumF(sa, predicate); // Do this to prevent compiler causing recursion in to this same function + case List sl: + return NumericPolicies.Instance.WhereSumFNullable(sl, predicate); + default: + int sourceCount = source.Count; + decimal sum = 0; + for (int i = 0; i < sourceCount; i++) + { + if (predicate(source[i])) + { + sum = sum + source[i] ?? 0; + } + } + return sum; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 WhereSumFNullable(this P p, List source, Func predicate) + where P : INullableNumericPolicy + where T : struct, IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + int sourceCount = source.Count; + T2 a = p.Zero(); + checked + { + for (int index = 0; index < sourceCount; index++) + { + if (predicate(source[index])) + { + a = p.Add(a, source[index]); + } + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T WhereSumFNullable(this P p, List source, Func predicate) + where P : INullableNumericPolicy + where T : struct, IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + int sourceCount = source.Count; + T a = p.Zero(); + checked + { + for (int index = 0; index < sourceCount; index++) + { + if (predicate(source[index])) + { + a = p.Add(a, source[index]); + } + } + } + + return a; + } + + #endregion Nullable Types + } +} diff --git a/LinqFaster/WhereSumSpan.cs b/LinqFaster/WhereSumSpan.cs new file mode 100644 index 0000000..39b2bf4 --- /dev/null +++ b/LinqFaster/WhereSumSpan.cs @@ -0,0 +1,569 @@ +using System; +using System.Globalization; +using System.Runtime.CompilerServices; + +using JM.LinqFaster.Utils; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable MemberCanBePrivate.Global + +namespace JM.LinqFaster +{ + public static partial class LinqFaster + { + /* + * Since Span is actually a struct and it does not inherit from IEnumerable, + * we can’t use LINQ against it. + * This is a big minus when compared to C# collections. + */ + + #region Normal Span + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float WhereSumF(this Span source, Func predicate) + { + return (float)NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this Span source, Func predicate, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + foreach (float b in source) + { + if (predicate(b)) + { + a = p.Add(a, selector(b).ToDouble(CultureInfo.InvariantCulture)); + } + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal WhereSumF(this Span source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this Span source, Func predicate, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + T2 a = default(T2); + checked + { + for (int index = 0; index < source.Length; index++) + { + if (predicate(source[index])) + { + a = GenericOperators.Add(a, selector(source[index])); + } + } + } + + return a; + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 WhereSumF(this P p, Span source, Func predicate) + where P : INumericPolicy + where T1 : IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + T2 a = p.Zero(); + checked + { + for (int index = 0; index < source.Length; index++) + { + if (predicate(source[index])) + { + a = p.Add(a, source[index]); + } + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T WhereSumF(this P p, Span source, Func predicate) + where P : INumericPolicy + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + T a = p.Zero(); + checked + { + for (int index = 0; index < source.Length; index++) + { + if (predicate(source[index])) + { + a = p.Add(a, source[index]); + } + } + } + + return a; + } + #endregion Normal Span + + #region ReadOnlySpan + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float WhereSumF(this ReadOnlySpan source, Func predicate) + { + return (float)NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + /// + /// Special case for floats, as IEnumerable does the sums on doubles before returning the type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this ReadOnlySpan source, Func predicate, Func selector) + where T2 : struct, IConvertible // Make sure these are not nullable + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + INumericPolicy p = NumericPolicies.Instance; + double a = 0; + checked + { + foreach (float b in source) + { + if (predicate(b)) + { + a = p.Add(a, selector(b).ToDouble(CultureInfo.InvariantCulture)); + } + } + } + + return (T2)Convert.ChangeType(a, typeof(T2)); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds a sequence of values. + /// + /// The sequence to add. + /// A function to filter the sequence with before summing. + /// The sum of the sequence. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal WhereSumF(this ReadOnlySpan source, Func predicate) + { + return NumericPolicies.Instance.WhereSumF(source, predicate); + } + + /// + /// Adds the transformed sequence of elements. + /// + /// The sequence of values to transform then sum. + /// A function to filter the sequence with before summing. + /// A transformation function. + /// The sum of the transformed elements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T2 WhereSumF(this ReadOnlySpan source, Func predicate, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + T2 a = default(T2); + checked + { + for (int index = 0; index < source.Length; index++) + { + if (predicate(source[index])) + { + a = GenericOperators.Add(a, selector(source[index])); + } + } + } + + return a; + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T2 WhereSumF(this P p, ReadOnlySpan source, Func predicate) + where P : INumericPolicy + where T1 : IConvertible + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + T2 a = p.Zero(); + checked + { + for (int index = 0; index < source.Length; index++) + { + if (predicate(source[index])) + { + a = p.Add(a, source[index]); + } + } + } + + return a; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T WhereSumF(this P p, ReadOnlySpan source, Func predicate) + where P : INumericPolicy + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull(nameof(predicate)); + } + + T a = p.Zero(); + checked + { + for (int index = 0; index < source.Length; index++) + { + if (predicate(source[index])) + { + a = p.Add(a, source[index]); + } + } + } + + return a; + } + #endregion ReadOnlySpan + } +} diff --git a/LinqFasterParallel/AverageParallel.cs b/LinqFasterParallel/AverageParallel.cs index 7c4915b..0cb7ed7 100644 --- a/LinqFasterParallel/AverageParallel.cs +++ b/LinqFasterParallel/AverageParallel.cs @@ -21,7 +21,7 @@ public static double AverageP(this int[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -61,7 +61,7 @@ public static double AverageP(this T[] source, Func selector, int? ba { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -104,7 +104,7 @@ public static double AverageP(this long[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -144,7 +144,7 @@ public static double AverageP(this T[] source, Func selector, int? b { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -187,7 +187,7 @@ public static float AverageP(this float[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -225,7 +225,7 @@ public static float AverageP(this T[] source, Func selector, int? b { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -267,7 +267,7 @@ public static double AverageP(this double[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -306,7 +306,7 @@ public static double AverageP(this T[] source, Func selector, int? { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -348,7 +348,7 @@ public static decimal AverageP(this decimal[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -388,7 +388,7 @@ public static decimal AverageP(this T[] source, Func selector, in { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) @@ -434,7 +434,7 @@ public static double AverageP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -474,7 +474,7 @@ public static double AverageP(this List source, Func selector, int { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -516,7 +516,7 @@ public static double AverageP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -556,7 +556,7 @@ public static double AverageP(this List source, Func selector, in { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -598,7 +598,7 @@ public static double AverageP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -636,7 +636,7 @@ public static double AverageP(this List source, Func selector, i { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -678,7 +678,7 @@ public static double AverageP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -717,7 +717,7 @@ public static double AverageP(this List source, Func selector, { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -759,7 +759,7 @@ public static decimal AverageP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) @@ -798,7 +798,7 @@ public static decimal AverageP(this List source, Func selector { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) diff --git a/LinqFasterParallel/ContainsParallel.cs b/LinqFasterParallel/ContainsParallel.cs index f9eed25..4a74af4 100644 --- a/LinqFasterParallel/ContainsParallel.cs +++ b/LinqFasterParallel/ContainsParallel.cs @@ -23,7 +23,7 @@ public static bool ContainsP(this TSource[] source, TSource value, IEqu { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (comparer == null) @@ -66,7 +66,7 @@ public static bool ContainsP(this List source, TSource value, { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (comparer == null) diff --git a/LinqFasterParallel/CountParallel.cs b/LinqFasterParallel/CountParallel.cs index 3c8275e..48fb39d 100644 --- a/LinqFasterParallel/CountParallel.cs +++ b/LinqFasterParallel/CountParallel.cs @@ -22,7 +22,7 @@ public static int CountP(this T[] source, Func predicate, int? batch { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -71,7 +71,7 @@ public static int CountP(this List source, Func predicate, int? b { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) diff --git a/LinqFasterParallel/MaxParallel.cs b/LinqFasterParallel/MaxParallel.cs index f419f97..340ff01 100644 --- a/LinqFasterParallel/MaxParallel.cs +++ b/LinqFasterParallel/MaxParallel.cs @@ -19,7 +19,7 @@ public static T MaxP(this T[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -92,7 +92,7 @@ public static T MaxP(this T[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -168,7 +168,7 @@ public static int MaxP(this int[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -216,7 +216,7 @@ public static int MaxP(this T[] source, Func selector, int? batchSize { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -264,7 +264,7 @@ public static long MaxP(this long[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -312,7 +312,7 @@ public static long MaxP(this T[] source, Func selector, int? batchSi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -360,7 +360,7 @@ public static float MaxP(this float[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -408,7 +408,7 @@ public static float MaxP(this T[] source, Func selector, int? batch { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -456,7 +456,7 @@ public static double MaxP(this double[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -504,7 +504,7 @@ public static double MaxP(this T[] source, Func selector, int? bat { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -552,7 +552,7 @@ public static decimal MaxP(this decimal[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -600,7 +600,7 @@ public static decimal MaxP(this T[] source, Func selector, int? b { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -651,7 +651,7 @@ public static T MaxP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -724,7 +724,7 @@ public static T MaxP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -800,7 +800,7 @@ public static int MaxP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -848,7 +848,7 @@ public static int MaxP(this List source, Func selector, int? batch { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -896,7 +896,7 @@ public static long MaxP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -944,7 +944,7 @@ public static long MaxP(this List source, Func selector, int? bat { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -992,7 +992,7 @@ public static float MaxP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1040,7 +1040,7 @@ public static float MaxP(this List source, Func selector, int? b { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1088,7 +1088,7 @@ public static double MaxP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1136,7 +1136,7 @@ public static double MaxP(this List source, Func selector, int? { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1184,7 +1184,7 @@ public static decimal MaxP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1232,7 +1232,7 @@ public static decimal MaxP(this List source, Func selector, in { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { diff --git a/LinqFasterParallel/MinParallel.cs b/LinqFasterParallel/MinParallel.cs index 8e45aeb..d73f126 100644 --- a/LinqFasterParallel/MinParallel.cs +++ b/LinqFasterParallel/MinParallel.cs @@ -23,7 +23,7 @@ public static T MinP(this T[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -96,7 +96,7 @@ public static T MinP(this T[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -172,7 +172,7 @@ public static int MinP(this int[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -220,7 +220,7 @@ public static int MinP(this T[] source, Func selector, int? batchSize { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -268,7 +268,7 @@ public static long MinP(this long[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -316,7 +316,7 @@ public static long MinP(this T[] source, Func selector, int? batchSi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -364,7 +364,7 @@ public static float MinP(this float[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -412,7 +412,7 @@ public static float MinP(this T[] source, Func selector, int? batch { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -460,7 +460,7 @@ public static double MinP(this double[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -508,7 +508,7 @@ public static double MinP(this T[] source, Func selector, int? bat { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -556,7 +556,7 @@ public static decimal MinP(this decimal[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -604,7 +604,7 @@ public static decimal MinP(this T[] source, Func selector, int? b { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) { @@ -655,7 +655,7 @@ public static T MinP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -728,7 +728,7 @@ public static T MinP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -804,7 +804,7 @@ public static int MinP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -852,7 +852,7 @@ public static int MinP(this List source, Func selector, int? batch { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -900,7 +900,7 @@ public static long MinP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -948,7 +948,7 @@ public static long MinP(this List source, Func selector, int? bat { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -996,7 +996,7 @@ public static float MinP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1044,7 +1044,7 @@ public static float MinP(this List source, Func selector, int? b { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1092,7 +1092,7 @@ public static double MinP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1140,7 +1140,7 @@ public static double MinP(this List source, Func selector, int? { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1188,7 +1188,7 @@ public static decimal MinP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { @@ -1236,7 +1236,7 @@ public static decimal MinP(this List source, Func selector, in { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Count == 0) { diff --git a/LinqFasterParallel/SelectParallel.cs b/LinqFasterParallel/SelectParallel.cs index a183ddb..3b62979 100644 --- a/LinqFasterParallel/SelectParallel.cs +++ b/LinqFasterParallel/SelectParallel.cs @@ -19,7 +19,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, int? { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -49,7 +49,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, i { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -79,7 +79,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, i { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -111,7 +111,7 @@ public static void SelectInPlaceP(this T[] source, Func selector, i { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -142,7 +142,7 @@ public static void SelectInPlaceP(this List source, Func selector, i { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -172,7 +172,7 @@ public static void SelectInPlaceP(this List source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -202,7 +202,7 @@ public static void SelectInPlaceP(this List source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -235,7 +235,7 @@ public static void SelectInPlaceP(this List source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -269,7 +269,7 @@ public static void SelectInPlaceP(this List source, Func select { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) diff --git a/LinqFasterParallel/SelectWhereParallel.cs b/LinqFasterParallel/SelectWhereParallel.cs index a358f47..ec638ff 100644 --- a/LinqFasterParallel/SelectWhereParallel.cs +++ b/LinqFasterParallel/SelectWhereParallel.cs @@ -20,7 +20,7 @@ public static partial class LinqFasterParallel { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -82,7 +82,7 @@ public static partial class LinqFasterParallel { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -146,7 +146,7 @@ public static partial class LinqFasterParallel { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) @@ -206,7 +206,7 @@ public static partial class LinqFasterParallel { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (predicate == null) diff --git a/LinqFasterParallel/SumParallel.cs b/LinqFasterParallel/SumParallel.cs index eb1dee0..b02748f 100644 --- a/LinqFasterParallel/SumParallel.cs +++ b/LinqFasterParallel/SumParallel.cs @@ -20,7 +20,7 @@ public static int SumP(this int[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } int sum = 0; OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); @@ -54,7 +54,7 @@ public static int SumP(this T[] source, Func selector, int? batchSize { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -92,7 +92,7 @@ public static long SumP(this long[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } long sum = 0; OrderablePartitioner> rangePartitioner = MakePartition(source.Length,batchSize); @@ -125,7 +125,7 @@ public static long SumP(this T[] source, Func selector, int? batchSi { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -163,7 +163,7 @@ public static float SumP(this float[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } double sum = 0; object LOCK = new object(); @@ -202,7 +202,7 @@ public static float SumP(this T[] source, Func selector, int? batch { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -246,7 +246,7 @@ public static double SumP(this double[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } double sum = 0; object LOCK = new object(); @@ -284,7 +284,7 @@ public static double SumP(this T[] source, Func selector, int? bat { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -327,7 +327,7 @@ public static decimal SumP(this decimal[] source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } decimal sum = 0; object LOCK = new object(); @@ -365,7 +365,7 @@ public static decimal SumP(this T[] source, Func selector, int? b { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -409,7 +409,7 @@ public static int SumP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } int sum = 0; OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); @@ -442,7 +442,7 @@ public static int SumP(this List source, Func selector, int? batch { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -480,7 +480,7 @@ public static long SumP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } long sum = 0; OrderablePartitioner> rangePartitioner = MakePartition(source.Count,batchSize); @@ -513,7 +513,7 @@ public static long SumP(this List source, Func selector, int? bat { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -551,7 +551,7 @@ public static float SumP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } double sum = 0; object LOCK = new object(); @@ -582,7 +582,7 @@ public static float SumP(this List source, Func selector, int? b { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -619,7 +619,7 @@ public static double SumP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } double sum = 0; object LOCK = new object(); @@ -650,7 +650,7 @@ public static double SumP(this List source, Func selector, int? { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) @@ -689,7 +689,7 @@ public static decimal SumP(this List source, int? batchSize = null) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } decimal sum = 0; @@ -724,7 +724,7 @@ public static decimal SumP(this List source, Func selector, in { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selector == null) diff --git a/LinqFasterParallel/WhereAggregateParallel.cs b/LinqFasterParallel/WhereAggregateParallel.cs index 20946f0..4deff07 100644 --- a/LinqFasterParallel/WhereAggregateParallel.cs +++ b/LinqFasterParallel/WhereAggregateParallel.cs @@ -20,7 +20,7 @@ public static TSource WhereAggregateP(this TSource[] source, Func(this TSource[] source, Func(this TSource[] source, Func(this TSource[] source, Func(this List source, Func(this List source, Func(this List source, Func(this List source, Func(this TSource[] source, Func(this TSource[] source, Func WhereP(this List source, Func WhereP(this List source, Func.Count; diff --git a/LinqFasterParallelSIMD/SumSIMDParallel.cs b/LinqFasterParallelSIMD/SumSIMDParallel.cs index c3f8888..b9d8b6f 100644 --- a/LinqFasterParallelSIMD/SumSIMDParallel.cs +++ b/LinqFasterParallelSIMD/SumSIMDParallel.cs @@ -20,7 +20,7 @@ public static partial class LinqFasterSIMDParallel { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } int count = Vector.Count; diff --git a/LinqFasterSIMD/ContainsSIMD.cs b/LinqFasterSIMD/ContainsSIMD.cs index 8cde1cc..f72dda6 100644 --- a/LinqFasterSIMD/ContainsSIMD.cs +++ b/LinqFasterSIMD/ContainsSIMD.cs @@ -19,7 +19,7 @@ public static bool ContainsS(this T[] source, T value) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } int count = Vector.Count; diff --git a/LinqFasterSIMD/MaxSIMD.cs b/LinqFasterSIMD/MaxSIMD.cs index 159ef41..5da13d6 100644 --- a/LinqFasterSIMD/MaxSIMD.cs +++ b/LinqFasterSIMD/MaxSIMD.cs @@ -16,7 +16,7 @@ public static T MaxS (this T[] source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) diff --git a/LinqFasterSIMD/MinSIMD.cs b/LinqFasterSIMD/MinSIMD.cs index 8f8181d..2325ffa 100644 --- a/LinqFasterSIMD/MinSIMD.cs +++ b/LinqFasterSIMD/MinSIMD.cs @@ -17,7 +17,7 @@ public static T MinS (this T[] source) { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (source.Length == 0) diff --git a/LinqFasterSIMD/SelectSIMD.cs b/LinqFasterSIMD/SelectSIMD.cs index f908cca..de58f08 100644 --- a/LinqFasterSIMD/SelectSIMD.cs +++ b/LinqFasterSIMD/SelectSIMD.cs @@ -20,7 +20,7 @@ public static partial class LinqFasterSIMD { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (slectorSIMD == null) { @@ -64,7 +64,7 @@ public static void SelectInPlaceS(this T[] source, Func, Vector> { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (slectorSIMD == null) { diff --git a/LinqFasterSIMD/SumSIMD.cs b/LinqFasterSIMD/SumSIMD.cs index 5591858..366d311 100644 --- a/LinqFasterSIMD/SumSIMD.cs +++ b/LinqFasterSIMD/SumSIMD.cs @@ -18,7 +18,7 @@ public static partial class LinqFasterSIMD { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } Vector state = Vector.Zero; @@ -58,7 +58,7 @@ public static partial class LinqFasterSIMD { if (source == null) { - throw Error.ArgumentNull("source"); + throw Error.ArgumentNull(nameof(source)); } if (selectorSIMD == null) { diff --git a/Tests/AverageTests.cs b/Tests/AverageTests.cs index 9e6d49e..2cb7f4c 100644 --- a/Tests/AverageTests.cs +++ b/Tests/AverageTests.cs @@ -1,22 +1,25 @@ -using NUnit.Framework; -using JM.LinqFaster; +using System; using System.Linq; -using System; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class AverageTests + internal class AverageTests { - + [Test] public void AverageArrayInt() { double a = intArray.AverageF(); double b = intArray.Average(); - Assert.That(a, Is.EqualTo(b)); + Assert.That(a, Is.EqualTo(b)); } [Test] @@ -70,7 +73,8 @@ public void AverageArrayString() [Test] - public void AverageListInt() { + public void AverageListInt() + { double a = intList.AverageF(); double b = intList.Average(); @@ -78,7 +82,8 @@ public void AverageArrayString() } [Test] - public void AverageListLong() { + public void AverageListLong() + { double a = Test.longList.AverageF(); double b = Test.longList.Average(); @@ -86,7 +91,8 @@ public void AverageArrayString() } [Test] - public void AverageListFloat() { + public void AverageListFloat() + { float a = floatList.AverageF(); float b = floatList.Average(); @@ -94,7 +100,8 @@ public void AverageArrayString() } [Test] - public void AverageListDouble() { + public void AverageListDouble() + { double a = Test.doubleList.AverageF(); double b = Test.doubleList.Average(); @@ -102,7 +109,8 @@ public void AverageArrayString() } [Test] - public void AverageListDecimal() { + public void AverageListDecimal() + { decimal a = decimalList.AverageF(); decimal b = decimalList.Average(); @@ -110,7 +118,8 @@ public void AverageArrayString() } [Test] - public void AverageListString() { + public void AverageListString() + { Func lambda = (x => int.Parse(x)); float a = stringList.AverageF(lambda); float b = stringList.Average(lambda); diff --git a/Tests/SumTests.cs b/Tests/SumTests.cs index b0b4542..05b10df 100644 --- a/Tests/SumTests.cs +++ b/Tests/SumTests.cs @@ -13,6 +13,37 @@ namespace Tests [TestFixture] internal class SumTests { + [Test] + public void NonOverflowOfComputableSumSingle() + { + float[] source = { float.MaxValue, float.MaxValue, + -float.MaxValue, -float.MaxValue }; + // In a world where we summed using a float accumulator, the + // result would be infinity. + Assert.AreEqual(0f, source.Sum()); + } + + [Test] + public void AccumulatorAccuracyForSingle() + { + // 20000000 and 20000004 are both exactly representable as + // float values, but 20000001 is not. Therefore if we use + // a float accumulator, we’ll end up with 20000000. However, + // if we use a double accumulator, we’ll get the right value. + float[] array = { 20000000f, 1f, 1f, 1f, 1f }; + Assert.AreEqual(20000004f, array.SumF()); + } + + [Test] + public void OverflowOfComputableSumInt32() + { + int[] source = { int.MaxValue, 1, -1, -int.MaxValue }; + // In a world where we summed using a long accumulator, the + // result would be 0. + Assert.Throws(() => source.Sum()); + Assert.DoesNotThrow(() => source.SumF()); + } + [Test] public void SumArray() { diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 2fc9b24..4ad1165 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -3309,255 +3309,633 @@ A function to transform the filtered elements. A sequence of filtered and transformed elements. - + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. - - The sequence of values to transform then sum. + Adds a sequence of values. + + The sequence to add. A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. + The sum of the sequence. - + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. - - The sequence of values to transform then sum. + Adds a sequence of values. + + The sequence to add. A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. + Adds the transformed sequence of elements. The sequence of values to transform then sum. A function to filter the sequence with before summing. - A transformation function. + A transformation function. The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. + Adds the transformed sequence of elements. The sequence of values to transform then sum. A function to filter the sequence with before summing. A transformation function. The sum of the transformed elements. - + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds the transformed sequence of elements. The sequence of values to transform then sum. A function to filter the sequence with before summing. A transformation function. The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + - + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. + Adds the transformed sequence of elements. The sequence of values to transform then sum. A function to filter the sequence with before summing. A transformation function. The sum of the transformed elements. - + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A function to filter the sequence with before summing. + A transformation function. + The sum of the transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds the transformed sequence of elements. The sequence of values to transform then sum. A function to filter the sequence with before summing. A transformation function. The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + - + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. - - The sequence of values to transform then sum. + Adds a sequence of values. + + The sequence to add. A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. + The sum of the sequence. - + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds the transformed sequence of elements. The sequence of values to transform then sum. A function to filter the sequence with before summing. A transformation function. The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. + Adds the transformed sequence of elements. The sequence of values to transform then sum. A function to filter the sequence with before summing. A transformation function. The sum of the transformed elements. - + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. - - The sequence of values to transform then sum. + Adds a sequence of values. + + The sequence to add. A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. + The sum of the sequence. - + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. - - The sequence of values to transform then sum. + Adds a sequence of values. + + The sequence to add. A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. + The sum of the sequence. - + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. - - The sequence of values to transform then sum. + Adds a sequence of values. + + The sequence to add. A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. + The sum of the sequence. - + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds the transformed sequence of elements. The sequence of values to transform then sum. A function to filter the sequence with before summing. A transformation function. The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + - + - Adds the values in the sequence that match the where predicate. + Adds a sequence of values. The sequence to add. A function to filter the sequence with before summing. The sum of the sequence. - + - Performs a filter with the where predicate, then sums the transformed values. + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds the transformed sequence of elements. The sequence of values to transform then sum. A function to filter the sequence with before summing. From ce954e296dc163f898e3a3ef0484909ef174214a Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Tue, 6 Aug 2019 15:26:28 +0100 Subject: [PATCH 20/30] - Note: Lists can have items added and removed whilst these API's are in use - The IReadOnlyList represents a list in which the _number_ and _order_ of list elements is read-only. --- LinqFaster/Aggregate.cs | 12 +++--- LinqFaster/First.cs | 36 ++++++++---------- LinqFaster/MaxList.cs | 75 +++++++++++++++++-------------------- LinqFaster/MinList.cs | 76 +++++++++++++++++--------------------- LinqFaster/SumList.cs | 24 ++++++------ LinqFaster/WhereSumList.cs | 24 ++++++------ 6 files changed, 110 insertions(+), 137 deletions(-) diff --git a/LinqFaster/Aggregate.cs b/LinqFaster/Aggregate.cs index 0f016ad..56360d4 100644 --- a/LinqFaster/Aggregate.cs +++ b/LinqFaster/Aggregate.cs @@ -13,6 +13,9 @@ namespace JM.LinqFaster /// public static partial class LinqFaster { + // Note: Lists can have items added and removed whilst these API's are in use + // The IReadOnlyList represents a list in which the _number_ and _order_ of list elements is read-only. + // /// /// Applies an accumulator function over an array[T] / List{T} / or IReadOnlyList{T}. @@ -55,8 +58,7 @@ public static partial class LinqFaster } break; default: - int sourceCount = source.Count; - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { result = func(result, source[i]); } @@ -104,8 +106,7 @@ public static partial class LinqFaster } break; default: - int sourceCount = source.Count; - for (int i = 0; i < sourceCount; i++) + for (int i = 0; i < source.Count; i++) { result = func(result, source[i]); } @@ -161,8 +162,7 @@ public static partial class LinqFaster } break; default: - int sourceCount = source.Count; - for (int i = 0; i < sourceCount; i++) + for (int i = 0; i < source.Count; i++) { result = func(result, source[i]); } diff --git a/LinqFaster/First.cs b/LinqFaster/First.cs index 95383b2..14ccc0e 100644 --- a/LinqFaster/First.cs +++ b/LinqFaster/First.cs @@ -9,7 +9,9 @@ namespace JM.LinqFaster { public static partial class LinqFaster { - // -------------------------- Arrays -------------------------------------------- + // Note: Lists can have items added and removed whilst these API's are in use + // The IReadOnlyList represents a list in which the _number_ and _order_ of list elements is read-only. + // /// /// Returns the first element of an array. @@ -152,18 +154,15 @@ public static T FirstF(this IReadOnlyList source, Func func) case T[] sa: return sa.FirstF(func); default: + for (int i = 0; i < source.Count; i++) { - int sourceCount = source.Count; - for (int i = 0; i < sourceCount; i++) + if (func(source[i])) { - if (func(source[i])) - { - return source[i]; - } + return source[i]; } - - break; } + + break; } throw Error.NoMatch(); @@ -213,18 +212,15 @@ public static T FirstOrDefaultF(this IReadOnlyList source, Func f case T[] sa: return sa.FirstOrDefaultF(func); default: + for (int i = 0; i < source.Count; i++) { - int sourceCount = source.Count; - for (int i = 0; i < sourceCount; i++) + if (func(source[i])) { - if (func(source[i])) - { - return source[i]; - } + return source[i]; } - - break; } + + break; } return default(T); @@ -270,8 +266,7 @@ public static T FirstF(this List source, Predicate predicate) throw Error.ArgumentNull(nameof(predicate)); } - int sourceCount = source.Count; - for (int i = 0; i < sourceCount; i++) + for (int i = 0; i < source.Count; i++) { if (predicate(source[i])) { @@ -323,8 +318,7 @@ public static T FirstOrDefaultF(this List source, Predicate predicate) throw Error.ArgumentNull(nameof(predicate)); } - int sourceCount = source.Count; - for (int i = 0; i < sourceCount; i++) + for (int i = 0; i < source.Count; i++) { if (predicate(source[i])) { diff --git a/LinqFaster/MaxList.cs b/LinqFaster/MaxList.cs index 668d3b3..f224040 100644 --- a/LinqFaster/MaxList.cs +++ b/LinqFaster/MaxList.cs @@ -18,6 +18,9 @@ public static partial class LinqFaster // means another generic instantiation, which can be costly esp. // for value types. + // Note: Lists can have items added and removed whilst these API's are in use + // The IReadOnlyList represents a list in which the _number_ and _order_ of list elements is read-only. + // // -------------------------- LISTS -------------------------------------------- /// @@ -34,8 +37,7 @@ public static T MaxF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -43,7 +45,7 @@ public static T MaxF(this List source) T r = source[0]; if (default(T) == null) { - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { T item = source[i]; if (item != null @@ -53,7 +55,7 @@ public static T MaxF(this List source) } else { - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { T item = source[i]; if (item.CompareTo(r) > 0) @@ -83,8 +85,7 @@ public static T MaxF(this List source) throw Error.ArgumentNull(nameof(selector)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -92,7 +93,7 @@ public static T MaxF(this List source) TResult r = selector(source[0]); if (default(TResult) == null) { - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { TResult item = selector(source[i]); if (item != null @@ -104,7 +105,7 @@ public static T MaxF(this List source) } else { - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { TResult item = selector(source[i]); if (item.CompareTo(r) > 0) @@ -128,13 +129,12 @@ public static int MaxF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } int r = source[0]; - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { if (source[i] > r) r = source[i]; } @@ -155,8 +155,7 @@ public static int MaxF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -166,7 +165,7 @@ public static int MaxF(this List source, Func selector) } int r = selector(source[0]); - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { int v = selector(source[i]); if (v > r) @@ -188,13 +187,12 @@ public static long MaxF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } long r = source[0]; - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { if (source[i] > r) r = source[i]; @@ -216,8 +214,7 @@ public static long MaxF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -226,7 +223,7 @@ public static long MaxF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } long r = selector(source[0]); - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { long v = selector(source[i]); if (v > r) @@ -248,20 +245,19 @@ public static float MaxF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } float r = source[0]; int startIndex = 0; - for (; startIndex < sourceCount; startIndex++) + for (; startIndex < source.Count; startIndex++) { if (float.IsNaN(source[startIndex])) continue; r = source[startIndex]; break; } - for (int i = startIndex; i < sourceCount; i++) + for (int i = startIndex; i < source.Count; i++) { if (source[i] > r) r = source[i]; @@ -283,8 +279,7 @@ public static float MaxF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -294,14 +289,14 @@ public static float MaxF(this List source, Func selector) } float r = selector(source[0]); int startIndex = 0; - for (; startIndex < sourceCount; startIndex++) + for (; startIndex < source.Count; startIndex++) { float v = selector(source[startIndex]); if (float.IsNaN(v)) continue; r = v; break; } - for (int i = startIndex; i < sourceCount; i++) + for (int i = startIndex; i < source.Count; i++) { float v = selector(source[i]); if (v > r) @@ -323,20 +318,19 @@ public static double MaxF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } double r = source[0]; int startIndex = 0; - for (; startIndex < sourceCount; startIndex++) + for (; startIndex < source.Count; startIndex++) { if (double.IsNaN(source[startIndex])) continue; r = source[startIndex]; break; } - for (int i = startIndex; i < sourceCount; i++) + for (int i = startIndex; i < source.Count; i++) { if (source[i] > r) r = source[i]; @@ -358,8 +352,7 @@ public static double MaxF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -369,14 +362,14 @@ public static double MaxF(this List source, Func selector) } double r = selector(source[0]); int startIndex = 0; - for (; startIndex < sourceCount; startIndex++) + for (; startIndex < source.Count; startIndex++) { double v = selector(source[startIndex]); if (double.IsNaN(v)) continue; r = v; break; } - for (int i = startIndex; i < sourceCount; i++) + for (int i = startIndex; i < source.Count; i++) { double v = selector(source[i]); if (v > r) @@ -398,13 +391,12 @@ public static decimal MaxF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } decimal r = source[0]; - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { if (source[i] > r) r = source[i]; @@ -426,13 +418,12 @@ public static decimal MaxF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } decimal r = selector(source[0]); - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { decimal v = selector(source[i]); if (v > r) r = v; diff --git a/LinqFaster/MinList.cs b/LinqFaster/MinList.cs index 85649b6..054e817 100644 --- a/LinqFaster/MinList.cs +++ b/LinqFaster/MinList.cs @@ -18,6 +18,10 @@ public static partial class LinqFaster // means another generic instantiation, which can be costly esp. // for value types. + // Note: Lists can have items added and removed whilst these API's are in use + // The IReadOnlyList represents a list in which the _number_ and _order_ of list elements is read-only. + // + // -------------------------- LISTS -------------------------------------------- /// @@ -34,8 +38,7 @@ public static T MinF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -43,7 +46,7 @@ public static T MinF(this List source) T r = source[0]; if (default(T) == null) { - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { T item = source[i]; if (item != null @@ -53,7 +56,7 @@ public static T MinF(this List source) } else { - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { T item = source[i]; if (item.CompareTo(r) < 0) @@ -83,8 +86,7 @@ public static T MinF(this List source) throw Error.ArgumentNull(nameof(selector)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -92,7 +94,7 @@ public static T MinF(this List source) TResult r = selector(source[0]); if (default(TResult) == null) { - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { TResult item = selector(source[i]); if (item != null @@ -104,7 +106,7 @@ public static T MinF(this List source) } else { - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { TResult item = selector(source[i]); if (item.CompareTo(r) < 0) @@ -128,13 +130,12 @@ public static int MinF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } int r = source[0]; - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { if (source[i] < r) r = source[i]; @@ -156,8 +157,7 @@ public static int MinF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -167,7 +167,7 @@ public static int MinF(this List source, Func selector) } int r = selector(source[0]); - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { int v = selector(source[i]); if (v < r) @@ -189,13 +189,12 @@ public static long MinF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } long r = source[0]; - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { if (source[i] < r) r = source[i]; @@ -217,8 +216,7 @@ public static long MinF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -227,7 +225,7 @@ public static long MinF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } long r = selector(source[0]); - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { long v = selector(source[i]); if (v < r) @@ -249,20 +247,19 @@ public static float MinF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } float r = source[0]; int startIndex = 0; - for (; startIndex < sourceCount; startIndex++) + for (; startIndex < source.Count; startIndex++) { if (float.IsNaN(source[startIndex])) continue; r = source[startIndex]; break; } - for (int i = startIndex; i < sourceCount; i++) + for (int i = startIndex; i < source.Count; i++) { if (source[i] < r) r = source[i]; @@ -284,8 +281,7 @@ public static float MinF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -295,14 +291,14 @@ public static float MinF(this List source, Func selector) } float r = selector(source[0]); int startIndex = 0; - for (; startIndex < sourceCount; startIndex++) + for (; startIndex < source.Count; startIndex++) { float v = selector(source[startIndex]); if (float.IsNaN(v)) continue; r = v; break; } - for (int i = startIndex; i < sourceCount; i++) + for (int i = startIndex; i < source.Count; i++) { float v = selector(source[i]); if (v < r) @@ -324,20 +320,19 @@ public static double MinF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } double r = source[0]; int startIndex = 0; - for (; startIndex < sourceCount; startIndex++) + for (; startIndex < source.Count; startIndex++) { if (double.IsNaN(source[startIndex])) continue; r = source[startIndex]; break; } - for (int i = startIndex; i < sourceCount; i++) + for (int i = startIndex; i < source.Count; i++) { if (source[i] < r) r = source[i]; @@ -359,8 +354,7 @@ public static double MinF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } @@ -370,14 +364,14 @@ public static double MinF(this List source, Func selector) } double r = selector(source[0]); int startIndex = 0; - for (; startIndex < sourceCount; startIndex++) + for (; startIndex < source.Count; startIndex++) { double v = selector(source[startIndex]); if (double.IsNaN(v)) continue; r = v; break; } - for (int i = startIndex; i < sourceCount; i++) + for (int i = startIndex; i < source.Count; i++) { double v = selector(source[i]); if (v < r) @@ -399,13 +393,12 @@ public static decimal MinF(this List source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } decimal r = source[0]; - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { if (source[i] < r) r = source[i]; @@ -427,13 +420,12 @@ public static decimal MinF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; - if (sourceCount == 0) + if (source.Count == 0) { throw Error.NoElements(); } decimal r = selector(source[0]); - for (int i = 1; i < sourceCount; i++) + for (int i = 1; i < source.Count; i++) { decimal v = selector(source[i]); if (v < r) diff --git a/LinqFaster/SumList.cs b/LinqFaster/SumList.cs index 8b365ef..c374d74 100644 --- a/LinqFaster/SumList.cs +++ b/LinqFaster/SumList.cs @@ -6,13 +6,17 @@ using JM.LinqFaster.Utils; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable LoopCanBeConvertedToQuery namespace JM.LinqFaster { public static partial class LinqFaster { - // -------------------------- Lists -------------------------------------------- + // Note: Lists can have items added and removed whilst these API's are in use + // The IReadOnlyList represents a list in which the _number_ and _order_ of list elements is read-only. + // /// /// Adds a sequence of values. @@ -366,11 +370,10 @@ public static decimal SumF(this IReadOnlyList source) throw Error.ArgumentNull(nameof(selector)); } - int sourceCount = source.Count; T2 a = default(T2); checked { - for (int index = 0; index < sourceCount; index++) + for (int index = 0; index < source.Count; index++) { a = GenericOperators.Add(a, selector(source[index])); } @@ -429,11 +432,10 @@ public static decimal SumF(this IReadOnlyList source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; T2 a = p.Zero(); checked { - for (int index = 0; index < sourceCount; index++) + for (int index = 0; index < source.Count; index++) { a = p.Add(a, source[index]); } @@ -451,11 +453,10 @@ public static decimal SumF(this IReadOnlyList source) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; T a = p.Zero(); checked { - for (int index = 0; index < sourceCount; index++) + for (int index = 0; index < source.Count; index++) { a = p.Add(a, source[index]); } @@ -731,12 +732,11 @@ public static T2 SumF(this List source, Func selector) throw Error.ArgumentNull(nameof(selector)); } - int sourceCount = source.Count; INumericPolicy p = NumericPolicies.Instance; double a = 0; checked { - for (int index = 0; index < sourceCount; index++) + for (int index = 0; index < source.Count; index++) { a = p.Add(a, selector(source[index]).ToDouble(CultureInfo.InvariantCulture)); } @@ -809,11 +809,10 @@ public static T2 SumF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; T2 a = p.Zero(); checked { - for (int index = 0; index < sourceCount; index++) + for (int index = 0; index < source.Count; index++) { a = p.Add(a, source[index]); } @@ -832,11 +831,10 @@ public static T2 SumF(this List source, Func selector) throw Error.ArgumentNull(nameof(source)); } - int sourceCount = source.Count; T a = p.Zero(); checked { - for (int index = 0; index < sourceCount; index++) + for (int index = 0; index < source.Count; index++) { a = p.Add(a, source[index]); } diff --git a/LinqFaster/WhereSumList.cs b/LinqFaster/WhereSumList.cs index 66fe3a8..af8733a 100644 --- a/LinqFaster/WhereSumList.cs +++ b/LinqFaster/WhereSumList.cs @@ -6,13 +6,17 @@ using JM.LinqFaster.Utils; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global +// ReSharper disable LoopCanBeConvertedToQuery +// ReSharper disable ForCanBeConvertedToForeach namespace JM.LinqFaster { public static partial class LinqFaster { - // -------------------------- Lists -------------------------------------------- + // Note: Lists can have items added and removed whilst these API's are in use + // The IReadOnlyList represents a list in which the _number_ and _order_ of list elements is read-only. + // /// /// Adds a sequence of values. @@ -467,11 +471,10 @@ public static decimal WhereSumF(this IReadOnlyList source, Func source, Func source, Func(this List source, Func pred throw Error.ArgumentNull(nameof(selector)); } - int sourceCount = source.Count; INumericPolicy p = NumericPolicies.Instance; double a = 0; checked { - for (int index = 0; index < sourceCount; index++) + for (int index = 0; index < source.Count; index++) { if (predicate(source[index])) { @@ -1035,11 +1035,10 @@ public static T2 WhereSumF(this List source, Func pred throw Error.ArgumentNull(nameof(predicate)); } - int sourceCount = source.Count; T2 a = p.Zero(); checked { - for (int index = 0; index < sourceCount; index++) + for (int index = 0; index < source.Count; index++) { if (predicate(source[index])) { @@ -1065,11 +1064,10 @@ public static T2 WhereSumF(this List source, Func pred throw Error.ArgumentNull(nameof(predicate)); } - int sourceCount = source.Count; T a = p.Zero(); checked { - for (int index = 0; index < sourceCount; index++) + for (int index = 0; index < source.Count; index++) { if (predicate(source[index])) { From 3bafae3276e162ee158fc7ad6b6601c535071b3b Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Wed, 7 Aug 2019 14:39:49 +0100 Subject: [PATCH 21/30] Invesigate #25: [Enhancement] Please also target .net4.8 and Benchmark - Add Ratio Comparisons to Benchmarks - Add .Net4.8 Output directories - Explicit call types for Average --- Benchmarks/BenchmarkAggregate.cs | 159 +++--- Benchmarks/BenchmarkAverage.cs | 73 +-- Benchmarks/BenchmarkFirst.cs | 162 +++--- Benchmarks/BenchmarkLast.cs | 163 +++--- Benchmarks/BenchmarkOrderBy.cs | 23 +- Benchmarks/BenchmarkSelect.cs | 35 ++ Benchmarks/BenchmarkSequenceEqual.cs | 48 ++ Benchmarks/BenchmarkSum.cs | 511 +++++++++--------- Benchmarks/BenchmarkWhereSum.cs | 209 ++++--- Benchmarks/Benchmarks.cs | 162 ++---- Benchmarks/Benchmarks.csproj | 20 +- Benchmarks/BenchmarksMax.cs | 308 +++++------ Benchmarks/BenchmarksMin.cs | 318 +++++------ Benchmarks/BenchmarksRepeat.cs | 38 ++ Benchmarks/BenchmarksWhereAggregate.cs | 29 + Benchmarks/Config.cs | 26 + LinqFaster/AverageIList.cs | 38 +- LinqFaster/LinqFaster.csproj | 8 +- LinqFasterParallel/LinqFasterParallel.csproj | 4 +- .../LinqFasterParallelSIMD.csproj | 8 +- LinqFasterSIMD/LinqFasterSIMD.csproj | 6 +- Tests/ParallelSIMDTests/SelectSIMDP.cs | 22 +- Tests/SIMDTests/AverageSIMDTests.cs | 10 +- Tests/SIMDTests/SelectSIMDTests.cs | 12 +- Tests/SIMDTests/SumSIMDTests.cs | 10 +- 25 files changed, 1243 insertions(+), 1159 deletions(-) create mode 100644 Benchmarks/BenchmarkSelect.cs create mode 100644 Benchmarks/BenchmarkSequenceEqual.cs create mode 100644 Benchmarks/BenchmarksRepeat.cs create mode 100644 Benchmarks/BenchmarksWhereAggregate.cs create mode 100644 Benchmarks/Config.cs diff --git a/Benchmarks/BenchmarkAggregate.cs b/Benchmarks/BenchmarkAggregate.cs index 2c40a09..2a2f935 100644 --- a/Benchmarks/BenchmarkAggregate.cs +++ b/Benchmarks/BenchmarkAggregate.cs @@ -2,92 +2,93 @@ using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; namespace Tests { - public partial class Benchmarks + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksAggregate { private static readonly Func mulXInts = (acc, x) => acc += x * x; - //[Benchmark] - //public double IntArrayAggregateLinq() - //{ - // return intArray.Aggregate(0.0D, mulXInts); - //} - - //[Benchmark] - //public double IntArrayAggregateFast() - //{ - // return intArray.AggregateF(0.0D, mulXInts); - //} - - //[Benchmark] - //public double IntReadOnlyArrayAggregateLinq() - //{ - // return Array.AsReadOnly(intArray).Aggregate(0.0D, mulXInts); - //} - - //[Benchmark] - //public double IntReadOnlyArrayAggregateFast() - //{ - // return Array.AsReadOnly(intArray).AggregateF(0.0D, mulXInts); - //} - - //[Benchmark] - //public double IntSpanAggregateForEach() - //{ - // //return intArray.AsSpan().Aggregate(0.0, mulXInts); - // double result = 0.0D; - // foreach (var v in intArray.AsSpan()) - // { - // result = mulXInts(result, v); - // } - // return result; - - //} - - //[Benchmark] - //public double IntSpanAggregateFast() - //{ - // return intArray.AsSpan().AggregateF(0.0, mulXInts); - //} - - //[Benchmark] - //public double IntArrayAggregateLinqSelector() - //{ - // return intArray.Aggregate(0.0, mulXInts, acc => acc / intArray.Length); - //} - - //[Benchmark] - //public double IntArrayAggregateFastSelector() - //{ - // return intArray.AggregateF(0.0, mulXInts, acc => acc / intArray.Length); - //} - - //[Benchmark] - //public double IntListAggregateLinq() - //{ - // return intList.Aggregate(0.0, mulXInts); - //} - - //[Benchmark] - //public double IntListAggregateFast() - //{ - // return intList.AggregateF(0.0, mulXInts); - //} - - //[Benchmark] - //public double IntReadOnlyListAggregateLinq() - //{ - // return intList.AsReadOnly().Aggregate(0.0, mulXInts); - //} - - //[Benchmark] - //public double IntReadOnlyListAggregateFast() - //{ - // return intList.AsReadOnly().AggregateF(0.0, mulXInts); - //} + [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + public double IntArrayAggregateLinq() + { + return Benchmarks.intArray.Aggregate(0.0D, mulXInts); + } + + [BenchmarkCategory("IntArrayAggregate"), Benchmark] + public double IntArrayAggregateFast() + { + return Benchmarks.intArray.AggregateF(0.0D, mulXInts); + } + + [BenchmarkCategory("IntReadOnlyArrayAggregate"), Benchmark(Baseline = true)] + public double IntReadOnlyArrayAggregateLinq() + { + return Array.AsReadOnly(Benchmarks.intArray).Aggregate(0.0D, mulXInts); + } + + [BenchmarkCategory("IntReadOnlyArrayAggregate"), Benchmark] + public double IntReadOnlyArrayAggregateFast() + { + return Array.AsReadOnly(Benchmarks.intArray).AggregateF(0.0D, mulXInts); + } + + [BenchmarkCategory("IntSpanAggregate"), Benchmark(Baseline = true)] + public double IntSpanAggregateForEach() + { + //return intArray.AsSpan().Aggregate(0.0, mulXInts); + double result = 0.0D; + foreach (var v in Benchmarks.intArray.AsSpan()) + { + result = mulXInts(result, v); + } + return result; + } + + [BenchmarkCategory("IntSpanAggregate"), Benchmark] + public double IntSpanAggregateFast() + { + return Benchmarks.intArray.AsSpan().AggregateF(0.0, mulXInts); + } + + [BenchmarkCategory("intList.Aggregate.Select"), Benchmark(Baseline = true)] + public double IntArrayAggregateLinqSelector() + { + return Benchmarks.intArray.Aggregate(0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); + } + + [BenchmarkCategory("intList.Aggregate.Select"), Benchmark] + public double IntArrayAggregateFastSelector() + { + return Benchmarks.intArray.AggregateF(0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); + } + + [BenchmarkCategory("intList.Aggregate"), Benchmark(Baseline = true)] + public double IntListAggregateLinq() + { + return Benchmarks.intList.Aggregate(0.0, mulXInts); + } + + [BenchmarkCategory("intList.Aggregate"), Benchmark] + public double IntListAggregateFast() + { + return Benchmarks.intList.AggregateF(0.0, mulXInts); + } + + [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + public double IntReadOnlyListAggregateLinq() + { + return Benchmarks.intList.AsReadOnly().Aggregate(0.0, mulXInts); + } + + [BenchmarkCategory("intList.AsReadOnly"), Benchmark] + public double IntReadOnlyListAggregateFast() + { + return Benchmarks.intList.AsReadOnly().AggregateF(0.0, mulXInts); + } } } diff --git a/Benchmarks/BenchmarkAverage.cs b/Benchmarks/BenchmarkAverage.cs index 376f69b..45b9b56 100644 --- a/Benchmarks/BenchmarkAverage.cs +++ b/Benchmarks/BenchmarkAverage.cs @@ -1,49 +1,52 @@ -using System; -using System.Linq; +using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; +using JM.LinqFaster.SIMD; namespace Tests { - public partial class Benchmarks + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksAverage { - //[Benchmark] - //public double IntArrayAverageLinq() - //{ - // return intArray.Average(); - //} - - //[Benchmark] - //public double IntArrayAverageFast() - //{ - // return intArray.AverageF(); - //} - - //[Benchmark] - //public double IntArrayAverageFastSIMD() - //{ - // return intArray.AverageS(); - //} - - - //[Benchmark] - //public double IntListAverageLinq() - //{ - // return intList.Average(); - //} - - //[Benchmark] - //public double IntListAverageFast() - //{ - // return intList.AverageF(); - //} - //[Benchmark] + [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + public double IntArrayAverageLinq() + { + return Benchmarks.intArray.Average(); + } + + [BenchmarkCategory("intArray"), Benchmark] + public double IntArrayAverageFast() + { + return Benchmarks.intArray.AverageF(); + } + + [BenchmarkCategory("intArray"), Benchmark] + public double IntArrayAverageFastSIMD() + { + return Benchmarks.intArray.AverageS(); + } + + + [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + public double IntListAverageLinq() + { + return Benchmarks.intList.Average(); + } + + [BenchmarkCategory("intList"), Benchmark] + public double IntListAverageFast() + { + return Benchmarks.intList.AverageF(); + } + + //[BenchmarkCategory("intList"), Benchmark] //public double IntListAverageFastSIMD() //{ - // return intList.AverageS(); + // return Benchmarks.intList.AverageS(); //} } diff --git a/Benchmarks/BenchmarkFirst.cs b/Benchmarks/BenchmarkFirst.cs index 556dbc7..fc7cbe4 100644 --- a/Benchmarks/BenchmarkFirst.cs +++ b/Benchmarks/BenchmarkFirst.cs @@ -2,94 +2,96 @@ using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; namespace Tests { - public partial class Benchmarks + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksFirst { private static readonly Func firstInts = (x) => x > 0; - //[Benchmark] - //public double IntArrayFirstLinqSelector() - //{ - // return intArray.First(firstInts); - //} - - //[Benchmark] - //public double IntArrayFirstFastSelector() - //{ - // return intArray.FirstF(firstInts); - //} - - //[Benchmark] - //public double IntArrayFirstArrayFindSelector() - //{ - // Predicate predicate = new Predicate(firstInts); - // return Array.Find(intArray, predicate); - //} - - - //[Benchmark] - //public double IntSpanFirstForEachSelector() - //{ - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // foreach (int i in asSpan) - // { - // if (firstInts(i)) - // { - // return i; - // } - // } - - // return 0; - //} - - //[Benchmark] - //public double IntSpanFirstFastSelector() - //{ - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // return asSpan.FirstF(firstInts); - //} - - //[Benchmark] - //public double IntListFirstLinqSelector() - //{ - // return intList.First(firstInts); - //} - - //[Benchmark] - //public double IntListFirstFastSelector() - //{ - // return intList.FirstF(firstInts); - //} - - //[Benchmark] - //public double IntAsListReadOnlyFirstLinqSelector() - //{ - // return intList.AsReadOnly().First(firstInts); - //} - - //[Benchmark] - //public double IntAsListReadOnlyFirstFastSelector() - //{ - // return intList.AsReadOnly().FirstF(firstInts); - //} - - //[Benchmark] - //public double IntArrayAsReadOnlyFirstLinqSelector() - //{ - // return Array.AsReadOnly(intArray).First(firstInts); - //} - - //[Benchmark] - //public double IntArrayAsReadOnlyFirstFastSelector() - //{ - // return Array.AsReadOnly(intArray).FirstF(firstInts); - //} + [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + public double IntArrayFirstLinqSelector() + { + return Benchmarks.intArray.First(firstInts); + } + + [BenchmarkCategory("intArray"), Benchmark] + public double IntArrayFirstArrayFindSelector() + { + Predicate predicate = new Predicate(firstInts); + return Array.Find(Benchmarks.intArray, predicate); + } + + [BenchmarkCategory("intArray"), Benchmark] + public double IntArrayFirstFastSelector() + { + return Benchmarks.intArray.FirstF(firstInts); + } + + + [BenchmarkCategory("localArray.AsSpan"), Benchmark(Baseline = true)] + public double IntSpanFirstForEachSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + foreach (int i in asSpan) + { + if (firstInts(i)) + { + return i; + } + } + + return 0; + } + + [BenchmarkCategory("localArray.AsSpan"), Benchmark] + public double IntSpanFirstFastSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.FirstF(firstInts); + } + + [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + public double IntListFirstLinqSelector() + { + return Benchmarks.intList.First(firstInts); + } + + [BenchmarkCategory("intList"), Benchmark] + public double IntListFirstFastSelector() + { + return Benchmarks.intList.FirstF(firstInts); + } + + [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + public double IntAsListReadOnlyFirstLinqSelector() + { + return Benchmarks.intList.AsReadOnly().First(firstInts); + } + + [BenchmarkCategory("intList.AsReadOnly"), Benchmark] + public double IntAsListReadOnlyFirstFastSelector() + { + return Benchmarks.intList.AsReadOnly().FirstF(firstInts); + } + + [BenchmarkCategory("Array.AsReadOnly"), Benchmark(Baseline = true)] + public double IntArrayAsReadOnlyFirstLinqSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).First(firstInts); + } + + [BenchmarkCategory("Array.AsReadOnly"), Benchmark] + public double IntArrayAsReadOnlyFirstFastSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).FirstF(firstInts); + } } } diff --git a/Benchmarks/BenchmarkLast.cs b/Benchmarks/BenchmarkLast.cs index 3469f57..eb67f4f 100644 --- a/Benchmarks/BenchmarkLast.cs +++ b/Benchmarks/BenchmarkLast.cs @@ -2,94 +2,97 @@ using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; namespace Tests { - public partial class Benchmarks + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksLast { private static readonly Func LastInts = (x) => x > 0; - //[Benchmark] - //public double IntArrayLastLinqSelector() - //{ - // return intArray.Last(LastInts); - //} - - //[Benchmark] - //public double IntArrayLastFastSelector() - //{ - // return intArray.LastF(LastInts); - //} - - //[Benchmark] - //public double IntArrayLastArrayFindSelector() - //{ - // Predicate predicate = new Predicate(LastInts); - // return Array.Find(intArray, predicate); - //} - - - //[Benchmark] - //public double IntSpanLastForEachSelector() - //{ - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // foreach (int i in asSpan) - // { - // if (LastInts(i)) - // { - // return i; - // } - // } - - // return 0; - //} - - //[Benchmark] - //public double IntSpanLastFastSelector() - //{ - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // return asSpan.LastF(LastInts); - //} - - //[Benchmark] - //public double IntListLastLinqSelector() - //{ - // return intList.Last(LastInts); - //} - - //[Benchmark] - //public double IntListLastFastSelector() - //{ - // return intList.LastF(LastInts); - //} - - //[Benchmark] - //public double IntAsListReadOnlyLastLinqSelector() - //{ - // return intList.AsReadOnly().Last(LastInts); - //} - - //[Benchmark] - //public double IntAsListReadOnlyLastFastSelector() - //{ - // return intList.AsReadOnly().LastF(LastInts); - //} - - //[Benchmark] - //public double IntArrayAsReadOnlyLastLinqSelector() - //{ - // return Array.AsReadOnly(intArray).Last(LastInts); - //} - - //[Benchmark] - //public double IntArrayAsReadOnlyLastFastSelector() - //{ - // return Array.AsReadOnly(intArray).LastF(LastInts); - //} + [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + public double IntArrayLastLinqSelector() + { + return Benchmarks.intArray.Last(LastInts); + } + + [BenchmarkCategory("intArray"), Benchmark] + public double IntArrayLastArrayFindSelector() + { + Predicate predicate = new Predicate(LastInts); + return Array.FindLast(Benchmarks.intArray, predicate); + } + + [BenchmarkCategory("intArray"), Benchmark] + public double IntArrayLastFastSelector() + { + return Benchmarks.intArray.LastF(LastInts); + } + + + + [BenchmarkCategory("localArray.AsSpan"), Benchmark(Baseline = true)] + public double IntSpanLastForEachSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + foreach (int i in asSpan) + { + if (LastInts(i)) + { + return i; + } + } + + return 0; + } + + [BenchmarkCategory("localArray.AsSpan"), Benchmark] + public double IntSpanLastFastSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.LastF(LastInts); + } + + [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + public double IntListLastLinqSelector() + { + return Benchmarks.intList.Last(LastInts); + } + + [BenchmarkCategory("intList"), Benchmark] + public double IntListLastFastSelector() + { + return Benchmarks.intList.LastF(LastInts); + } + + [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + public double IntAsListReadOnlyLastLinqSelector() + { + return Benchmarks.intList.AsReadOnly().Last(LastInts); + } + + [BenchmarkCategory("intList.AsReadOnly"), Benchmark] + public double IntAsListReadOnlyLastFastSelector() + { + return Benchmarks.intList.AsReadOnly().LastF(LastInts); + } + + [BenchmarkCategory("Array.AsReadOnly"), Benchmark(Baseline = true)] + public double IntArrayAsReadOnlyLastLinqSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).Last(LastInts); + } + + [BenchmarkCategory("Array.AsReadOnly"), Benchmark] + public double IntArrayAsReadOnlyLastFastSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).LastF(LastInts); + } } } diff --git a/Benchmarks/BenchmarkOrderBy.cs b/Benchmarks/BenchmarkOrderBy.cs index 006a335..35b0106 100644 --- a/Benchmarks/BenchmarkOrderBy.cs +++ b/Benchmarks/BenchmarkOrderBy.cs @@ -7,20 +7,21 @@ namespace Tests { - public partial class Benchmarks + //[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkOrderBy { private static readonly Func orderBy = (x) => x - 1; - //[Benchmark] - //public int IntArrayOrderByLinq() - //{ - // return intArray.OrderBy(orderBy).Sum(); - //} + [Benchmark(Baseline = true)] + public int IntArrayOrderByLinq() + { + return Benchmarks.intArray.OrderBy(orderBy).Sum(); + } - //[Benchmark] - //public int IntArrayOrderByFast() - //{ - // return intArray.OrderByF(orderBy).Sum(); - //} + [Benchmark] + public int IntArrayOrderByFast() + { + return Benchmarks.intArray.OrderByF(orderBy).Sum(); + } } } diff --git a/Benchmarks/BenchmarkSelect.cs b/Benchmarks/BenchmarkSelect.cs new file mode 100644 index 0000000..eba9a92 --- /dev/null +++ b/Benchmarks/BenchmarkSelect.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFaster.SIMD; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkSelect + { + [BenchmarkCategory("intArray.Select"), Benchmark(Baseline = true)] + public IEnumerable IntArraySelectLinq() + { + return Benchmarks.intArray.Select(x => x * x); + } + + [BenchmarkCategory("intArray.Select"), Benchmark] + public int[] IntArraySelectFast() + { + return Benchmarks.intArray.SelectF(x => x * x); + } + + [BenchmarkCategory("intArray.Select"), Benchmark] + public int[] IntArraySelectFastSIMD() + { + return Benchmarks.intArray.SelectS(x => x * x, x => x * x); + } + + + } +} diff --git a/Benchmarks/BenchmarkSequenceEqual.cs b/Benchmarks/BenchmarkSequenceEqual.cs new file mode 100644 index 0000000..590a0fe --- /dev/null +++ b/Benchmarks/BenchmarkSequenceEqual.cs @@ -0,0 +1,48 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; +using JM.LinqFaster.Parallel; +using JM.LinqFaster.SIMD; +using JM.LinqFaster.SIMD.Parallel; + +namespace Tests +{ + //[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkSequenceEqual + { + [Benchmark(Baseline = true)] + public bool IntArraySequenceEqual() + { + return Benchmarks.intArray.SequenceEqual(Benchmarks.array2); + } + + [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + public bool IntArraySequenceEqualF() + { + return Benchmarks.intArray.SequenceEqualF(Benchmarks.array2); + } + + + [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + public bool IntArraySequenceEqualP() + { + return Benchmarks.intArray.SequenceEqualP(Benchmarks.array2); + } + + [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + public bool IntArraySequenceEqualS() + { + return Benchmarks.intArray.SequenceEqualS(Benchmarks.array2); + } + + [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + public bool IntArraySequenceEqualSP() + { + return Benchmarks.intArray.SequenceEqualSP(Benchmarks.array2); + } + + } +} diff --git a/Benchmarks/BenchmarkSum.cs b/Benchmarks/BenchmarkSum.cs index 7abe5ef..a71281e 100644 --- a/Benchmarks/BenchmarkSum.cs +++ b/Benchmarks/BenchmarkSum.cs @@ -2,276 +2,261 @@ using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; +using JM.LinqFaster.SIMD; namespace Tests { - public partial class Benchmarks + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkSum { private static readonly Func sumDivide = (x) => x / 2; - //[Benchmark] - //public int ByteArraySumLinq() - //{ - // return byteArray.Aggregate(0, (current, b1) => current + b1); - //} - - //[Benchmark] - //public uint ByteArraySumFast() - //{ - // return byteArray.SumF(); - //} - - - //[Benchmark] - //public int ShortArraySumLinq() - //{ - // return shortArray.Aggregate(0, (current, s1) => current + s1); - //} - - //[Benchmark] - //public int ShortArraySumFast() - //{ - // return shortArray.SumF(); - //} - - - //[Benchmark] - //public int IntArraySumLinq() - //{ - // return intArray.Sum(); - //} - - //[Benchmark] - //public int IntArraySumFast() - //{ - // return intArray.SumF(); - //} - - //[Benchmark] - //public int IntSpanSumFor() - //{ - // int val = 0; - // Span span = intArray.AsSpan(); - // for (int index = 0; index < span.Length; index++) - // { - // val += span[index]; - // } - - // return val; - //} - - //[Benchmark] - //public int IntSpanSumFast() - //{ - // return intArray.AsSpan().SumF(); - //} - - //[Benchmark] - //public int IntIArraySumFast() - //{ - // return ((IReadOnlyList)intArray).SumF(); - //} - - //[Benchmark] - //public int IntListSumLinq() - //{ - // return intList.Sum(); - //} - - //[Benchmark] - //public int IntListSumFast() - //{ - // return intList.SumF(); - //} - - //[Benchmark] - //public int IntIReadOnlyListSumLinq() - //{ - // return ((IReadOnlyList)intList).Sum(); - //} - - //[Benchmark] - //public int IntIReadOnlyListSumFast() - //{ - // return ((IReadOnlyList)intList).SumF(); - //} - - - //[Benchmark] - //public int IntArraySumLinqSelect() - //{ - // return intArray.Sum(x => x / 2); - //} - - //[Benchmark] - //public int IntArraySumFastSelect() - //{ - // return intArray.SumF(x => x / 2); - //} - - //[Benchmark] - //public double IntReadOnlyArraySumWithSelectLinq() - //{ - // return Array.AsReadOnly(intArray).Sum(x => x / 2); - //} - - //[Benchmark] - //public double IntReadOnlyArraySumWithSelectFast() - //{ - // return Array.AsReadOnly(intArray).SumF(x => x / 2); - //} - - //[Benchmark] - //public int IntArraySumFastSIMD() - //{ - // return intArray.SumS(); - //} - - //[Benchmark] - //public int? IntNullArraySumLinq() - //{ - // return intNullArray.Sum(); - //} - - //[Benchmark] - //public int? IntNullArraySumFast() - //{ - // return intNullArray.SumF(); - //} - - //[Benchmark] - //public int IntNullArraySumLinqSelect() - //{ - // return intNullArray.Sum(x => x/2 ?? 0); - //} - - //[Benchmark] - //public int IntNullArraySumFastSelect() - //{ - // return intNullArray.SumF(x => x/2 ?? 0); - //} - - //[Benchmark] - //public float FloatArraySumLinq() - //{ - // return floatArray.Sum(); - //} - - //[Benchmark] - //public float FloatArraySumFast() - //{ - // return floatArray.SumF(); - //} - - //[Benchmark] - //public float FloatListSumLinq() - //{ - // return floatList.Sum(); - //} - - //[Benchmark] - //public float FloatListSumFast() - //{ - // return floatList.SumF(); - //} - - //[Benchmark] - //public float FloatArraySumLinqSelect() - //{ - // return floatArray.Sum(x => x / 2); - //} - - //[Benchmark] - //public float FloatArraySumFastSelect() - //{ - // return floatArray.SumF(x => x / 2); - //} - - //[Benchmark] - //public float? FloatNullArraySumLinq() - //{ - // return floatNullArray.Sum(); - //} - - //[Benchmark] - //public float? FloatNullArraySumFast() - //{ - // return floatNullArray.SumF(); - //} - - //[Benchmark] - //public float FloatNullArraySumLinqSelect() - //{ - // return floatNullArray.Sum(x => x / 2 ?? 0); - //} - - //[Benchmark] - //public float FloatNullArraySumFastSelect() - //{ - // return floatNullArray.SumF(x => x / 2 ?? 0); - //} - - - //[Benchmark] - //public double DoubleArraySumLinq() - //{ - // return doubleArray.Sum(); - //} - - //[Benchmark] - //public double DoubleArraySumFast() - //{ - // return doubleArray.SumF(); - //} - - //[Benchmark] - //public double DoubleListSumLinq() - //{ - // return doubleList.Sum(); - //} - - //[Benchmark] - //public double DoubleListSumFast() - //{ - // return doubleList.SumF(); - //} - - //[Benchmark] - //public double DoubleArraySumLinqSelect() - //{ - // return doubleArray.Sum(x => x / 2); - //} - - //[Benchmark] - //public double DoubleArraySumFastSelect() - //{ - // return doubleArray.SumF(x => x / 2); - //} - - //[Benchmark] - //public double? DoubleNullArraySumLinq() - //{ - // return doubleNullArray.Sum(); - //} - - //[Benchmark] - //public double? DoubleNullArraySumFast() - //{ - // return doubleNullArray.SumF(); - //} - - //[Benchmark] - //public double? DoubleNullArraySumLinqSelect() - //{ - // return doubleNullArray.Sum(x => x / 2 ?? 0); - //} - - //[Benchmark] - //public double? DoubleNullArraySumFastSelect() - //{ - // return doubleNullArray.SumF(x => x / 2 ?? 0); - //} + [BenchmarkCategory("byteArray"), Benchmark(Baseline = true)] + public int ByteArraySumLinq() + { + return Benchmarks.byteArray.Aggregate(0, (current, b1) => current + b1); + } + + [BenchmarkCategory("byteArray"), Benchmark] + public uint ByteArraySumFast() + { + return Benchmarks.byteArray.SumF(); + } + + + [BenchmarkCategory("shortArray"), Benchmark(Baseline = true)] + public int ShortArraySumLinq() + { + return Benchmarks.shortArray.Aggregate(0, (current, s1) => current + s1); + } + + [BenchmarkCategory("shortArray"), Benchmark] + public int ShortArraySumFast() + { + return Benchmarks.shortArray.SumF(); + } + + + [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + public int IntArraySumLinq() + { + return Benchmarks.intArray.Sum(); + } + + [BenchmarkCategory("intArray"), Benchmark] + public int IntArraySumFast() + { + return Benchmarks.intArray.SumF(); + } + + [BenchmarkCategory("intArray"), Benchmark] + public int IntArraySumFastSIMD() + { + return Benchmarks.intArray.SumS(); + } + + [BenchmarkCategory("intArraySpan"), Benchmark(Baseline = true)] + public int IntSpanSumFor() + { + int val = 0; + Span span = Benchmarks.intArray.AsSpan(); + for (int index = 0; index < span.Length; index++) + { + val += span[index]; + } + + return val; + } + + [BenchmarkCategory("intArraySpan"), Benchmark] + public int IntSpanSumFast() + { + return Benchmarks.intArray.AsSpan().SumF(); + } + + [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + public int IntListSumLinq() + { + return Benchmarks.intList.Sum(); + } + + [BenchmarkCategory("intList"), Benchmark] + public int IntListSumFast() + { + return Benchmarks.intList.SumF(); + } + + + [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + public int IntArraySumLinqSelect() + { + return Benchmarks.intArray.Sum(sumDivide); + } + + [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + public int IntArraySumFastSelect() + { + return Benchmarks.intArray.SumF(sumDivide); + } + + [BenchmarkCategory("intArrayAsReadOnly"), Benchmark(Baseline = true)] + public double IntReadOnlyArraySumWithSelectLinq() + { + return Array.AsReadOnly(Benchmarks.intArray).Sum(sumDivide); + } + + [BenchmarkCategory("intArrayAsReadOnly"), Benchmark] + public double IntReadOnlyArraySumWithSelectFast() + { + return Array.AsReadOnly(Benchmarks.intArray).SumF(sumDivide); + } + + [BenchmarkCategory("intNullArray"), Benchmark(Baseline = true)] + public int? IntNullArraySumLinq() + { + return Benchmarks.intNullArray.Sum(); + } + + [BenchmarkCategory("intNullArray"), Benchmark] + public int? IntNullArraySumFast() + { + return Benchmarks.intNullArray.SumF(); + } + + [BenchmarkCategory("intNullArraySelect"), Benchmark(Baseline = true)] + public int IntNullArraySumLinqSelect() + { + return Benchmarks.intNullArray.Sum(x => x / 2 ?? 0); + } + + [BenchmarkCategory("intNullArraySelect"), Benchmark] + public int IntNullArraySumFastSelect() + { + return Benchmarks.intNullArray.SumF(x => x / 2 ?? 0); + } + + [BenchmarkCategory("floatArray"), Benchmark(Baseline = true)] + public float FloatArraySumLinq() + { + return Benchmarks.floatArray.Sum(); + } + + [BenchmarkCategory("floatArray"), Benchmark] + public float FloatArraySumFast() + { + return Benchmarks.floatArray.SumF(); + } + + [BenchmarkCategory("floatList"), Benchmark(Baseline = true)] + public float FloatListSumLinq() + { + return Benchmarks.floatList.Sum(); + } + + [BenchmarkCategory("floatList"), Benchmark] + public float FloatListSumFast() + { + return Benchmarks.floatList.SumF(); + } + + [BenchmarkCategory("floatArraySelect"), Benchmark(Baseline = true)] + public float FloatArraySumLinqSelect() + { + return Benchmarks.floatArray.Sum(x => x / 2); + } + + [BenchmarkCategory("floatArraySelect"), Benchmark] + public float FloatArraySumFastSelect() + { + return Benchmarks.floatArray.SumF(x => x / 2); + } + + [BenchmarkCategory("floatNullArray"), Benchmark(Baseline = true)] + public float? FloatNullArraySumLinq() + { + return Benchmarks.floatNullArray.Sum(); + } + + [BenchmarkCategory("floatNullArray"), Benchmark] + public float? FloatNullArraySumFast() + { + return Benchmarks.floatNullArray.SumF(); + } + + [BenchmarkCategory("floatNullArraySelect"), Benchmark(Baseline = true)] + public float FloatNullArraySumLinqSelect() + { + return Benchmarks.floatNullArray.Sum(x => x / 2 ?? 0); + } + + [BenchmarkCategory("floatNullArraySelect"), Benchmark] + public float FloatNullArraySumFastSelect() + { + return Benchmarks.floatNullArray.SumF(x => x / 2 ?? 0); + } + + + [BenchmarkCategory("doubleArray"), Benchmark(Baseline = true)] + public double DoubleArraySumLinq() + { + return Benchmarks.doubleArray.Sum(); + } + + [BenchmarkCategory("doubleArray"), Benchmark] + public double DoubleArraySumFast() + { + return Benchmarks.doubleArray.SumF(); + } + + [BenchmarkCategory("doubleList"), Benchmark(Baseline = true)] + public double DoubleListSumLinq() + { + return Benchmarks.doubleList.Sum(); + } + + [BenchmarkCategory("doubleList"), Benchmark] + public double DoubleListSumFast() + { + return Benchmarks.doubleList.SumF(); + } + + [BenchmarkCategory("doubleArraySelect"), Benchmark(Baseline = true)] + public double DoubleArraySumLinqSelect() + { + return Benchmarks.doubleArray.Sum(x => x / 2); + } + + [BenchmarkCategory("doubleArraySelect"), Benchmark] + public double DoubleArraySumFastSelect() + { + return Benchmarks.doubleArray.SumF(x => x / 2); + } + + [BenchmarkCategory("doubleNullArray"), Benchmark(Baseline = true)] + public double? DoubleNullArraySumLinq() + { + return Benchmarks.doubleNullArray.Sum(); + } + + [BenchmarkCategory("doubleNullArray"), Benchmark] + public double? DoubleNullArraySumFast() + { + return Benchmarks.doubleNullArray.SumF(); + } + + [BenchmarkCategory("doubleNullArraySelect"), Benchmark(Baseline = true)] + public double? DoubleNullArraySumLinqSelect() + { + return Benchmarks.doubleNullArray.Sum(x => x / 2 ?? 0); + } + + [BenchmarkCategory("doubleNullArraySelect"), Benchmark] + public double? DoubleNullArraySumFastSelect() + { + return Benchmarks.doubleNullArray.SumF(x => x / 2 ?? 0); + } } } diff --git a/Benchmarks/BenchmarkWhereSum.cs b/Benchmarks/BenchmarkWhereSum.cs index 9ab07f5..188c4b7 100644 --- a/Benchmarks/BenchmarkWhereSum.cs +++ b/Benchmarks/BenchmarkWhereSum.cs @@ -1,60 +1,69 @@ using System; -using System.Collections.Generic; using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; -using JM.LinqFaster.SIMD; namespace Tests { - public partial class Benchmarks + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkWhereSum { - [Benchmark] + [BenchmarkCategory("byteArray"), Benchmark(Baseline = true)] public int ByteArrayWhereSumLinq() { - return byteArray.Where(x=> x>0).Aggregate(0, (current, b1) => current + b1); + return Benchmarks.byteArray.Where(x => x > 0).Aggregate(0, (current, b1) => current + b1); } - [Benchmark] + [BenchmarkCategory("byteArray"), Benchmark] public uint ByteArrayWhereSumFast() { - return byteArray.WhereSumF(x => x > 0); + return Benchmarks.byteArray.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("shortArray"), Benchmark(Baseline = true)] public int ShortArrayWhereSumLinq() { - return shortArray.Where(x => x > 0).Aggregate(0, (current, s1) => current + s1); + return Benchmarks.shortArray.Where(x => x > 0).Aggregate(0, (current, s1) => current + s1); } - [Benchmark] + [BenchmarkCategory("shortArray"), Benchmark] public int ShortArrayWhereSumFast() { - return shortArray.WhereSumF(x => x > 0); + return Benchmarks.shortArray.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] public int IntArrayWhereSumLinq() { - return intArray.Where(x => x > 0).Sum(); + return Benchmarks.intArray.Where(x => x > 0).Sum(); } - [Benchmark] + [BenchmarkCategory("intArray"), Benchmark] public int IntArrayWhereSumFast() { - return intArray.WhereSumF(x => x > 0); + return Benchmarks.intArray.WhereSumF(x => x > 0); } - [Benchmark] + /* + [BenchmarkCategory("intArray"), Benchmark] + public int IntArrayWhereSumFastSIMD() + { + return intArray.WhereSumS(x => x > 0); + } + */ + + + [BenchmarkCategory("intArray.AsSpan"), Benchmark(Baseline = true)] public int IntSpanWhereSumFor() { int val = 0; - Span span = intArray.AsSpan(); + Span span = Benchmarks.intArray.AsSpan(); for (int index = 0; index < span.Length; index++) { if (span[index] > 0) @@ -66,241 +75,217 @@ public int IntSpanWhereSumFor() return val; } - [Benchmark] + [BenchmarkCategory("intArray.AsSpan"), Benchmark] public int IntSpanWhereSumFast() { - return intArray.AsSpan().WhereSumF(x => x > 0); - } - - [Benchmark] - public int IntIArrayWhereSumFast() - { - return ((IReadOnlyList)intArray).WhereSumF(x => x > 0); + return Benchmarks.intArray.AsSpan().WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("intList"), Benchmark(Baseline = true)] public int IntListWhereSumLinq() { - return intList.Where(x => x > 0).Sum(); + return Benchmarks.intList.Where(x => x > 0).Sum(); } - [Benchmark] + [BenchmarkCategory("intList"), Benchmark] public int IntListWhereSumFast() { - return intList.WhereSumF(x => x > 0); - } - - [Benchmark] - public int IntIReadOnlyListWhereSumLinq() - { - return ((IReadOnlyList)intList).Where(x => x > 0).Sum(); - } - - [Benchmark] - public int IntIReadOnlyListWhereSumFast() - { - return ((IReadOnlyList)intList).WhereSumF(x => x > 0); + return Benchmarks.intList.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("intArraySelect"), Benchmark(Baseline = true)] public int IntArrayWhereSumLinqSelect() { - return intArray.Where(x => x > 0).Sum(x => x / 2); + return Benchmarks.intArray.Where(x => x > 0).Sum(x => x / 2); } - [Benchmark] + [BenchmarkCategory("intArraySelect"), Benchmark] public int IntArrayWhereSumFastSelect() { - return intArray.WhereSumF(x => x > 0, x => x / 2); + return Benchmarks.intArray.WhereSumF(x => x > 0, x => x / 2); } - [Benchmark] + [BenchmarkCategory("Array.AsReadOnlySelect"), Benchmark(Baseline = true)] public double IntReadOnlyArraySumWithSelectLinq() { - return Array.AsReadOnly(intArray).Where(x => x > 0).Sum(x => x / 2); + return Array.AsReadOnly(Benchmarks.intArray).Where(x => x > 0).Sum(x => x / 2); } - [Benchmark] + [BenchmarkCategory("Array.AsReadOnlySelect"), Benchmark] public double IntReadOnlyArraySumWithSelectFast() { - return Array.AsReadOnly(intArray).WhereSumF(x => x > 0, x => x / 2); + return Array.AsReadOnly(Benchmarks.intArray).WhereSumF(x => x > 0, x => x / 2); } - /* - [Benchmark] - public int IntArrayWhereSumFastSIMD() - { - return intArray.WhereSumS(x => x > 0); - } - */ - [Benchmark] + + [BenchmarkCategory("intNullArray"), Benchmark(Baseline = true)] public int? IntNullArrayWhereSumLinq() { - return intNullArray.Where(x => x > 0).Sum(); + return Benchmarks.intNullArray.Where(x => x > 0).Sum(); } - [Benchmark] + [BenchmarkCategory("intNullArray"), Benchmark] public int? IntNullArrayWhereSumFast() { - return intNullArray.WhereSumF(x => x > 0); + return Benchmarks.intNullArray.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("intNullArraySelect"), Benchmark(Baseline = true)] public int IntNullArrayWhereSumLinqSelect() { - return intNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); + return Benchmarks.intNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); } - [Benchmark] + [BenchmarkCategory("intNullArraySelect"), Benchmark] public int IntNullArrayWhereSumFastSelect() { - return intNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); + return Benchmarks.intNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); } - [Benchmark] + [BenchmarkCategory("floatArray"), Benchmark(Baseline = true)] public float FloatArrayWhereSumLinq() { - return floatArray.Where(x => x > 0).Sum(); + return Benchmarks.floatArray.Where(x => x > 0).Sum(); } - [Benchmark] + [BenchmarkCategory("floatArray"), Benchmark] public float FloatArrayWhereSumFast() { - return floatArray.WhereSumF(x => x > 0); + return Benchmarks.floatArray.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("floatList"), Benchmark(Baseline = true)] public float FloatListWhereSumLinq() { - return floatList.Where(x => x > 0).Sum(); + return Benchmarks.floatList.Where(x => x > 0).Sum(); } - [Benchmark] + [BenchmarkCategory("floatList"), Benchmark] public float FloatListWhereSumFast() { - return floatList.WhereSumF(x => x > 0); + return Benchmarks.floatList.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("floatArraySelect"), Benchmark(Baseline = true)] public float FloatArrayWhereSumLinqSelect() { - return floatArray.Where(x => x > 0).Sum( x => x / 2); + return Benchmarks.floatArray.Where(x => x > 0).Sum(x => x / 2); } - [Benchmark] + [BenchmarkCategory("floatArraySelect"), Benchmark] public float FloatArrayWhereSumFastSelect() { - return floatArray.WhereSumF(x => x > 0, x => x / 2); + return Benchmarks.floatArray.WhereSumF(x => x > 0, x => x / 2); } - [Benchmark] + [BenchmarkCategory("floatNullArray"), Benchmark(Baseline = true)] public float? FloatNullArrayWhereSumLinq() { - return floatNullArray.Where(x => x > 0).Sum(); + return Benchmarks.floatNullArray.Where(x => x > 0).Sum(); } - [Benchmark] + [BenchmarkCategory("floatNullArray"), Benchmark] public float? FloatNullArrayWhereSumFast() { - return floatNullArray.WhereSumF(x => x > 0); + return Benchmarks.floatNullArray.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("floatNullArraySelect"), Benchmark(Baseline = true)] public float FloatNullArrayWhereSumLinqSelect() { - return floatNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); + return Benchmarks.floatNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); } - [Benchmark] + [BenchmarkCategory("floatNullArraySelect"), Benchmark] public float FloatNullArrayWhereSumFastSelect() { - return floatNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); + return Benchmarks.floatNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); } - [Benchmark] + [BenchmarkCategory("doubleArray"), Benchmark(Baseline = true)] public double DoubleArrayWhereSumLinq() { - return doubleArray.Where(x => x > 0).Sum(); + return Benchmarks.doubleArray.Where(x => x > 0).Sum(); } - [Benchmark] + [BenchmarkCategory("doubleArray"), Benchmark] public double DoubleArrayWhereSumFast() { - return doubleArray.WhereSumF(x => x > 0); + return Benchmarks.doubleArray.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("doubleList"), Benchmark(Baseline = true)] public double DoubleListWhereSumLinq() { - return doubleList.Where(x => x > 0).Sum(); + return Benchmarks.doubleList.Where(x => x > 0).Sum(); } - [Benchmark] + [BenchmarkCategory("doubleList"), Benchmark] public double DoubleListWhereSumFast() { - return doubleList.WhereSumF(x => x > 0); + return Benchmarks.doubleList.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("doubleArraySelect"), Benchmark(Baseline = true)] public double DoubleArrayWhereSumLinqSelect() { - return doubleArray.Where(x => x > 0).Sum(x => x / 2); + return Benchmarks.doubleArray.Where(x => x > 0).Sum(x => x / 2); } - [Benchmark] + [BenchmarkCategory("doubleArraySelect"), Benchmark] public double DoubleArrayWhereSumFastSelect() { - return doubleArray.WhereSumF(x => x > 0, x => x / 2); + return Benchmarks.doubleArray.WhereSumF(x => x > 0, x => x / 2); } - [Benchmark] + [BenchmarkCategory("doubleNullArray"), Benchmark(Baseline = true)] public double? DoubleNullArrayWhereSumLinq() { - return doubleNullArray.Where(x => x > 0).Sum(); + return Benchmarks.doubleNullArray.Where(x => x > 0).Sum(); } - [Benchmark] + [BenchmarkCategory("doubleNullArray"), Benchmark] public double? DoubleNullArrayWhereSumFast() { - return doubleNullArray.WhereSumF(x => x > 0); + return Benchmarks.doubleNullArray.WhereSumF(x => x > 0); } - [Benchmark] + [BenchmarkCategory("doubleNullArraySelect"), Benchmark(Baseline = true)] public double? DoubleNullArrayWhereSumLinqSelect() { - return doubleNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); + return Benchmarks.doubleNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); } - [Benchmark] + [BenchmarkCategory("doubleNullArraySelect"), Benchmark] public double? DoubleNullArrayWhereSumFastSelect() { - return doubleNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); + return Benchmarks.doubleNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); } - [Benchmark] + [BenchmarkCategory("intListSelect"), Benchmark(Baseline = true)] public int IntListSumWithSelectLinq() { - return intList.Where(x => x > 0).Sum(x => x / 2); + return Benchmarks.intList.Where(x => x > 0).Sum(x => x / 2); } - [Benchmark] + [BenchmarkCategory("intListSelect"), Benchmark] public int IntListSumWithSelectFast() { - return intList.WhereSumF(x => x > 0, x => x / 2); + return Benchmarks.intList.WhereSumF(x => x > 0, x => x / 2); } - [Benchmark] + [BenchmarkCategory("intList.AsReadOnlySelect"), Benchmark(Baseline = true)] public double IntReadOnlyListSumWithSelectLinq() { - return intList.AsReadOnly().Where(x => x > 0).Sum(x => x / 2); + return Benchmarks.intList.AsReadOnly().Where(x => x > 0).Sum(x => x / 2); } - [Benchmark] + [BenchmarkCategory("intList.AsReadOnlySelect"), Benchmark] public double IntReadOnlyListSumWithSelectFast() { - return intList.AsReadOnly().WhereSumF(x => x > 0, x => x / 2); + return Benchmarks.intList.AsReadOnly().WhereSumF(x => x > 0, x => x / 2); } } diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index 2b89f68..94fe581 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -1,16 +1,12 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Reports; using BenchmarkDotNet.Running; -using JM.LinqFaster; -using JM.LinqFaster.SIMD; - namespace Tests { [MemoryDiagnoser] @@ -19,32 +15,25 @@ public partial class Benchmarks private const int LARGE_TEST_SIZE = 1000000; private const int SMALL_TEST_SIZE = 100; - private List list; - private byte[] byteArray; - private short[] shortArray; - private int[] intArray; - private List intList; - private int?[] intNullArray; - private int[] array2; - private float[] floatArray; - private List floatList; - private float?[] floatNullArray; - private double[] doubleArray; - private List doubleList; - private double?[] doubleNullArray; - private string[] strarray; - - - - [Params(1000000)] - public int TEST_SIZE { get; set; } - - public Benchmarks() - { - } - - [GlobalSetup] - public void Setup() + internal static List list; + internal static byte[] byteArray; + internal static short[] shortArray; + internal static int[] intArray; + internal static List intList; + internal static int?[] intNullArray; + internal static int[] array2; + internal static float[] floatArray; + internal static List floatList; + internal static float?[] floatNullArray; + internal static double[] doubleArray; + internal static List doubleList; + internal static double?[] doubleNullArray; + internal static string[] strarray; + + + internal static int TEST_SIZE => LARGE_TEST_SIZE; + + static Benchmarks() { byteArray = new byte[TEST_SIZE]; shortArray = new short[TEST_SIZE]; @@ -83,99 +72,28 @@ public void Setup() - - //[Benchmark] - //public double IntArrayWhereAggregateLinq() - //{ - // return intArray.Where(x => x % 2 == 0).Aggregate(0.0, mulXInts, acc => acc / intArray.Length); - //} - - //[Benchmark] - //public double IntArrayWhereAggregateFast() - //{ - // return intArray.WhereAggregateF(x => x % 2 == 0, 0.0, mulXInts, acc => acc / intArray.Length); - //} - - //[Benchmark] - //public int[] IntArraySelectLinq() - //{ - // return intArray.Select(x => x * x); - //} - - //[Benchmark] - //public int[] IntArraySelectFast() - //{ - // return intArray.SelectF(x => x * x); - //} - - //[Benchmark] - //public int[] IntArraySelectFastSIMD() - //{ - // return intArray.SelectS(x => x * x, x => x * x); - //} - - - - //[Benchmark] - //public int[] IntArrayRepeatLinq() - //{ - // return Enumerable.Repeat(5, TEST_SIZE).ToArray(); - //} - - //[Benchmark] - //public int[] IntArrayRepeatFast() - //{ - // return LinqFaster.RepeatArrayF(5, TEST_SIZE); - //} - - - //[Benchmark] - //public int[] IntArrayRepeatFastSIMD() - //{ - // return LinqFasterSIMD.RepeatS(5, TEST_SIZE); - //} - - //[Benchmark] - //public int[] IntArrayRepeatFastSIMDB() - //{ - // return LinqFasterSIMD.RepeatSB(5, TEST_SIZE); - //} - - //[Benchmark] - //public bool IntArraySequenceEqual() - //{ - // return intArray.SequenceEqual(array2); - //} - - //[Benchmark] - //public bool IntArraySequenceEqualF() - //{ - // return intArray.SequenceEqualF(array2); - //} - - - //[Benchmark] - //public bool IntArraySequenceEqualP() - //{ - // return intArray.SequenceEqualP(array2); - //} - - //[Benchmark] - //public bool IntArraySequenceEqualS() - //{ - // return intArray.SequenceEqualS(array2); - //} - - //[Benchmark] - //public bool IntArraySequenceEqualSP() - //{ - // return intArray.SequenceEqualSP(array2); - //} - - public static void Main(string[] args) { - Console.WriteLine(BenchmarkRunner.Run(ManualConfig.Create(DefaultConfig.Instance).With(Job.RyuJitX64)).ResultsDirectoryPath); + ManualConfig config = (ManualConfig)ManualConfig.Create(DefaultConfig.Instance).With(Job.RyuJitX64); + config.Options |= ConfigOptions.JoinSummary; + + BenchmarkRunInfo[] benchmarkRunInfos = + { + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarkSum), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksAverage), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksFirst), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksLast), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksMax), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksMin), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksAggregate), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksRepeat), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarkOrderBy), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarkSequenceEqual), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarkSelect), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksWhereAggregate), config), + //BenchmarkConverter.TypeToBenchmarks(typeof ( + }; + Summary[] summaries = BenchmarkRunner.Run(benchmarkRunInfos); Console.WriteLine("Press enter to close"); Console.ReadLine(); } diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index e002907..975c5a0 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -8,7 +8,7 @@ {42DD1432-5209-49B3-81D7-B487A9DBF2F3} Exe Properties - Benchmarks + Tests Benchmarks v4.6.1 512 @@ -66,9 +66,8 @@ ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll - - - ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll + True + True ..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll @@ -106,22 +105,13 @@ True - - ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll - - - ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - ..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll ..\packages\System.Reflection.TypeExtensions.4.5.1\lib\net461\System.Reflection.TypeExtensions.dll - - ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll - ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll True @@ -204,8 +194,12 @@ + + + + diff --git a/Benchmarks/BenchmarksMax.cs b/Benchmarks/BenchmarksMax.cs index 7f24226..10bec5e 100644 --- a/Benchmarks/BenchmarksMax.cs +++ b/Benchmarks/BenchmarksMax.cs @@ -2,162 +2,164 @@ using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; namespace Tests { - //public partial class Benchmarks - //{ - // private static readonly Func MaxInts = (x) => x + 1; - - // [Benchmark] - // public double IntArrayMaxLinq() - // { - // return intArray.Max(); - // } - - // [Benchmark] - // public double IntArrayMaxFast() - // { - // return intArray.MaxF(); - // } - - // [Benchmark] - // public double IntSpanMaxForEach() - // { - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // int max = int.MinValue; - // foreach (int i in asSpan) - // { - // if (max > i) - // { - // max = i; - // } - // } - - // return max; - // } - - // [Benchmark] - // public double IntSpanMaxFast() - // { - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // return asSpan.MaxF(); - // } - - // [Benchmark] - // public double IntListMaxLinq() - // { - // return intList.Max(); - // } - - // [Benchmark] - // public double IntListMaxFast() - // { - // return intList.MaxF(); - // } - - // [Benchmark] - // public double IntAsListReadOnlyMaxLinq() - // { - // return intList.AsReadOnly().Max(); - // } - - // [Benchmark] - // public double IntAsListReadOnlyMaxFast() - // { - // return intList.AsReadOnly().MaxF(); - // } - - // [Benchmark] - // public double IntArrayAsReadOnlyMaxLinq() - // { - // return Array.AsReadOnly(intArray).Max(); - // } - - // [Benchmark] - // public double IntArrayAsReadOnlyMaxFast() - // { - // return Array.AsReadOnly(intArray).MaxF(); - // } - - - // [Benchmark] - // public double IntArrayMaxLinqSelector() - // { - // return intArray.Max(MaxInts); - // } - - // [Benchmark] - // public double IntArrayMaxFastSelector() - // { - // return intArray.MaxF(MaxInts); - // } - - // [Benchmark] - // public double IntSpanMaxForEachSelector() - // { - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // int max = int.MinValue; - // foreach (int i in asSpan) - // { - // int l = MaxInts(i); - // if (max > l) - // { - // max = l; - // } - // } - - // return max; - // } - - // [Benchmark] - // public double IntSpanMaxFastSelector() - // { - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // return asSpan.MaxF(MaxInts); - // } - - // [Benchmark] - // public double IntListMaxLinqSelector() - // { - // return intList.Max(MaxInts); - // } - - // [Benchmark] - // public double IntListMaxFastSelector() - // { - // return intList.MaxF(MaxInts); - // } - - // [Benchmark] - // public double IntAsListReadOnlyMaxLinqSelector() - // { - // return intList.AsReadOnly().Max(MaxInts); - // } - - // [Benchmark] - // public double IntAsListReadOnlyMaxFastSelector() - // { - // return intList.AsReadOnly().MaxF(MaxInts); - // } - - // [Benchmark] - // public double IntArrayAsReadOnlyMaxLinqSelector() - // { - // return Array.AsReadOnly(intArray).Max(MaxInts); - // } - - // [Benchmark] - // public double IntArrayAsReadOnlyMaxFastSelector() - // { - // return Array.AsReadOnly(intArray).MaxF(MaxInts); - // } - - //} + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksMax + { + private static readonly Func MaxInts = (x) => x + 1; + + [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + public double IntArrayMaxLinq() + { + return Benchmarks.intArray.Max(); + } + + [BenchmarkCategory("intArray"), Benchmark] + public double IntArrayMaxFast() + { + return Benchmarks.intArray.MaxF(); + } + + [BenchmarkCategory("localArray.AsSpan"), Benchmark(Baseline = true)] + public double IntSpanMaxForEach() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + int max = int.MinValue; + foreach (int i in asSpan) + { + if (max > i) + { + max = i; + } + } + + return max; + } + + [BenchmarkCategory("localArray.AsSpan"), Benchmark] + public double IntSpanMaxFast() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.MaxF(); + } + + [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + public double IntListMaxLinq() + { + return Benchmarks.intList.Max(); + } + + [BenchmarkCategory("intList"), Benchmark] + public double IntListMaxFast() + { + return Benchmarks.intList.MaxF(); + } + + [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + public double IntAsListReadOnlyMaxLinq() + { + return Benchmarks.intList.AsReadOnly().Max(); + } + + [BenchmarkCategory("intList.AsReadOnly"), Benchmark] + public double IntAsListReadOnlyMaxFast() + { + return Benchmarks.intList.AsReadOnly().MaxF(); + } + + [BenchmarkCategory("Array.AsReadOnly"), Benchmark(Baseline = true)] + public double IntArrayAsReadOnlyMaxLinq() + { + return Array.AsReadOnly(Benchmarks.intArray).Max(); + } + + [BenchmarkCategory("Array.AsReadOnly"), Benchmark] + public double IntArrayAsReadOnlyMaxFast() + { + return Array.AsReadOnly(Benchmarks.intArray).MaxF(); + } + + + [BenchmarkCategory("intArraySelector"), Benchmark(Baseline = true)] + public double IntArrayMaxLinqSelector() + { + return Benchmarks.intArray.Max(MaxInts); + } + + [BenchmarkCategory("intArraySelector"), Benchmark] + public double IntArrayMaxFastSelector() + { + return Benchmarks.intArray.MaxF(MaxInts); + } + + [BenchmarkCategory("localArray.AsSpanSelector"), Benchmark(Baseline = true)] + public double IntSpanMaxForEachSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + int max = int.MinValue; + foreach (int i in asSpan) + { + int l = MaxInts(i); + if (max > l) + { + max = l; + } + } + + return max; + } + + [BenchmarkCategory("localArray.AsSpanSelector"), Benchmark] + public double IntSpanMaxFastSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.MaxF(MaxInts); + } + + [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + public double IntListMaxLinqSelector() + { + return Benchmarks.intList.Max(MaxInts); + } + + [BenchmarkCategory("intList"), Benchmark] + public double IntListMaxFastSelector() + { + return Benchmarks.intList.MaxF(MaxInts); + } + + [BenchmarkCategory("intList.AsReadOnlySelector"), Benchmark(Baseline = true)] + public double IntAsListReadOnlyMaxLinqSelector() + { + return Benchmarks.intList.AsReadOnly().Max(MaxInts); + } + + [BenchmarkCategory("intList.AsReadOnlySelector"), Benchmark] + public double IntAsListReadOnlyMaxFastSelector() + { + return Benchmarks.intList.AsReadOnly().MaxF(MaxInts); + } + + [BenchmarkCategory("Array.AsReadOnlySelector"), Benchmark(Baseline = true)] + public double IntArrayAsReadOnlyMaxLinqSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).Max(MaxInts); + } + + [BenchmarkCategory("Array.AsReadOnlySelector"), Benchmark] + public double IntArrayAsReadOnlyMaxFastSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).MaxF(MaxInts); + } + + } } diff --git a/Benchmarks/BenchmarksMin.cs b/Benchmarks/BenchmarksMin.cs index 5fb1465..4f018c8 100644 --- a/Benchmarks/BenchmarksMin.cs +++ b/Benchmarks/BenchmarksMin.cs @@ -1,166 +1,172 @@ using System; using System.Linq; + using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFaster.SIMD; namespace Tests { - public partial class Benchmarks + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksMin { - private static readonly Func MinInts = (x) => x + 1; - - //[Benchmark] - //public double IntArrayMinLinq() - //{ - // return intArray.Min(); - //} - - // [Benchmark] - // public double IntArrayMinFast() - // { - // return intArray.MinF(); - // } - - //[Benchmark] - //public int IntArrayMinFastSIMD() - //{ - // return intArray.MinS(); - //} - - // [Benchmark] - // public double IntSpanMinForEach() - // { - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // int Min = int.MinValue; - // foreach (int i in asSpan) - // { - // if (Min > i) - // { - // Min = i; - // } - // } - - // return Min; - // } - - // [Benchmark] - // public double IntSpanMinFast() - // { - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // return asSpan.MinF(); - // } - - // [Benchmark] - // public double IntListMinLinq() - // { - // return intList.Min(); - // } - - // [Benchmark] - // public double IntListMinFast() - // { - // return intList.MinF(); - // } - - // [Benchmark] - // public double IntAsListReadOnlyMinLinq() - // { - // return intList.AsReadOnly().Min(); - // } - - // [Benchmark] - // public double IntAsListReadOnlyMinFast() - // { - // return intList.AsReadOnly().MinF(); - // } - - // [Benchmark] - // public double IntArrayAsReadOnlyMinLinq() - // { - // return Array.AsReadOnly(intArray).Min(); - // } - - // [Benchmark] - // public double IntArrayAsReadOnlyMinFast() - // { - // return Array.AsReadOnly(intArray).MinF(); - // } - - - // [Benchmark] - // public double IntArrayMinLinqSelector() - // { - // return intArray.Min(MinInts); - // } - - // [Benchmark] - // public double IntArrayMinFastSelector() - // { - // return intArray.MinF(MinInts); - // } - - // [Benchmark] - // public double IntSpanMinForEachSelector() - // { - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // int Min = int.MinValue; - // foreach (int i in asSpan) - // { - // int l = MinInts(i); - // if (Min > l) - // { - // Min = l; - // } - // } - - // return Min; - // } - - // [Benchmark] - // public double IntSpanMinFastSelector() - // { - // int[] localArray = intArray; - // Span asSpan = localArray.AsSpan(); - // return asSpan.MinF(MinInts); - // } - - // [Benchmark] - // public double IntListMinLinqSelector() - // { - // return intList.Min(MinInts); - // } - - // [Benchmark] - // public double IntListMinFastSelector() - // { - // return intList.MinF(MinInts); - // } - - // [Benchmark] - // public double IntAsListReadOnlyMinLinqSelector() - // { - // return intList.AsReadOnly().Min(MinInts); - // } - - // [Benchmark] - // public double IntAsListReadOnlyMinFastSelector() - // { - // return intList.AsReadOnly().MinF(MinInts); - // } - - // [Benchmark] - // public double IntArrayAsReadOnlyMinLinqSelector() - // { - // return Array.AsReadOnly(intArray).Min(MinInts); - // } - - // [Benchmark] - // public double IntArrayAsReadOnlyMinFastSelector() - // { - // return Array.AsReadOnly(intArray).MinF(MinInts); - // } + private static readonly Func MinInts = (x) => x + 1; + + [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + public double IntArrayMinLinq() + { + return Benchmarks.intArray.Min(); + } + + [BenchmarkCategory("intArray"), Benchmark] + public double IntArrayMinFast() + { + return Benchmarks.intArray.MinF(); + } + + [BenchmarkCategory("intArray"), Benchmark] + public int IntArrayMinFastSIMD() + { + return Benchmarks.intArray.MinS(); + } + + [BenchmarkCategory("localArray.AsSpan"), Benchmark(Baseline = true)] + public double IntSpanMinForEach() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + int Min = int.MinValue; + foreach (int i in asSpan) + { + if (Min > i) + { + Min = i; + } + } + + return Min; + } + + [BenchmarkCategory("localArray.AsSpan"), Benchmark] + public double IntSpanMinFast() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.MinF(); + } + + [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + public double IntListMinLinq() + { + return Benchmarks.intList.Min(); + } + + [BenchmarkCategory("intList"), Benchmark] + public double IntListMinFast() + { + return Benchmarks.intList.MinF(); + } + + [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + public double IntAsListReadOnlyMinLinq() + { + return Benchmarks.intList.AsReadOnly().Min(); + } + + [BenchmarkCategory("Array.AsReadOnly"), Benchmark] + public double IntAsListReadOnlyMinFast() + { + return Benchmarks.intList.AsReadOnly().MinF(); + } + + [BenchmarkCategory("Array.AsReadOnly"), Benchmark(Baseline = true)] + public double IntArrayAsReadOnlyMinLinq() + { + return Array.AsReadOnly(Benchmarks.intArray).Min(); + } + + [BenchmarkCategory("intArraySelector"), Benchmark] + public double IntArrayAsReadOnlyMinFast() + { + return Array.AsReadOnly(Benchmarks.intArray).MinF(); + } + + + [BenchmarkCategory("intArraySelector"), Benchmark(Baseline = true)] + public double IntArrayMinLinqSelector() + { + return Benchmarks.intArray.Min(MinInts); + } + + [BenchmarkCategory("IntArrayAggregate"), Benchmark] + public double IntArrayMinFastSelector() + { + return Benchmarks.intArray.MinF(MinInts); + } + + [BenchmarkCategory("localArray.AsSpanSelector"), Benchmark(Baseline = true)] + public double IntSpanMinForEachSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + int Min = int.MinValue; + foreach (int i in asSpan) + { + int l = MinInts(i); + if (Min > l) + { + Min = l; + } + } + + return Min; + } + + [BenchmarkCategory("localArray.AsSpanSelector"), Benchmark] + public double IntSpanMinFastSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.MinF(MinInts); + } + + [BenchmarkCategory("intListSelector"), Benchmark(Baseline = true)] + public double IntListMinLinqSelector() + { + return Benchmarks.intList.Min(MinInts); + } + + [BenchmarkCategory("intListSelector"), Benchmark] + public double IntListMinFastSelector() + { + return Benchmarks.intList.MinF(MinInts); + } + + [BenchmarkCategory("intList.AsReadOnlySelector"), Benchmark(Baseline = true)] + public double IntAsListReadOnlyMinLinqSelector() + { + return Benchmarks.intList.AsReadOnly().Min(MinInts); + } + + [BenchmarkCategory("intList.AsReadOnlySelector"), Benchmark] + public double IntAsListReadOnlyMinFastSelector() + { + return Benchmarks.intList.AsReadOnly().MinF(MinInts); + } + + [BenchmarkCategory("Array.AsReadOnlySelector"), Benchmark(Baseline = true)] + public double IntArrayAsReadOnlyMinLinqSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).Min(MinInts); + } + + [BenchmarkCategory("Array.AsReadOnlySelector"), Benchmark] + public double IntArrayAsReadOnlyMinFastSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).MinF(MinInts); + } } } diff --git a/Benchmarks/BenchmarksRepeat.cs b/Benchmarks/BenchmarksRepeat.cs new file mode 100644 index 0000000..245d8bd --- /dev/null +++ b/Benchmarks/BenchmarksRepeat.cs @@ -0,0 +1,38 @@ +using System.Linq; + +using BenchmarkDotNet.Attributes; + +using JM.LinqFaster; +using JM.LinqFaster.SIMD; + +namespace Tests +{ + internal class BenchmarksRepeat + { + + [Benchmark(Baseline = true)] + public int[] IntArrayRepeatLinq() + { + return Enumerable.Repeat(5, Benchmarks.TEST_SIZE).ToArray(); + } + + [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + public int[] IntArrayRepeatFast() + { + return LinqFaster.RepeatArrayF(5, Benchmarks.TEST_SIZE); + } + + + [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + public int[] IntArrayRepeatFastSIMD() + { + return LinqFasterSIMD.RepeatS(5, Benchmarks.TEST_SIZE); + } + + //[BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + //public int[] IntArrayRepeatFastSIMDB() + //{ + // return LinqFasterSIMD.RepeatSB(5, Benchmarks.TEST_SIZE); + //} + } +} diff --git a/Benchmarks/BenchmarksWhereAggregate.cs b/Benchmarks/BenchmarksWhereAggregate.cs new file mode 100644 index 0000000..6db849f --- /dev/null +++ b/Benchmarks/BenchmarksWhereAggregate.cs @@ -0,0 +1,29 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksWhereAggregate + { + private static readonly Func mulXInts = (acc, x) => acc += x * x; + + + [BenchmarkCategory("intArray.WhereAggregateSelect"), Benchmark(Baseline = true)] + public double IntArrayWhereAggregateLinq() + { + return Benchmarks.intArray.Where(x => x % 2 == 0).Aggregate(0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); + } + + [BenchmarkCategory("intArray.WhereAggregateSelect"), Benchmark(Baseline = true)] + public double IntArrayWhereAggregateFast() + { + return Benchmarks.intArray.WhereAggregateF(x => x % 2 == 0, 0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); + } + } +} diff --git a/Benchmarks/Config.cs b/Benchmarks/Config.cs new file mode 100644 index 0000000..b747f9c --- /dev/null +++ b/Benchmarks/Config.cs @@ -0,0 +1,26 @@ +using System; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Toolchains; +using BenchmarkDotNet.Toolchains.CsProj; + +namespace Benchmarks +{ + internal class Config : ManualConfig + { + public Config() + { + KeepBenchmarkFiles = true; + + //Add(Job.Default.With(CsProjClassicNetToolchain.Net472)); + Add(Job.Default.With(CsProjClassicNetToolchain.From("net48"))); + //Add(Job.Default.With(CsProjCoreToolchain.Current.Value)); + + //var toolchain = CsProjCoreToolchain.Current.Value; + //var jobWithCustomConfiguration = Job.Dry.WithCustomBuildConfiguration("CUSTOM").With(toolchain); + //Add(jobWithCustomConfiguration); + + } + } +} diff --git a/LinqFaster/AverageIList.cs b/LinqFaster/AverageIList.cs index 8796056..c0cb1fb 100644 --- a/LinqFaster/AverageIList.cs +++ b/LinqFaster/AverageIList.cs @@ -61,7 +61,7 @@ public static double AverageF(this IReadOnlyList source) { return 0; } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -76,7 +76,7 @@ public static double AverageF(this IReadOnlyList source) { return 0; } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -91,7 +91,7 @@ public static double AverageF(this IReadOnlyList source) { return 0; } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -106,7 +106,7 @@ public static double AverageF(this IReadOnlyList source) { return 0; } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -121,7 +121,7 @@ public static double AverageF(this IReadOnlyList source) { return 0; } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -136,7 +136,7 @@ public static double AverageF(this IReadOnlyList source) { return 0; } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -151,7 +151,7 @@ public static double AverageF(this IReadOnlyList source) { return 0; } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -166,7 +166,7 @@ public static double AverageF(this IReadOnlyList source) { return 0; } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } @@ -182,7 +182,7 @@ public static float AverageF(this IReadOnlyList source) { return 0; } - return SumF(source) / (float)source.Count; + return source.SumF() / (float)source.Count; } /// @@ -230,7 +230,7 @@ public static decimal AverageF(this IReadOnlyList source, Func return 0; } - return SumF(source, selector) / source.Count; + return source.SumF(selector) / source.Count; } #region Nullable types @@ -246,7 +246,7 @@ public static decimal AverageF(this IReadOnlyList source, Func { return new double?(); } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -261,7 +261,7 @@ public static decimal AverageF(this IReadOnlyList source, Func { return new double?(); } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -276,7 +276,7 @@ public static decimal AverageF(this IReadOnlyList source, Func { return new double?(); } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -291,7 +291,7 @@ public static decimal AverageF(this IReadOnlyList source, Func { return new double?(); } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -306,7 +306,7 @@ public static decimal AverageF(this IReadOnlyList source, Func { return new double?(); } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -321,7 +321,7 @@ public static decimal AverageF(this IReadOnlyList source, Func { return new double?(); } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -336,7 +336,7 @@ public static decimal AverageF(this IReadOnlyList source, Func { return new double?(); } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// @@ -351,7 +351,7 @@ public static decimal AverageF(this IReadOnlyList source, Func { return new double?(); } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } @@ -367,7 +367,7 @@ public static decimal AverageF(this IReadOnlyList source, Func { return new double?(); } - return (double)SumF(source) / source.Count; + return (double)source.SumF() / source.Count; } /// diff --git a/LinqFaster/LinqFaster.csproj b/LinqFaster/LinqFaster.csproj index ab850b7..56f6c2d 100644 --- a/LinqFaster/LinqFaster.csproj +++ b/LinqFaster/LinqFaster.csproj @@ -1,11 +1,11 @@  - netstandard2.0;net461 - 1.1.0 + netstandard2.0;net461;net48 + 1.1.1 Jack Mott - - High performance Linq-style extension methods for arrays and lists. + Jack Mott + High performance Linq-style extension methods for arrays and lists. Copyright 2017 (c) Jack Mott. All rights reserved. https://github.com/jackmott/LinqFaster https://github.com/jackmott/LinqFaster diff --git a/LinqFasterParallel/LinqFasterParallel.csproj b/LinqFasterParallel/LinqFasterParallel.csproj index 2b9c418..e56afde 100644 --- a/LinqFasterParallel/LinqFasterParallel.csproj +++ b/LinqFasterParallel/LinqFasterParallel.csproj @@ -1,9 +1,9 @@  - netstandard1.3;netstandard2.0;net461 + netstandard1.3;netstandard2.0;net461;net48 LinqFaster.Parallel - 1.0.1 + 1.0.2 Jack Mott Jack Mott LinqFaster Parallel diff --git a/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj b/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj index 84b8b76..a4cbe6f 100644 --- a/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj +++ b/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj @@ -1,11 +1,11 @@  - netstandard1.3;netstandard2.0;net461 - 1.0.1 + netstandard1.3;netstandard2.0;net461;net48 + 1.0.2 Jack Mott - - High performance Linq-style extension methods that are multithreaded and use System.Numerics SIMD for arrays and lists. + Jack Mott + High performance Linq-style extension methods that are multithreaded and use System.Numerics SIMD for arrays and lists. Copyright 2017 (c) Jack Mott. All rights reserved. https://github.com/jackmott/LinqFaster https://github.com/jackmott/LinqFaster diff --git a/LinqFasterSIMD/LinqFasterSIMD.csproj b/LinqFasterSIMD/LinqFasterSIMD.csproj index b2d4f36..2d49e84 100644 --- a/LinqFasterSIMD/LinqFasterSIMD.csproj +++ b/LinqFasterSIMD/LinqFasterSIMD.csproj @@ -1,11 +1,11 @@  - netstandard2.0 + netstandard2.0;net461;net48 1.0.2 Jack Mott - - High performance Linq-style extension methods that use System.Numerics SIMD for arrays. + Jack Mott + High performance Linq-style extension methods that use System.Numerics SIMD for arrays. Copyright 2017 (c) Jack Mott. All rights reserved. https://github.com/jackmott/LinqFaster https://github.com/jackmott/LinqFaster diff --git a/Tests/ParallelSIMDTests/SelectSIMDP.cs b/Tests/ParallelSIMDTests/SelectSIMDP.cs index e495ba2..0e4ed62 100644 --- a/Tests/ParallelSIMDTests/SelectSIMDP.cs +++ b/Tests/ParallelSIMDTests/SelectSIMDP.cs @@ -1,27 +1,29 @@ using System.Collections.Generic; -using NUnit.Framework; -using JM.LinqFaster.SIMD.Parallel; using System.Linq; +using JM.LinqFaster.SIMD.Parallel; + +using NUnit.Framework; + namespace Tests { [TestFixture] - class SelectSIMDPTests + internal class SelectSIMDPTests { [Test] - public void SelectSIMDP() + public void SelectSIMDP() { - int[] a = Test.intArray.SelectSP(x => x * x, x => x*x); + int[] a = Test.intArray.SelectSP(x => x * x, x => x * x); IEnumerable b = Test.intArray.Select(x => x * x); Assert.That(a, Is.EqualTo(b)); - -// Assert.That(c, Is.EqualTo(d)); - - // Assert.That(e, Is.EqualTo(f)); + // Assert.That(c, Is.EqualTo(d)); + + + // Assert.That(e, Is.EqualTo(f)); } - + } } diff --git a/Tests/SIMDTests/AverageSIMDTests.cs b/Tests/SIMDTests/AverageSIMDTests.cs index e8323b2..50575b2 100644 --- a/Tests/SIMDTests/AverageSIMDTests.cs +++ b/Tests/SIMDTests/AverageSIMDTests.cs @@ -1,13 +1,15 @@ -using NUnit.Framework; -using JM.LinqFaster.SIMD; +using System; using System.Linq; -using System; using System.Numerics; +using JM.LinqFaster.SIMD; + +using NUnit.Framework; + namespace Tests { [TestFixture] - class AverageSIMDTests + internal class AverageSIMDTests { [Test] diff --git a/Tests/SIMDTests/SelectSIMDTests.cs b/Tests/SIMDTests/SelectSIMDTests.cs index 326e73c..26359b5 100644 --- a/Tests/SIMDTests/SelectSIMDTests.cs +++ b/Tests/SIMDTests/SelectSIMDTests.cs @@ -1,11 +1,13 @@ -using NUnit.Framework; +using System.Linq; + using JM.LinqFaster.SIMD; -using System.Linq; + +using NUnit.Framework; namespace Tests { [TestFixture] - class SelectSIMDTests + internal class SelectSIMDTests { [Test] @@ -17,7 +19,7 @@ public void SelectSIMD() Assert.That(a, Is.EqualTo(b)); } - - + + } } \ No newline at end of file diff --git a/Tests/SIMDTests/SumSIMDTests.cs b/Tests/SIMDTests/SumSIMDTests.cs index 40b07bb..ddef5c2 100644 --- a/Tests/SIMDTests/SumSIMDTests.cs +++ b/Tests/SIMDTests/SumSIMDTests.cs @@ -1,12 +1,14 @@ -using NUnit.Framework; -using JM.LinqFaster.SIMD; +using System; using System.Linq; -using System; + +using JM.LinqFaster.SIMD; + +using NUnit.Framework; namespace Tests { [TestFixture] - class SumSIMDTests + internal class SumSIMDTests { [Test] From 9c9dd9d4e33afbfed52e7ca26b6586b91ba83350 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Wed, 7 Aug 2019 15:45:11 +0100 Subject: [PATCH 22/30] Investigate #25: [Enhancement] Please also target .net4.8 and Benchmark - Attempt to sort why Appveyor is unhappy. - Sort out the ratio detection code when all are put back in. --- Benchmarks/BenchmarkOrderBy.cs | 7 +- Benchmarks/BenchmarkSelect.cs | 7 +- Benchmarks/BenchmarkSequenceEqual.cs | 11 +-- Benchmarks/BenchmarkSum.cs | 2 +- Benchmarks/Benchmarks.csproj | 94 -------------------------- Benchmarks/BenchmarksMax.cs | 4 +- Benchmarks/BenchmarksRepeat.cs | 12 ++-- Benchmarks/BenchmarksWhereAggregate.cs | 2 +- 8 files changed, 24 insertions(+), 115 deletions(-) diff --git a/Benchmarks/BenchmarkOrderBy.cs b/Benchmarks/BenchmarkOrderBy.cs index 35b0106..c7a095b 100644 --- a/Benchmarks/BenchmarkOrderBy.cs +++ b/Benchmarks/BenchmarkOrderBy.cs @@ -2,23 +2,24 @@ using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; namespace Tests { - //[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class BenchmarkOrderBy { private static readonly Func orderBy = (x) => x - 1; - [Benchmark(Baseline = true)] + [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] public int IntArrayOrderByLinq() { return Benchmarks.intArray.OrderBy(orderBy).Sum(); } - [Benchmark] + [BenchmarkCategory("intArray"), Benchmark] public int IntArrayOrderByFast() { return Benchmarks.intArray.OrderByF(orderBy).Sum(); diff --git a/Benchmarks/BenchmarkSelect.cs b/Benchmarks/BenchmarkSelect.cs index eba9a92..9cc8892 100644 --- a/Benchmarks/BenchmarkSelect.cs +++ b/Benchmarks/BenchmarkSelect.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; @@ -13,9 +12,9 @@ namespace Tests public class BenchmarkSelect { [BenchmarkCategory("intArray.Select"), Benchmark(Baseline = true)] - public IEnumerable IntArraySelectLinq() + public int[] IntArraySelectLinq() { - return Benchmarks.intArray.Select(x => x * x); + return Benchmarks.intArray.Select(x => x * x).ToArray(); } [BenchmarkCategory("intArray.Select"), Benchmark] diff --git a/Benchmarks/BenchmarkSequenceEqual.cs b/Benchmarks/BenchmarkSequenceEqual.cs index 590a0fe..126ce59 100644 --- a/Benchmarks/BenchmarkSequenceEqual.cs +++ b/Benchmarks/BenchmarkSequenceEqual.cs @@ -2,6 +2,7 @@ using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; using JM.LinqFaster.Parallel; @@ -10,7 +11,7 @@ namespace Tests { - //[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class BenchmarkSequenceEqual { [Benchmark(Baseline = true)] @@ -19,26 +20,26 @@ public bool IntArraySequenceEqual() return Benchmarks.intArray.SequenceEqual(Benchmarks.array2); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("intArray"), Benchmark] public bool IntArraySequenceEqualF() { return Benchmarks.intArray.SequenceEqualF(Benchmarks.array2); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("intArray"), Benchmark] public bool IntArraySequenceEqualP() { return Benchmarks.intArray.SequenceEqualP(Benchmarks.array2); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("intArray"), Benchmark] public bool IntArraySequenceEqualS() { return Benchmarks.intArray.SequenceEqualS(Benchmarks.array2); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("intArray"), Benchmark] public bool IntArraySequenceEqualSP() { return Benchmarks.intArray.SequenceEqualSP(Benchmarks.array2); diff --git a/Benchmarks/BenchmarkSum.cs b/Benchmarks/BenchmarkSum.cs index a71281e..f9b3b2c 100644 --- a/Benchmarks/BenchmarkSum.cs +++ b/Benchmarks/BenchmarkSum.cs @@ -96,7 +96,7 @@ public int IntArraySumLinqSelect() return Benchmarks.intArray.Sum(sumDivide); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("IntArrayAggregate"), Benchmark] public int IntArraySumFastSelect() { return Benchmarks.intArray.SumF(sumDivide); diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 975c5a0..52758ab 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -64,82 +64,19 @@ ..\packages\Microsoft.Win32.Registry.4.5.0\lib\net461\Microsoft.Win32.Registry.dll - - ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll - True - True - ..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll - - - ..\packages\System.Console.4.3.1\lib\net46\System.Console.dll - True - True - - - ..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll - True - True - - - ..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll - True - True - - - ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll - True - True - - - ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll - True - True - - - ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll - True - True - - - ..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll ..\packages\System.Reflection.TypeExtensions.4.5.1\lib\net461\System.Reflection.TypeExtensions.dll - - ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll - True - True - ..\packages\System.Security.AccessControl.4.5.0\lib\net461\System.Security.AccessControl.dll - - ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll - True - True - - - ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll - True - True - - - ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll - True - True - - - ..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll - True - True - ..\packages\System.Security.Principal.Windows.4.5.1\lib\net461\System.Security.Principal.Windows.dll @@ -149,40 +86,9 @@ ..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll - - ..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll - True - True - ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll - - - - - - - - ..\packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll - True - True - - - ..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll - True - True - - - ..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll - True - True - - - ..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll - True - True - ..\packages\System.Xml.XPath.XmlDocument.4.3.0\lib\net46\System.Xml.XPath.XmlDocument.dll diff --git a/Benchmarks/BenchmarksMax.cs b/Benchmarks/BenchmarksMax.cs index 10bec5e..2f6ed3b 100644 --- a/Benchmarks/BenchmarksMax.cs +++ b/Benchmarks/BenchmarksMax.cs @@ -125,13 +125,13 @@ public double IntSpanMaxFastSelector() return asSpan.MaxF(MaxInts); } - [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + [BenchmarkCategory("intListSelect"), Benchmark(Baseline = true)] public double IntListMaxLinqSelector() { return Benchmarks.intList.Max(MaxInts); } - [BenchmarkCategory("intList"), Benchmark] + [BenchmarkCategory("intListSelect"), Benchmark] public double IntListMaxFastSelector() { return Benchmarks.intList.MaxF(MaxInts); diff --git a/Benchmarks/BenchmarksRepeat.cs b/Benchmarks/BenchmarksRepeat.cs index 245d8bd..c9b8999 100644 --- a/Benchmarks/BenchmarksRepeat.cs +++ b/Benchmarks/BenchmarksRepeat.cs @@ -1,35 +1,37 @@ using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; using JM.LinqFaster; using JM.LinqFaster.SIMD; namespace Tests { - internal class BenchmarksRepeat + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksRepeat { - [Benchmark(Baseline = true)] + [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] public int[] IntArrayRepeatLinq() { return Enumerable.Repeat(5, Benchmarks.TEST_SIZE).ToArray(); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("intArray"), Benchmark] public int[] IntArrayRepeatFast() { return LinqFaster.RepeatArrayF(5, Benchmarks.TEST_SIZE); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("intArray"), Benchmark] public int[] IntArrayRepeatFastSIMD() { return LinqFasterSIMD.RepeatS(5, Benchmarks.TEST_SIZE); } - //[BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + //[BenchmarkCategory("intArray"), Benchmark] //public int[] IntArrayRepeatFastSIMDB() //{ // return LinqFasterSIMD.RepeatSB(5, Benchmarks.TEST_SIZE); diff --git a/Benchmarks/BenchmarksWhereAggregate.cs b/Benchmarks/BenchmarksWhereAggregate.cs index 6db849f..8ebb2e6 100644 --- a/Benchmarks/BenchmarksWhereAggregate.cs +++ b/Benchmarks/BenchmarksWhereAggregate.cs @@ -20,7 +20,7 @@ public double IntArrayWhereAggregateLinq() return Benchmarks.intArray.Where(x => x % 2 == 0).Aggregate(0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); } - [BenchmarkCategory("intArray.WhereAggregateSelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("intArray.WhereAggregateSelect"), Benchmark] public double IntArrayWhereAggregateFast() { return Benchmarks.intArray.WhereAggregateF(x => x % 2 == 0, 0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); From fb43c8c7025a61e56d16d7d6769e3a8a588492fd Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Thu, 8 Aug 2019 10:39:01 +0100 Subject: [PATCH 23/30] Investigate #21: [Bug] Span SumF is slower than a for loop over a span Create #22: [Question] Span_FirstF and List_FirstF are slower than just calling foreach -> Why? Span this #24: [Enhancement] DefaultIfEmptyF should be implemented Add Span #25: [Enhancement] Please also target .net4.8 and Benchmark --- Benchmarks/BenchmarkAggregate.cs | 1 + Benchmarks/BenchmarkFirst.cs | 1 + Benchmarks/BenchmarkLast.cs | 1 + Benchmarks/BenchmarkSum.cs | 1 + Benchmarks/BenchmarkWhereSum.cs | 1 + Benchmarks/Benchmarks.csproj | 4 + Benchmarks/BenchmarksMax.cs | 1 + Benchmarks/BenchmarksMin.cs | 1 + Benchmarks/Config.cs | 5 +- BenchmarksCore/BenchmarksCore.csproj | 19 + BenchmarksCore/Program.cs | 252 --- LinqFaster.sln | 8 +- LinqFaster/Aggregate.cs | 213 -- LinqFaster/AnyAll.cs | 76 +- LinqFaster/Contains.cs | 36 +- LinqFaster/Count.cs | 39 +- LinqFaster/Distinct.cs | 3 + LinqFaster/First.cs | 209 +- LinqFaster/Last.cs | 207 +- LinqFaster/LinqFaster.csproj | 51 +- LinqFaster/Reverse.cs | 25 - LinqFaster/Select.cs | 102 - LinqFaster/SelectMany.cs | 64 +- LinqFaster/SelectWhere.cs | 73 +- LinqFaster/SequenceEqual.cs | 163 +- LinqFaster/Single.cs | 136 +- LinqFaster/Skip.cs | 65 +- LinqFaster/Take.cs | 96 +- LinqFaster/Where.cs | 67 - LinqFaster/WhereAggregate.cs | 172 +- LinqFaster/WhereSelect.cs | 82 - LinqFaster/Zip.cs | 45 - LinqFasterParallel/LinqFasterParallel.csproj | 1 + .../LinqFasterParallelSIMD.csproj | 1 + LinqFasterSIMD/LinqFasterSIMD.csproj | 1 + LinqFasterSpan/Aggregate.cs | 233 +++ LinqFasterSpan/AnyAll.cs | 85 + {LinqFaster => LinqFasterSpan}/AverageSpan.cs | 4 +- LinqFasterSpan/Contains.cs | 46 + LinqFasterSpan/Count.cs | 48 + LinqFasterSpan/DefaultIfEmpty.cs | 37 + LinqFasterSpan/First.cs | 219 +++ LinqFasterSpan/Last.cs | 221 +++ LinqFasterSpan/LinqFasterSpan.csproj | 41 + {LinqFaster => LinqFasterSpan}/MaxSpan.cs | 4 +- {LinqFaster => LinqFasterSpan}/MinSpan.cs | 4 +- LinqFasterSpan/Reverse.cs | 35 + LinqFasterSpan/Select.cs | 113 ++ LinqFasterSpan/SelectMany.cs | 73 + LinqFasterSpan/SelectWhere.cs | 84 + LinqFasterSpan/SequenceEqual.cs | 123 ++ LinqFasterSpan/Single.cs | 145 ++ LinqFasterSpan/Skip.cs | 72 + {LinqFaster => LinqFasterSpan}/SumSpan.cs | 6 +- LinqFasterSpan/Take.cs | 103 + LinqFasterSpan/Where.cs | 78 + LinqFasterSpan/WhereAggregate.cs | 176 ++ LinqFasterSpan/WhereSelect.cs | 92 + .../WhereSumSpan.cs | 4 +- LinqFasterSpan/Zip.cs | 54 + LinqFasterSpan/readme.txt | 21 + Tests/AggregateTests.cs | 4 + Tests/AnyAllTests.cs | 23 +- Tests/ContainsTests.cs | 28 +- Tests/CountTests.cs | 20 +- Tests/DistinctTests.cs | 5 +- Tests/FirstTests.cs | 30 +- Tests/LastTests.cs | 30 +- Tests/MaxTests.cs | 21 +- Tests/OrderByTests.cs | 41 +- Tests/RangeTests.cs | 8 +- Tests/RepeatTests.cs | 7 +- Tests/ReverseTests.cs | 21 +- Tests/SelectManyTests.cs | 13 +- Tests/SelectTEsts.cs | 11 +- Tests/SelectWhereTests.cs | 16 +- Tests/SequenceEqualsTests.cs | 33 +- Tests/SingleTests.cs | 68 +- Tests/SkipTests.cs | 24 +- Tests/TakeTests.cs | 27 +- Tests/Test.cs | 9 +- Tests/Tests.csproj | 4 + Tests/WhereAggregateTests.cs | 28 +- Tests/WhereSelectTests.cs | 32 +- Tests/WhereSumTEsts.cs | 27 +- Tests/WhereTests.cs | 15 +- docs/LinqFasterSpan.xml | 1497 +++++++++++++++ docs/linqfaster.xml | 1708 ++--------------- 88 files changed, 4198 insertions(+), 3895 deletions(-) delete mode 100644 BenchmarksCore/Program.cs create mode 100644 LinqFasterSpan/Aggregate.cs create mode 100644 LinqFasterSpan/AnyAll.cs rename {LinqFaster => LinqFasterSpan}/AverageSpan.cs (99%) create mode 100644 LinqFasterSpan/Contains.cs create mode 100644 LinqFasterSpan/Count.cs create mode 100644 LinqFasterSpan/DefaultIfEmpty.cs create mode 100644 LinqFasterSpan/First.cs create mode 100644 LinqFasterSpan/Last.cs create mode 100644 LinqFasterSpan/LinqFasterSpan.csproj rename {LinqFaster => LinqFasterSpan}/MaxSpan.cs (99%) rename {LinqFaster => LinqFasterSpan}/MinSpan.cs (99%) create mode 100644 LinqFasterSpan/Reverse.cs create mode 100644 LinqFasterSpan/Select.cs create mode 100644 LinqFasterSpan/SelectMany.cs create mode 100644 LinqFasterSpan/SelectWhere.cs create mode 100644 LinqFasterSpan/SequenceEqual.cs create mode 100644 LinqFasterSpan/Single.cs create mode 100644 LinqFasterSpan/Skip.cs rename {LinqFaster => LinqFasterSpan}/SumSpan.cs (99%) create mode 100644 LinqFasterSpan/Take.cs create mode 100644 LinqFasterSpan/Where.cs create mode 100644 LinqFasterSpan/WhereAggregate.cs create mode 100644 LinqFasterSpan/WhereSelect.cs rename {LinqFaster => LinqFasterSpan}/WhereSumSpan.cs (99%) create mode 100644 LinqFasterSpan/Zip.cs create mode 100644 LinqFasterSpan/readme.txt create mode 100644 docs/LinqFasterSpan.xml diff --git a/Benchmarks/BenchmarkAggregate.cs b/Benchmarks/BenchmarkAggregate.cs index 2a2f935..12da968 100644 --- a/Benchmarks/BenchmarkAggregate.cs +++ b/Benchmarks/BenchmarkAggregate.cs @@ -5,6 +5,7 @@ using BenchmarkDotNet.Configs; using JM.LinqFaster; +using JM.LinqFasterSpan; namespace Tests { diff --git a/Benchmarks/BenchmarkFirst.cs b/Benchmarks/BenchmarkFirst.cs index fc7cbe4..e1ca96f 100644 --- a/Benchmarks/BenchmarkFirst.cs +++ b/Benchmarks/BenchmarkFirst.cs @@ -5,6 +5,7 @@ using BenchmarkDotNet.Configs; using JM.LinqFaster; +using JM.LinqFasterSpan; namespace Tests { diff --git a/Benchmarks/BenchmarkLast.cs b/Benchmarks/BenchmarkLast.cs index eb67f4f..25d0e9c 100644 --- a/Benchmarks/BenchmarkLast.cs +++ b/Benchmarks/BenchmarkLast.cs @@ -5,6 +5,7 @@ using BenchmarkDotNet.Configs; using JM.LinqFaster; +using JM.LinqFasterSpan; namespace Tests { diff --git a/Benchmarks/BenchmarkSum.cs b/Benchmarks/BenchmarkSum.cs index f9b3b2c..f81d8b1 100644 --- a/Benchmarks/BenchmarkSum.cs +++ b/Benchmarks/BenchmarkSum.cs @@ -5,6 +5,7 @@ using BenchmarkDotNet.Configs; using JM.LinqFaster; +using JM.LinqFasterSpan; using JM.LinqFaster.SIMD; namespace Tests diff --git a/Benchmarks/BenchmarkWhereSum.cs b/Benchmarks/BenchmarkWhereSum.cs index 188c4b7..550dec4 100644 --- a/Benchmarks/BenchmarkWhereSum.cs +++ b/Benchmarks/BenchmarkWhereSum.cs @@ -5,6 +5,7 @@ using BenchmarkDotNet.Configs; using JM.LinqFaster; +using JM.LinqFasterSpan; namespace Tests { diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 52758ab..77dbde4 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -127,6 +127,10 @@ {050c43b5-4a4f-45d9-be0c-9b2a6acc189e} LinqFasterSIMD + + {68835792-9274-4ddc-8312-29700ef16f62} + LinqFasterSpan + {5b2f0f9f-6dda-4f06-a999-26e43ae04f86} LinqFaster diff --git a/Benchmarks/BenchmarksMax.cs b/Benchmarks/BenchmarksMax.cs index 2f6ed3b..1625cdc 100644 --- a/Benchmarks/BenchmarksMax.cs +++ b/Benchmarks/BenchmarksMax.cs @@ -5,6 +5,7 @@ using BenchmarkDotNet.Configs; using JM.LinqFaster; +using JM.LinqFasterSpan; namespace Tests { diff --git a/Benchmarks/BenchmarksMin.cs b/Benchmarks/BenchmarksMin.cs index 4f018c8..f6b84e0 100644 --- a/Benchmarks/BenchmarksMin.cs +++ b/Benchmarks/BenchmarksMin.cs @@ -6,6 +6,7 @@ using JM.LinqFaster; using JM.LinqFaster.SIMD; +using JM.LinqFasterSpan; namespace Tests { diff --git a/Benchmarks/Config.cs b/Benchmarks/Config.cs index b747f9c..6ed862b 100644 --- a/Benchmarks/Config.cs +++ b/Benchmarks/Config.cs @@ -1,8 +1,5 @@ -using System; -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Configs; using BenchmarkDotNet.Jobs; -using BenchmarkDotNet.Toolchains; using BenchmarkDotNet.Toolchains.CsProj; namespace Benchmarks diff --git a/BenchmarksCore/BenchmarksCore.csproj b/BenchmarksCore/BenchmarksCore.csproj index 398c9dd..cac2e16 100644 --- a/BenchmarksCore/BenchmarksCore.csproj +++ b/BenchmarksCore/BenchmarksCore.csproj @@ -13,6 +13,24 @@ true + + + + + + + + + + + + + + + + + + @@ -21,6 +39,7 @@ + diff --git a/BenchmarksCore/Program.cs b/BenchmarksCore/Program.cs deleted file mode 100644 index 3bae77b..0000000 --- a/BenchmarksCore/Program.cs +++ /dev/null @@ -1,252 +0,0 @@ -using System; -using BenchmarkDotNet; -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Running; -using JM.LinqFaster; -using JM.LinqFaster.Parallel; -using JM.LinqFaster.SIMD.Parallel; -using JM.LinqFaster.SIMD; - -using System.Linq; -using System.Collections.Generic; -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Jobs; -using BenchmarkDotNet.Reports; - -namespace Tests -{ - [MemoryDiagnoser] - public class Benchmarks - { - - const int LARGE_TEST_SIZE = 1000000; - const int SMALL_TEST_SIZE = 100; - - - - public List list; - public int[] array; - public int[] array2; - public float[] floatArray; - public string[] strarray; - - - [Params(1000000)] - public int TEST_SIZE { get; set; } - - public Benchmarks() - { - - - } - - [GlobalSetup] - public void Setup() - { - Random r = new Random(); - array = new int[TEST_SIZE]; - array2 = new int[TEST_SIZE]; - floatArray = new float[TEST_SIZE]; - list = new List(TEST_SIZE); - strarray = new string[TEST_SIZE]; - - for (int i = 0; i < TEST_SIZE; i++) - { - array[i] = r.Next(-100,100); - array2[i] = r.Next(-100,100); - list.Add(array[i]); - strarray[i] = array[i].ToString(); - floatArray[i] = array[i]; - } - array2[TEST_SIZE / 2] = 0; - } - - - /* - [Benchmark] - public int OrderByLinq() - { - return array.OrderBy((x => x -1)).Sum(); - } - - [Benchmark] - public int OrderByFast() - { - return array.OrderByF((x => x - 1)).Sum(); - } - - - - - [Benchmark] - public int SumLinq() - { - return array.Sum(); - } - - [Benchmark] - public int SumFast() - { - return array.SumF(); - } - - [Benchmark] - public int SumFastSIMD() - { - return array.SumS(); - } - - [Benchmark] - public double AverageLinq() - { - return array.Average(); - } - - [Benchmark] - public double AverageFast() - { - return array.AverageF(); - } - - [Benchmark] - public double AverageFastSIMD() - { - return array.AverageS(); - } - - [Benchmark] - public int SumWithSelectLinq() - { - return array.Sum(x => x / 2); - } - - [Benchmark] - public int SumWithSelectFast() - { - return array.SumF(x => x/2); - } - - - [Benchmark] - public double WhereAggregateLinq() - { - return array.Where(x => x % 2 == 0).Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / array.Length); - } - - [Benchmark] - public double WhereAggregateFast() - { - return array.WhereAggregateF(x => x % 2 == 0,0.0,(acc,x)=> acc += x*x,acc => acc/array.Length); - } - - [Benchmark] - public int[] SelectFast() - { - return array.SelectF(x => x * x); - } - - [Benchmark] - public int[] SelectFastSIMD() - { - return array.SelectS(x => x * x, x=>x*x); - } - - - - [Benchmark] - public int[] RepeatLinq() - { - return Enumerable.Repeat(5, TEST_SIZE).ToArray(); - } - - [Benchmark] - public int[] RepeastFast() - { - return LinqFaster.RepeatArrayF(5, TEST_SIZE); - } - - - [Benchmark] - public int[] RepeastFastSIMD() - { - return LinqFasterSIMD.RepeatS(5, TEST_SIZE); - } - - [Benchmark] - public int[] RepeastFastSIMDB() - { - return LinqFasterSIMD.RepeatSB(5, TEST_SIZE); - } - - [Benchmark] - public int MinLinq() - { - return array.Min(); - } - - [Benchmark] - public int MinFast() - { - return array.MinF(); - } - - [Benchmark] - public int MinFastSIMD() - { - return array.MinS(); - } - - [Benchmark] - public bool SequenceEqual() - { - return array.SequenceEqual(array2); - }*/ - - /* - [Benchmark] - public bool SequenceEqualP() - { - return array.SequenceEqualP(array2); - } - - [Benchmark] - public bool SequenceEqualS() - { - return array.SequenceEqualS(array2); - } - - [Benchmark] - public bool SequenceEqualSP() - { - return array.SequenceEqualSP(array2); - } - - */ - - [Benchmark] - public int MaxSIMD() - { - return array.MaxS(); - } - - - - - - public static void Main(string[] args) - { - int[] a = { 1, 2, 3, 4, 5, 6, 7, 8 }; - int[] b = { 1, 0, 4, 4, 6, 7, 2, 10 }; - int[] r = a.SequenceCompareS(b); - a.Slice(2, 4).SumF(); - foreach (int i in r) - { - Console.Write(i + ","); - } - - Summary summary = BenchmarkRunner.Run(ManualConfig.Create(DefaultConfig.Instance).With(Job.RyuJitX64)); - Console.ReadLine(); - } - - } -} diff --git a/LinqFaster.sln b/LinqFaster.sln index f0bf8b8..be44b89 100644 --- a/LinqFaster.sln +++ b/LinqFaster.sln @@ -21,7 +21,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{42DD1432-5209-49B3-81D7-B487A9DBF2F3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BenchmarksCore", "BenchmarksCore\BenchmarksCore.csproj", "{6F05ABE2-B763-47E3-B255-6A0F75A6CEDC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarksCore", "BenchmarksCore\BenchmarksCore.csproj", "{6F05ABE2-B763-47E3-B255-6A0F75A6CEDC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LinqFasterSpan", "LinqFasterSpan\LinqFasterSpan.csproj", "{68835792-9274-4DDC-8312-29700EF16F62}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -57,6 +59,10 @@ Global {6F05ABE2-B763-47E3-B255-6A0F75A6CEDC}.Debug|Any CPU.Build.0 = Debug|Any CPU {6F05ABE2-B763-47E3-B255-6A0F75A6CEDC}.Release|Any CPU.ActiveCfg = Release|Any CPU {6F05ABE2-B763-47E3-B255-6A0F75A6CEDC}.Release|Any CPU.Build.0 = Release|Any CPU + {68835792-9274-4DDC-8312-29700EF16F62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68835792-9274-4DDC-8312-29700EF16F62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68835792-9274-4DDC-8312-29700EF16F62}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68835792-9274-4DDC-8312-29700EF16F62}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/LinqFaster/Aggregate.cs b/LinqFaster/Aggregate.cs index 56360d4..511cab6 100644 --- a/LinqFaster/Aggregate.cs +++ b/LinqFaster/Aggregate.cs @@ -172,218 +172,5 @@ public static partial class LinqFaster return resultSelector(result); } - // ------------------------------ Spans -------------------------- - #region Normal Span - /// - /// Applies an accumulator function over a Span{T}. - /// - /// A Span{T} to aggregate over. - /// An accumulator function to be invoked on each element - /// The final accumulator value - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TSource AggregateF(this Span source, - Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull("func"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - TSource result = source[0]; - for (int i = 1; i < source.Length; i++) - { - result = func(result, source[i]); - } - return result; - } - - /// - /// Applies an accumulator function over a Span{T}. The specified seed - /// value is used as the initial accumulator value. - /// - /// A Span{T} to aggregate over. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element - /// The final accumulator value - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TAccumulate AggregateF(this Span source, TAccumulate seed, - Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull("func"); - } - - TAccumulate result = seed; - for (int index = 0; index < source.Length; index++) - { - result = func(result, source[index]); - } - - return result; - } - - /// - /// Applies an accumulator function over a Span{T}. The specified seed - /// value is used as the initial accumulator value, and the specified - /// function is used to select the result value. - /// - /// A Span{T} to aggregate over. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element - /// A function to transform the final accumulator value into the result value. - /// The transformed final accumulator value - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TResult AggregateF(this Span source, TAccumulate seed, - Func func, - Func resultSelector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull("func"); - } - - if (resultSelector == null) - { - throw Error.ArgumentNull("resultSelector"); - } - - TAccumulate result = seed; - for (int index = 0; index < source.Length; index++) - { - result = func(result, source[index]); - } - - return resultSelector(result); - } - #endregion Normal Span - - // ------------------------------ ReadOnlySpans -------------------------- - #region ReadOnlySpan - /// - /// Applies an accumulator function over a ReadOnlySpan{T}. - /// - /// A ReadOnlySpan{T} to aggregate over. - /// An accumulator function to be invoked on each element - /// The final accumulator value - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TSource AggregateF(this ReadOnlySpan source, - Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull("func"); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - TSource result = source[0]; - for (int i = 1; i < source.Length; i++) - { - result = func(result, source[i]); - } - return result; - } - - /// - /// Applies an accumulator function over a ReadOnlySpan{T}. The specified seed - /// value is used as the initial accumulator value. - /// - /// A ReadOnlySpan{T} to aggregate over. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element - /// The final accumulator value - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TAccumulate AggregateF(this ReadOnlySpan source, TAccumulate seed, - Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull("func"); - } - - TAccumulate result = seed; - for (int index = 0; index < source.Length; index++) - { - result = func(result, source[index]); - } - - return result; - } - - /// - /// Applies an accumulator function over a ReadOnlySpan{T}. The specified seed - /// value is used as the initial accumulator value, and the specified - /// function is used to select the result value. - /// - /// A ReadOnlySpan{T} to aggregate over. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element - /// A function to transform the final accumulator value into the result value. - /// The transformed final accumulator value - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TResult AggregateF(this ReadOnlySpan source, TAccumulate seed, - Func func, - Func resultSelector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull("func"); - } - - if (resultSelector == null) - { - throw Error.ArgumentNull("resultSelector"); - } - - TAccumulate result = seed; - for (int index = 0; index < source.Length; index++) - { - result = func(result, source[index]); - } - - return resultSelector(result); - } - #endregion ReadOnlySpan - - } } \ No newline at end of file diff --git a/LinqFaster/AnyAll.cs b/LinqFaster/AnyAll.cs index 75996e8..eb57d61 100644 --- a/LinqFaster/AnyAll.cs +++ b/LinqFaster/AnyAll.cs @@ -72,81 +72,7 @@ public static bool AllF(this TSource[] source, Predicate predi return Array.TrueForAll(source, predicate); } - // -------------------------- this SpanS -------------------------------------------- - - /// - /// Determines whether an array contains any elements - /// - /// The array to check for emptiness - /// true if the source array contains any elements, otherwise, false/ - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AnyF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - return source.Length > 0; - } - - - - /// - /// Determines whether any element of an array satisfies a condition. - /// - /// An array whose elements to apply the predicate to. - /// A function to test each element for a condition. - /// true if any elements in the source array pass the test in the specified predicate; otherwise, false. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AnyF(this Span source, Predicate predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - for (int i = 0; i < source.Length; i++) - { - if (predicate(source[i])) return true; - } - return false; - } - - - /// - /// Determines whether all elements of an array satisfy a condition. - /// - /// An array that contains the elements to apply the predicate to. - /// A function to test each element for a condition. - /// true if every element of the source array passes the test in the specified - /// predicate, or if the array is empty; otherwise, false - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AllF(this Span source, Predicate predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - for (int i = 0; i < source.Length; i++) - { - if (!predicate(source[i])) return false; - } - return true; - } - - - + // -------------------------- Lists -------------------------------------------- /// diff --git a/LinqFaster/Contains.cs b/LinqFaster/Contains.cs index d1e8d19..ba67c5d 100644 --- a/LinqFaster/Contains.cs +++ b/LinqFaster/Contains.cs @@ -40,41 +40,7 @@ public static bool ContainsF(this TSource[] source, TSource value, IEqu return false; } - // -------------------------- this SpanS -------------------------------------------- - - /// - /// Determines whether an array contains a specified element by using the - /// provided IEqualityComparer. - /// - /// An array in which to locate a value. - /// The value to locate. - /// An equality comparer to compare values. - /// true if the source sequence contains an element that has the specified value; otherwise, false. - public static bool ContainsF(this Span source, TSource value, IEqualityComparer comparer = null) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (comparer == null) - { - comparer = EqualityComparer.Default; - } - - - for (int i = 0; i < source.Length;i++) - { - if (comparer.Equals(source[i], value)) - { - return true; - } - } - - return false; - } - - + // -------------------------- Lists -------------------------------------------- /// diff --git a/LinqFaster/Count.cs b/LinqFaster/Count.cs index 8c6115f..1029c06 100644 --- a/LinqFaster/Count.cs +++ b/LinqFaster/Count.cs @@ -43,44 +43,7 @@ public static int CountF(this T[] source, Func predicate) return count; } - // -------------------------- this Spans -------------------------------------------- - - /// - /// Returns a number that represents how many elements in the specified - /// array satisfy a condition. - /// - /// An array that contains elements to be tested and counted. - /// A function to test each element for a condition. - /// A number that represents how many elements in the array satisfy the condition - /// in the predicate function. - public static int CountF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - int count = 0; - for (int i = 0; i < source.Length; i++) - { - checked - { - if (predicate(source[i])) - { - count++; - } - } - } - - return count; - } - - + // ------------------------------ Lists --------------------- /// diff --git a/LinqFaster/Distinct.cs b/LinqFaster/Distinct.cs index ca5892a..f4573e6 100644 --- a/LinqFaster/Distinct.cs +++ b/LinqFaster/Distinct.cs @@ -34,6 +34,9 @@ public static void DistinctInPlaceF(this List source, IEqualit eqComparer = EqualityComparer.Default; } + if (source.Count == 0) + return; + source.Sort(comparer); TSource oldV = source[0]; diff --git a/LinqFaster/First.cs b/LinqFaster/First.cs index 14ccc0e..e16e9d5 100644 --- a/LinqFaster/First.cs +++ b/LinqFaster/First.cs @@ -328,213 +328,6 @@ public static T FirstOrDefaultF(this List source, Predicate predicate) return default(T); } - // -------------------------- Span -------------------------------------------- - #region Normal Span - /// - /// Returns the first element of an Span. - /// - /// The Span to return the first element of. - /// The first element in the specified array. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - return source[0]; - } - - /// - /// Returns the first element in an Span that satisfies a specified condition. - /// - /// An Span to return an element from. - /// A function to test each element for a condition. - /// The first element that satisfies the condition. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstF(this Span source, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull(nameof(func)); - } - - int sourceCount = source.Length; - for (int i = 0; i < sourceCount; i++) - { - if (func(source[i])) - { - return source[i]; - } - } - - throw Error.NoMatch(); - } - - /// - /// Returns the first element of an Span, or a default value if the - /// array contains no elements. - /// - /// The Span to return the first element of. - /// default value if source is empty, otherwise, the first element - /// in source. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstOrDefaultF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (source.Length == 0) - { - return default(T); - } - return source[0]; - } - - /// - /// Returns the first element of the sequence that satisfies a condition or a - /// default value if no such element is found. - /// - /// An Span to return an element from. - /// A function to test each element for a condition. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstOrDefaultF(this Span source, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull(nameof(func)); - } - - foreach (T a in source) - { - if (func(a)) - { - return a; - } - } - - return default(T); - } - #endregion Normal Span - - #region ReadOnlySpan - /// - /// Returns the first element of an ReadOnlySpan. - /// - /// The ReadOnlySpan to return the first element of. - /// The first element in the specified array. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstF(this ReadOnlySpan source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - return source[0]; - } - - /// - /// Returns the first element in an ReadOnlySpan that satisfies a specified condition. - /// - /// An ReadOnlySpan to return an element from. - /// A function to test each element for a condition. - /// The first element that satisfies the condition. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstF(this ReadOnlySpan source, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull(nameof(func)); - } - - foreach (T a in source) - { - if (func(a)) - { - return a; - } - } - - throw Error.NoMatch(); - } - - /// - /// Returns the first element of an ReadOnlySpan, or a default value if the - /// array contains no elements. - /// - /// The ReadOnlySpan to return the first element of. - /// default value if source is empty, otherwise, the first element - /// in source. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstOrDefaultF(this ReadOnlySpan source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (source.Length == 0) - { - return default(T); - } - return source[0]; - } - - /// - /// Returns the first element of the sequence that satisfies a condition or a - /// default value if no such element is found. - /// - /// An ReadOnlySpan to return an element from. - /// A function to test each element for a condition. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T FirstOrDefaultF(this ReadOnlySpan source, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull(nameof(func)); - } - - foreach (T a in source) - { - if (func(a)) - { - return a; - } - } - - return default(T); - } - #endregion ReadOnlySpan - + } } diff --git a/LinqFaster/Last.cs b/LinqFaster/Last.cs index abe3632..7bf4b08 100644 --- a/LinqFaster/Last.cs +++ b/LinqFaster/Last.cs @@ -326,211 +326,6 @@ public static T LastOrDefaultF(this List source, Predicate predicate) return default(T); } - // -------------------------- Span -------------------------------------------- - #region Normal Span - /// - /// Returns the first element of an Span. - /// - /// The Span to return the first element of. - /// The first element in the specified array. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T LastF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - return source[source.Length - 1]; - } - - /// - /// Returns the first element in an Span that satisfies a specified condition. - /// - /// An Span to return an element from. - /// A function to test each element for a condition. - /// The first element that satisfies the condition. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T LastF(this Span source, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull(nameof(func)); - } - - for (int i = source.Length - 1; i >= 0; i--) - { - if (func(source[i])) - { - return source[i]; - } - } - - throw Error.NoMatch(); - } - - /// - /// Returns the first element of an Span, or a default value if the - /// array contains no elements. - /// - /// The Span to return the first element of. - /// default value if source is empty, otherwise, the first element - /// in source. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T LastOrDefaultF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (source.Length == 0) - { - return default(T); - } - return source[source.Length - 1]; - } - - /// - /// Returns the first element of the sequence that satisfies a condition or a - /// default value if no such element is found. - /// - /// An Span to return an element from. - /// A function to test each element for a condition. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T LastOrDefaultF(this Span source, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull(nameof(func)); - } - - for (int i = source.Length - 1; i >= 0; i--) - { - if (func(source[i])) - { - return source[i]; - } - } - - return default(T); - } - #endregion Normal Span - - #region ReadOnlySpan - /// - /// Returns the first element of an ReadOnlySpan. - /// - /// The ReadOnlySpan to return the first element of. - /// The first element in the specified array. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T LastF(this ReadOnlySpan source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (source.Length == 0) - { - throw Error.NoElements(); - } - return source[source.Length - 1]; - } - - /// - /// Returns the first element in an ReadOnlySpan that satisfies a specified condition. - /// - /// An ReadOnlySpan to return an element from. - /// A function to test each element for a condition. - /// The first element that satisfies the condition. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T LastF(this ReadOnlySpan source, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull(nameof(func)); - } - - for (int i = source.Length - 1; i >= 0; i--) - { - if (func(source[i])) - { - return source[i]; - } - } - - throw Error.NoMatch(); - } - - /// - /// Returns the first element of an ReadOnlySpan, or a default value if the - /// array contains no elements. - /// - /// The ReadOnlySpan to return the first element of. - /// default value if source is empty, otherwise, the first element - /// in source. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T LastOrDefaultF(this ReadOnlySpan source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (source.Length == 0) - { - return default(T); - } - return source[source.Length - 1]; - } - - /// - /// Returns the first element of the sequence that satisfies a condition or a - /// default value if no such element is found. - /// - /// An ReadOnlySpan to return an element from. - /// A function to test each element for a condition. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T LastOrDefaultF(this ReadOnlySpan source, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull(nameof(func)); - } - - for (int i = source.Length - 1; i >= 0; i--) - { - if (func(source[i])) - { - return source[i]; - } - } - - return default(T); - } - #endregion ReadOnlySpan + } } diff --git a/LinqFaster/LinqFaster.csproj b/LinqFaster/LinqFaster.csproj index 56f6c2d..6c39a82 100644 --- a/LinqFaster/LinqFaster.csproj +++ b/LinqFaster/LinqFaster.csproj @@ -1,32 +1,31 @@  - - netstandard2.0;net461;net48 - 1.1.1 - Jack Mott - Jack Mott - High performance Linq-style extension methods for arrays and lists. - Copyright 2017 (c) Jack Mott. All rights reserved. - https://github.com/jackmott/LinqFaster - https://github.com/jackmott/LinqFaster - https://jackmott.github.io/images/LinqFaster.png - Github - performance linq - Added Span<T> support, improved performance of Take functions. - - JM.LinqFaster - JM.LinqFaster - - + + netstandard2.0;net461;net48 + 1.1.1 + Jack Mott + Jack Mott + High performance Linq-style extension methods for arrays and lists. + Copyright 2017 (c) Jack Mott. All rights reserved. + https://github.com/jackmott/LinqFaster + https://github.com/jackmott/LinqFaster + https://jackmott.github.io/images/LinqFaster.png + Github + performance linq + improved performance of Array and List functions. + + JM.LinqFaster + JM.LinqFaster + - - ..\docs\linqfaster.xml - True - true - + + ..\docs\LinqFaster.xml + True + true + - - - + + + \ No newline at end of file diff --git a/LinqFaster/Reverse.cs b/LinqFaster/Reverse.cs index 310c931..8d07de2 100644 --- a/LinqFaster/Reverse.cs +++ b/LinqFaster/Reverse.cs @@ -34,31 +34,6 @@ public static void ReverseInPlaceF(this T[] source) } - - /// - /// Inverts the order of the elements in a sequence. - /// - /// A sequence of values to reverse. - /// A sequence whose elements correspond to those of the input sequence in reverse order. - public static T[] ReverseF(this Span source) - { - T[] result = new T[source.Length]; - int lenLessOne = source.Length - 1; - for (int i = 0; i < result.Length; i++) - { - result[i] = source[lenLessOne - i]; - } - return result; - } - /// - /// Inverts the order of the elements in a sequence in place. - /// - /// A sequence of values to reverse. - public static void ReverseInPlaceF(this Span source) - { - source.Reverse(); - } - /// /// Inverts the order of the elements in a sequence. /// diff --git a/LinqFaster/Select.cs b/LinqFaster/Select.cs index 6fce614..1c94ad6 100644 --- a/LinqFaster/Select.cs +++ b/LinqFaster/Select.cs @@ -109,108 +109,6 @@ public static void SelectInPlaceF(this T[] source, Func selector) return r; } - // -------------------------- this SpanS -------------------------------------------- - - /// - /// Projects each element of a sequence into a new form in place. - /// - /// A sequence of values to invoke a transform function on (map). - /// A transform function to apply (map) to each element. - public static void SelectInPlaceF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - for (int i = 0; i < source.Length; i++) - { - source[i] = selector(source[i]); - } - } - - /// - /// Projects each element of a sequence into a new form, in place, by incorporating the element's index. - /// - /// A sequence of values to invoke a transform function on. - /// A transform function to apply to each source element; the second parameter of the function represents the index of the source element. - public static void SelectInPlaceF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - for (int i = 0; i < source.Length; i++) - { - source[i] = selector(source[i], i); - } - } - - - /// - /// Projects each element of a sequence into a new form. (map in every other language) - /// - /// A sequence of values to invoke a transform function on (map). - /// A transform function to apply (map) to each element. - /// A sequence whose elements are the result of invoking the transform function on each element (mapping) of source. - public static TResult[] SelectF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - TResult[] r = new TResult[source.Length]; - for (int i = 0; i < source.Length; i++) - { - r[i] = selector(source[i]); - } - return r; - } - - - - /// - /// Projects each element of a sequence into a new form by incorporating the element's index. - /// - /// A sequence of values to invoke a transform function on. - /// A transform function to apply to each source element; the second parameter of the function represents the index of the source element. - /// A sequence whose elements are the result of invoking the transform function on each element of source. - public static TResult[] SelectF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - TResult[] r = new TResult[source.Length]; - for (int i = 0; i < source.Length; i++) - { - r[i] = selector(source[i], i); - } - return r; - } - // -------------------------- LISTS -------------------------------------------- /// diff --git a/LinqFaster/SelectMany.cs b/LinqFaster/SelectMany.cs index 6ec71a1..7ae45ed 100644 --- a/LinqFaster/SelectMany.cs +++ b/LinqFaster/SelectMany.cs @@ -69,69 +69,7 @@ public static partial class LinqFaster return result.ToArray(); } - // -------------------------- this Spans -------------------------------------------- - - /// - /// Projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence. - /// Yo dawg, I heard you like sequences. - /// - /// A sequence of values to project. - /// A transform function to apply to each element. - /// A sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence. - public static TResult[] SelectManyF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - List result = new List(source.Length); - for (int i = 0; i < source.Length; i++) - { - TResult[] va = selector(source[i]); - for (int j = 0; j < va.Length; j++) - { - result.Add(va[j]); - } - } - return result.ToArray(); - } - - /// - /// Projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence - /// utilizing the index of each element. - /// - /// A sequence of values to project. - /// A transform function to apply to each element and it's index. - /// A sequence whose elements are the result of invoking the one-to-many transform function on each element and index of the input sequence. - public static TResult[] SelectManyF(this Span source, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - List result = new List(source.Length); - for (int i = 0; i < source.Length; i++) - { - TResult[] va = selector(source[i], i); - for (int j = 0; j < va.Length; j++) - { - result.Add(va[j]); - } - } - return result.ToArray(); - } + // -------------------------- LISTS -------------------------------------------- /// diff --git a/LinqFaster/SelectWhere.cs b/LinqFaster/SelectWhere.cs index c52fc97..7eb8d1a 100644 --- a/LinqFaster/SelectWhere.cs +++ b/LinqFaster/SelectWhere.cs @@ -78,78 +78,7 @@ public static partial class LinqFaster return result; } - // -------------------------- this Spans -------------------------------------------- - - /// - /// Combines Select and Where into a single call for optimal - /// performance. - /// - /// The input sequence to filter and select - /// The transformation to apply before filtering. - /// The predicate with which to filter result. - /// A sequence transformed and then filtered by selector and predicate. - public static TResult[] SelectWhereF(this Span source, Func selector, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - TResult[] result = new TResult[source.Length]; - int idx = 0; - for (int i = 0; i < source.Length; i++) - { - TResult s = selector(source[i]); - if (predicate(s)) - { - result[idx] = s; - idx++; - } - } - Array.Resize(ref result, idx); - return result; - } - - /// - /// Combines Select and Where with indexes into a single call for optimal - /// performance. - /// - /// The input sequence to filter and select - /// The transformation with index to apply before filtering. - /// The predicate with index with which to filter result. - /// A sequence transformed and then filtered by selector and predicate with indexes. - public static TResult[] SelectWhereF(this Span source, Func selector, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - TResult[] result = new TResult[source.Length]; - int idx = 0; - for (int i = 0; i < source.Length; i++) - { - TResult s = selector(source[i], i); - if (predicate(s, i)) - { - result[idx] = s; - idx++; - } - } - Array.Resize(ref result, idx); - return result; - } - + // -------------------------- LISTS -------------------------------------------- /// diff --git a/LinqFaster/SequenceEqual.cs b/LinqFaster/SequenceEqual.cs index ada87e1..68da20d 100644 --- a/LinqFaster/SequenceEqual.cs +++ b/LinqFaster/SequenceEqual.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System; namespace JM.LinqFaster { @@ -33,12 +32,22 @@ public static bool SequenceEqualF(this T[] first, T[] second, IEqualityCompar throw Error.ArgumentNull("second"); } - if (first.Length != second.Length) return false; - if (first == second) return true; + if (first.Length != second.Length) + { + return false; + } + + if (first == second) + { + return true; + } for (int i = 0; i < first.Length; i++) { - if (!comparer.Equals(first[i], second[i])) return false; + if (!comparer.Equals(first[i], second[i])) + { + return false; + } } return true; @@ -68,12 +77,15 @@ public static int[] SequenceCompareF(this T[] first, T[] second, IComparer { comparer = Comparer.Default; } - if (first.Length != second.Length) throw Error.NotSupported(); + if (first.Length != second.Length) + { + throw Error.NotSupported(); + } int[] result = new int[first.Length]; for (int i = 0; i < first.Length; i++) { - result[i] = comparer.Compare(first[i], second[i]); + result[i] = comparer.Compare(first[i], second[i]); } return result; } @@ -106,11 +118,17 @@ public static bool SequenceEqualF(this T[] first, List second, IEqualityCo throw Error.ArgumentNull("second"); } - if (first.Length != second.Count) return false; + if (first.Length != second.Count) + { + return false; + } for (int i = 0; i < first.Length; i++) { - if (!comparer.Equals(first[i], second[i])) return false; + if (!comparer.Equals(first[i], second[i])) + { + return false; + } } return true; @@ -142,55 +160,24 @@ public static bool SequenceEqualF(this List first, T[] second, IEqualityCo throw Error.ArgumentNull("second"); } - if (first.Count != second.Length) return false; - - for (int i = 0; i < first.Count; i++) - { - if (!comparer.Equals(first[i], second[i])) return false; - } - - return true; - } - - /*---- Spans ----*/ - /// - /// Determines whether two sequences are equal by comparing the elements by using the - /// provided comparer or the default equality comparer for their type if none is provided. - /// - /// A sequence to compare to second. - /// A sequence to compare to first. - /// An optional Comparer to use for the comparison. - /// true of the two sources are of equal length and their corresponding - /// elements are equal according to the equality comparer. Otherwise, false. - public static bool SequenceEqualF(this Span first, Span second, IEqualityComparer comparer = null) - { - if (comparer == null) - { - comparer = EqualityComparer.Default; - } - - if (first == null) - { - throw Error.ArgumentNull("first"); - } - - if (second == null) + if (first.Count != second.Length) { - throw Error.ArgumentNull("second"); + return false; } - if (first.Length != second.Length) return false; - if (first == second) return true; - - for (int i = 0; i < first.Length; i++) + for (int i = 0; i < first.Count; i++) { - if (!comparer.Equals(first[i], second[i])) return false; + if (!comparer.Equals(first[i], second[i])) + { + return false; + } } return true; } + /* ------------ List ---------------- */ /// /// Determines whether two sequences are equal by comparing the elements by using the @@ -201,43 +188,7 @@ public static bool SequenceEqualF(this Span first, Span second, IEquali /// An optional Comparer to use for the comparison. /// true of the two sources are of equal length and their corresponding /// elements are equal according to the equality comparer. Otherwise, false. - public static bool SequenceEqualF(this Span first, List second, IEqualityComparer comparer = null) - { - if (comparer == null) - { - comparer = EqualityComparer.Default; - } - - if (first == null) - { - throw Error.ArgumentNull("first"); - } - - if (second == null) - { - throw Error.ArgumentNull("second"); - } - - if (first.Length != second.Count) return false; - - for (int i = 0; i < first.Length; i++) - { - if (!comparer.Equals(first[i], second[i])) return false; - } - - return true; - } - - /// - /// Determines whether two sequences are equal by comparing the elements by using the - /// provided comparer or the default equality comparer for their type if none is provided. - /// - /// A sequence to compare to second. - /// A sequence to compare to first. - /// An optional Comparer to use for the comparison. - /// true of the two sources are of equal length and their corresponding - /// elements are equal according to the equality comparer. Otherwise, false. - public static bool SequenceEqualF(this List first, Span second, IEqualityComparer comparer = null) + public static bool SequenceEqualF(this List first, List second, IEqualityComparer comparer = null) { if (comparer == null) { @@ -254,50 +205,22 @@ public static bool SequenceEqualF(this List first, Span second, IEquali throw Error.ArgumentNull("second"); } - if (first.Count != second.Length) return false; - - for (int i = 0; i < first.Count; i++) - { - if (!comparer.Equals(first[i], second[i])) return false; - } - - return true; - } - - /* ------------ List ---------------- */ - - /// - /// Determines whether two sequences are equal by comparing the elements by using the - /// provided comparer or the default equality comparer for their type if none is provided. - /// - /// A sequence to compare to second. - /// A sequence to compare to first. - /// An optional Comparer to use for the comparison. - /// true of the two sources are of equal length and their corresponding - /// elements are equal according to the equality comparer. Otherwise, false. - public static bool SequenceEqualF(this List first, List second, IEqualityComparer comparer = null) - { - if (comparer == null) + if (first.Count != second.Count) { - comparer = EqualityComparer.Default; + return false; } - if (first == null) + if (first == second) { - throw Error.ArgumentNull("first"); + return true; } - if (second == null) - { - throw Error.ArgumentNull("second"); - } - - if (first.Count != second.Count) return false; - if (first == second) return true; - for (int i = 0; i < first.Count; i++) { - if (!comparer.Equals(first[i], second[i])) return false; + if (!comparer.Equals(first[i], second[i])) + { + return false; + } } return true; diff --git a/LinqFaster/Single.cs b/LinqFaster/Single.cs index 14ce32f..ab03b76 100644 --- a/LinqFaster/Single.cs +++ b/LinqFaster/Single.cs @@ -138,141 +138,7 @@ public static T SingleOrDefaultF(this T[] source, Func predicate) return result; } - // --------------------------- Spans ---------------------------- - - /// - /// Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence. - /// - /// A sequence to return the single element of - /// The single element of the input sequence or default if no elements exist. - public static T SingleF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (source.Length == 0) - { - throw Error.NoElements(); - } - - if (source.Length > 1) - { - throw Error.MoreThanOneElement(); - } - - return source[0]; - } - - /// - /// Returns the only element of a sequence, or the default if no elements exist, and throws an exception if there is not exactly one element in the sequence. - /// - /// A sequence to return the single element of - /// The single element of the input sequence - public static T SingleOrDefaultF(this Span source) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (source.Length == 0) - { - return default(T); - } - - if (source.Length > 1) - { - throw Error.MoreThanOneElement(); - } - - return source[0]; - } - - /// - /// Returns the only element of a sequence that satisfies a specified condition, and throws an exception if more than one such element exists. - /// - /// A sequence to return a single element from. - /// A function to test an element for a condition. - /// The single element of the input sequence that satisfies a condition. - public static T SingleF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - T result = default(T); - bool foundMatch = false; - for (int i = 0; i < source.Length; i++) - { - if (predicate(source[i])) - { - if (foundMatch) - { - throw Error.MoreThanOneMatch(); - } - - result = source[i]; - foundMatch = true; - } - } - - if (foundMatch) - { - return result; - } - else - { - throw Error.NoMatch(); - } - } - - /// - /// Returns the only element of a sequence that satisfies a specified condition, or a default value if - /// no such element exists, and throws an exception if more than one such element exists. - /// - /// A sequence to return a single element from. - /// A function to test an element for a condition. - /// The single element of the input sequence that satisfies a condition or default value if no such element is found. - public static T SingleOrDefaultF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - - T result = default(T); - bool foundMatch = false; - for (int i = 0; i < source.Length; i++) - { - if (predicate(source[i])) - { - if (foundMatch) - { - throw Error.MoreThanOneMatch(); - } - - result = source[i]; - foundMatch = true; - } - } - - return result; - } - + // --------------------------- Lists ---------------------------- /// diff --git a/LinqFaster/Skip.cs b/LinqFaster/Skip.cs index f4f46bc..edc6ca5 100644 --- a/LinqFaster/Skip.cs +++ b/LinqFaster/Skip.cs @@ -59,70 +59,7 @@ public static T[] SkipWhileF(this T[] source, Func predicate) return result; } - /*------------- SPans ---------------- */ - - /// - /// Bypasses a specified number of elements in a sequence and then returns the remaining elements. - /// - /// A sequence to return elements from. - /// The number of elements to skip before returning the remaining elements. - /// A sequence that contains the elements that occur after the specified index in the input sequence. - public static T[] SkipF(this Span source, int count) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (count < 0) - { - count = 0; - } - else if (count > source.Length) - { - return new T[0]; - } - - T[] result = new T[source.Length - count]; - for (int i = count; i < source.Length; i++) - { - result[i - count] = source[i]; - } - return result; - } - - /// - /// Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. - /// - /// A sequence to return elements from. - /// A function to test each element for a condition. - /// A sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate. - public static T[] SkipWhileF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - int count = 0; - for (; count < source.Length; count++) - { - if (!predicate(source[count])) break; - } - T[] result = new T[source.Length - count]; - for (int i = count; i < source.Length; i++) - { - result[i - count] = source[i]; - } - return result; - } - - - - + // ------------- Lists ---------------- /// diff --git a/LinqFaster/Take.cs b/LinqFaster/Take.cs index 9aa2dfc..5c24df6 100644 --- a/LinqFaster/Take.cs +++ b/LinqFaster/Take.cs @@ -88,101 +88,7 @@ public static T[] TakeWhileF(this T[] source, Func predicate) return result; } - /*---- spans ---- */ - /// - /// Returns a specified number of contiguous elements from the start of a sequence. - /// - /// The sequence to return elements from. - /// The number of elements to return. - /// A sequence that contains the specified number of elements from the start of the input sequence. - public static T[] TakeF(this Span source, int count) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (count < 0) - { - count = 0; - } - else if (count > source.Length) - { - count = source.Length; - } - - T[] result = new T[count]; - for (int i = 0; i < result.Length; i++) - { - result[i] = source[i]; - } - return result; - } - - - /// - /// Returns elements from a sequence as long as a specified condition is true. - /// - /// A sequence to return elements from. - /// A function to test each element for a condition. - /// A sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes. - public static T[] TakeWhileF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - int count = 0; - for (; count < source.Length; count++) - { - if (!predicate(source[count])) - break; - } - T[] result = new T[count]; - for (int i = 0; i < result.Length; i++) - { - result[i] = source[i]; - } - return result; - } - - /// - /// Returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function. - /// - /// The sequence to return elements from. - /// A function to test each source element for a condition; the second parameter of the function represents the index of the source element. - /// A sequence that contains elements from the input sequence that occur before the element at which the test no longer passes. - public static T[] TakeWhileF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - int count = 0; - for (; count < source.Length; count++) - { - if (!predicate(source[count], count)) - break; - } - T[] result = new T[count]; - for (int i = 0; i < result.Length; i++) - { - result[i] = source[i]; - } - return result; - } - - - // ------------- Lists ---------------- + // ------------- Lists ---------------- /// /// Returns a specified number of contiguous elements from the start of a sequence. diff --git a/LinqFaster/Where.cs b/LinqFaster/Where.cs index afe6ad4..4d00c93 100644 --- a/LinqFaster/Where.cs +++ b/LinqFaster/Where.cs @@ -59,73 +59,6 @@ public static T[] WhereF(this T[] source, Func predicate) } - T[] result = new T[source.Length]; - int idx = 0; - for (int i = 0; i < source.Length; i++) - { - if (predicate(source[i], i)) - { - result[idx] = source[i]; - idx++; - } - } - Array.Resize(ref result, idx); - return result; - } - - // -------------------------- Spans -------------------------------------------- - - /// - /// Filters a sequence of values based on a predicate. - /// - /// A sequence to filter. - /// A function to test each element for a condition. - /// A sequence that contains elements from the input sequence that satisfy the condition. - public static T[] WhereF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - T[] result = new T[source.Length]; - int idx = 0; - for (int i = 0; i < source.Length; i++) - { - if (predicate(source[i])) - { - result[idx] = source[i]; - idx++; - } - } - Array.Resize(ref result, idx); - return result; - } - - /// - /// Filters a sequence of values based on a predicate that includes the index in it's logic. - /// - /// A sequence to filter. - /// A function to test each element for a condition along with the element's index. - /// A sequence that contains elements from the input sequence that satisfy the condition. - public static T[] WhereF(this Span source, Func predicate) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - T[] result = new T[source.Length]; int idx = 0; for (int i = 0; i < source.Length; i++) diff --git a/LinqFaster/WhereAggregate.cs b/LinqFaster/WhereAggregate.cs index c22a199..14e3ea7 100644 --- a/LinqFaster/WhereAggregate.cs +++ b/LinqFaster/WhereAggregate.cs @@ -160,184 +160,16 @@ public static T WhereAggregateF(this T[] source, Func predicate } TAccumulate result = seed; - int count = 0; - foreach (TSource v in source) - { - if (predicate(v)) { - result = func(result, v); - count++; - } - } - return resultSelector(result); - } - - // ----------------------------- Spans ------------------ - - /// - /// Combines Where and Aggregate for optimal performance - /// - /// The input to filter then aggregate. - /// The function to filter the input sequence with. - /// The function to aggregate the filtered sequence. - /// The filtered then aggregated sequence. - public static T WhereAggregateF(this Span source, Func predicate, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - if (func == null) - { - throw Error.ArgumentNull("func"); - } - - T result = default(T); - - int i = 0; - for (; i < source.Length; i++) - { - if (predicate(source[i])) - { - result = source[i]; - i++; - break; - } - } - for (; i < source.Length; i++) - { - if (predicate(source[i])) - { - result = func(result, source[i]); - } - } - return result; - } - - /// - /// Combines Where and Aggregate with index for optimal performance - /// - /// The input to filter then aggregate. - /// The function to filter the input sequence and it's index with. - /// The function to aggregate the filtered sequence. - /// The filtered then aggregated sequence. - public static T WhereAggregateF(this Span source, Func predicate, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - T result = default(T); - - int i = 0; - for (; i < source.Length; i++) - { - if (predicate(source[i], i)) - { - result = source[i]; - i++; - break; - } - } - for (; i < source.Length; i++) - { - if (predicate(source[i], i)) - { - result = func(result, source[i]); - } - } - return result; - } - - /// - /// Combines Where and Aggregate for optimal performance with a starting seed. - /// - /// The input to filter then aggregate. - /// The function to filter the input sequence with. - /// The initial value to aggregate on. - /// The function to aggregate the filtered sequence. - /// The filtered then aggregated sequence. - public static TAccumulate WhereAggregateF(this Span source, Func predicate, TAccumulate seed, Func func) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull("func"); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - TAccumulate result = seed; - foreach (TSource v in source) - { - if (predicate(v)) - result = func(result, v); - } - return result; - } - - /// - /// Combines Where and Aggregate for optimal performance with a starting seed and a result transformation. - /// - /// The input to filter then aggregate. - /// The function to filter the input sequence with. - /// The initial value to aggregate on. - /// The function to aggregate the filtered sequence. - /// A function to transform the final result. - /// The filtered then aggregated then transformed sequence. - public static TResult WhereAggregateF(this Span source, Func predicate, TAccumulate seed, Func func, Func resultSelector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (func == null) - { - throw Error.ArgumentNull("func"); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - if (resultSelector == null) - { - throw Error.ArgumentNull("resultSelector"); - } - - TAccumulate result = seed; - int count = 0; foreach (TSource v in source) { if (predicate(v)) { result = func(result, v); - count++; - } + } } return resultSelector(result); } - - + // --------------------------- Lists ------------------------- /// diff --git a/LinqFaster/WhereSelect.cs b/LinqFaster/WhereSelect.cs index 9456a29..35ab258 100644 --- a/LinqFaster/WhereSelect.cs +++ b/LinqFaster/WhereSelect.cs @@ -86,88 +86,6 @@ public static partial class LinqFaster return result; } - - // -------------------------- SPANS -------------------------------------------- - - - /// - /// Combined Where and Select for optimal performance. - /// - /// The input sequence to filter then transform. - /// A function to use to filter the sequence. - /// A function to transform the filtered elements. - /// A sequence of filtered and transformed elements. - public static TResult[] WhereSelectF(this Span source, Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - if (selector == null) - { - throw Error.ArgumentNull("predicate"); - } - - TResult[] result = new TResult[source.Length]; - int idx = 0; - for (int i = 0; i < source.Length; i++) - { - if (predicate(source[i])) - { - result[idx] = selector(source[i]); - idx++; - } - } - Array.Resize(ref result, idx); - return result; - } - - /// - /// Combined Where and Select for optimal performance that uses the index in the - /// predicate and selector. - /// - /// The input sequence to filter then transform. - /// A function to use to filter the sequence. - /// A function to transform the filtered elements. - /// A sequence of filtered and transformed elements. - public static TResult[] WhereSelectF(this Span source, Func predicate, Func selector) - { - if (source == null) - { - throw Error.ArgumentNull(nameof(source)); - } - - if (predicate == null) - { - throw Error.ArgumentNull("predicate"); - } - - if (selector == null) - { - throw Error.ArgumentNull("predicate"); - } - - TResult[] result = new TResult[source.Length]; - int idx = 0; - for (int i = 0; i < source.Length; i++) - { - if (predicate(source[i], i)) - { - result[idx] = selector(source[i], idx); - idx++; - } - } - Array.Resize(ref result, idx); - return result; - } - - // -------------------------- LISTS -------------------------------------------- /// diff --git a/LinqFaster/Zip.cs b/LinqFaster/Zip.cs index b6d59f7..64f6cdf 100644 --- a/LinqFaster/Zip.cs +++ b/LinqFaster/Zip.cs @@ -51,51 +51,6 @@ public static partial class LinqFaster } - /// - /// Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results. - /// - /// The first sequence to merge. - /// The second sequence to merge. - /// A function that specifies how to merge the elements from the two sequences. - /// A sequence that contains merged elements of two input sequences. - public static R[] ZipF(this Span first, Span second, Func selector) - { - if (first == null) - { - throw Error.ArgumentNull("first"); - } - if (second == null) - { - throw Error.ArgumentNull("second"); - } - if (selector == null) - { - throw Error.ArgumentNull(nameof(selector)); - } - - //maintain array bounds elision - if (first.Length < second.Length) - { - R[] result = new R[first.Length]; - for (int i = 0; i < first.Length; i++) - { - result[i] = selector(first[i], second[i]); - } - return result; - - } - else - { - R[] result = new R[second.Length]; - for (int i = 0; i < second.Length; i++) - { - result[i] = selector(first[i], second[i]); - } - return result; - } - - } - /// /// Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results. /// diff --git a/LinqFasterParallel/LinqFasterParallel.csproj b/LinqFasterParallel/LinqFasterParallel.csproj index e56afde..b868301 100644 --- a/LinqFasterParallel/LinqFasterParallel.csproj +++ b/LinqFasterParallel/LinqFasterParallel.csproj @@ -20,6 +20,7 @@ ..\docs\linqfaster-parallel.xml true + JM.LinqFaster.Parallel diff --git a/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj b/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj index a4cbe6f..d10dc78 100644 --- a/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj +++ b/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj @@ -21,6 +21,7 @@ ..\docs\linqfaster-parallel-simd.xml true + JM.LinqFaster.SIMD.Parallel diff --git a/LinqFasterSIMD/LinqFasterSIMD.csproj b/LinqFasterSIMD/LinqFasterSIMD.csproj index 2d49e84..85572b9 100644 --- a/LinqFasterSIMD/LinqFasterSIMD.csproj +++ b/LinqFasterSIMD/LinqFasterSIMD.csproj @@ -21,6 +21,7 @@ ..\docs\linqfaster-simd.xml true + JM.LinqFaster.SIMD diff --git a/LinqFasterSpan/Aggregate.cs b/LinqFasterSpan/Aggregate.cs new file mode 100644 index 0000000..230eba5 --- /dev/null +++ b/LinqFasterSpan/Aggregate.cs @@ -0,0 +1,233 @@ +using System; +using System.Runtime.CompilerServices; + +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global + +namespace JM.LinqFasterSpan +{ + /// + /// Provides faster array and list specific extension methods with + /// the same semantics as the Linq extensions methods. + /// + public static partial class LinqFasterSpan + { + // Note: Lists can have items added and removed whilst these API's are in use + // The IReadOnlyList represents a list in which the _number_ and _order_ of list elements is read-only. + // + + // ------------------------------ Spans -------------------------- + #region Normal Span + /// + /// Applies an accumulator function over a Span{T}. + /// + /// A Span{T} to aggregate over. + /// An accumulator function to be invoked on each element + /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TSource AggregateF(this Span source, + Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull("func"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + TSource result = source[0]; + for (int i = 1; i < source.Length; i++) + { + result = func(result, source[i]); + } + return result; + } + + /// + /// Applies an accumulator function over a Span{T}. The specified seed + /// value is used as the initial accumulator value. + /// + /// A Span{T} to aggregate over. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element + /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TAccumulate AggregateF(this Span source, TAccumulate seed, + Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull("func"); + } + + TAccumulate result = seed; + for (int index = 0; index < source.Length; index++) + { + result = func(result, source[index]); + } + + return result; + } + + /// + /// Applies an accumulator function over a Span{T}. The specified seed + /// value is used as the initial accumulator value, and the specified + /// function is used to select the result value. + /// + /// A Span{T} to aggregate over. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element + /// A function to transform the final accumulator value into the result value. + /// The transformed final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult AggregateF(this Span source, TAccumulate seed, + Func func, + Func resultSelector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull("func"); + } + + if (resultSelector == null) + { + throw Error.ArgumentNull("resultSelector"); + } + + TAccumulate result = seed; + for (int index = 0; index < source.Length; index++) + { + result = func(result, source[index]); + } + + return resultSelector(result); + } + #endregion Normal Span + + // ------------------------------ ReadOnlySpans -------------------------- + #region ReadOnlySpan + /// + /// Applies an accumulator function over a ReadOnlySpan{T}. + /// + /// A ReadOnlySpan{T} to aggregate over. + /// An accumulator function to be invoked on each element + /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TSource AggregateF(this ReadOnlySpan source, + Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull("func"); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + TSource result = source[0]; + for (int i = 1; i < source.Length; i++) + { + result = func(result, source[i]); + } + return result; + } + + /// + /// Applies an accumulator function over a ReadOnlySpan{T}. The specified seed + /// value is used as the initial accumulator value. + /// + /// A ReadOnlySpan{T} to aggregate over. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element + /// The final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TAccumulate AggregateF(this ReadOnlySpan source, TAccumulate seed, + Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull("func"); + } + + TAccumulate result = seed; + for (int index = 0; index < source.Length; index++) + { + result = func(result, source[index]); + } + + return result; + } + + /// + /// Applies an accumulator function over a ReadOnlySpan{T}. The specified seed + /// value is used as the initial accumulator value, and the specified + /// function is used to select the result value. + /// + /// A ReadOnlySpan{T} to aggregate over. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element + /// A function to transform the final accumulator value into the result value. + /// The transformed final accumulator value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TResult AggregateF(this ReadOnlySpan source, TAccumulate seed, + Func func, + Func resultSelector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull("func"); + } + + if (resultSelector == null) + { + throw Error.ArgumentNull("resultSelector"); + } + + TAccumulate result = seed; + for (int index = 0; index < source.Length; index++) + { + result = func(result, source[index]); + } + + return resultSelector(result); + } + #endregion ReadOnlySpan + + + } +} \ No newline at end of file diff --git a/LinqFasterSpan/AnyAll.cs b/LinqFasterSpan/AnyAll.cs new file mode 100644 index 0000000..862f2d4 --- /dev/null +++ b/LinqFasterSpan/AnyAll.cs @@ -0,0 +1,85 @@ +using System; +using System.Runtime.CompilerServices; + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + + // -------------------------- this SpanS -------------------------------------------- + + /// + /// Determines whether an array contains any elements + /// + /// The array to check for emptiness + /// true if the source array contains any elements, otherwise, false/ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + return source.Length > 0; + } + + + + /// + /// Determines whether any element of an array satisfies a condition. + /// + /// An array whose elements to apply the predicate to. + /// A function to test each element for a condition. + /// true if any elements in the source array pass the test in the specified predicate; otherwise, false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyF(this Span source, Predicate predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + for (int i = 0; i < source.Length; i++) + { + if (predicate(source[i])) return true; + } + return false; + } + + + /// + /// Determines whether all elements of an array satisfy a condition. + /// + /// An array that contains the elements to apply the predicate to. + /// A function to test each element for a condition. + /// true if every element of the source array passes the test in the specified + /// predicate, or if the array is empty; otherwise, false + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllF(this Span source, Predicate predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + for (int i = 0; i < source.Length; i++) + { + if (!predicate(source[i])) return false; + } + return true; + } + + + } +} \ No newline at end of file diff --git a/LinqFaster/AverageSpan.cs b/LinqFasterSpan/AverageSpan.cs similarity index 99% rename from LinqFaster/AverageSpan.cs rename to LinqFasterSpan/AverageSpan.cs index 845a4fa..93b08c9 100644 --- a/LinqFaster/AverageSpan.cs +++ b/LinqFasterSpan/AverageSpan.cs @@ -2,9 +2,9 @@ using System.Globalization; using System.Runtime.CompilerServices; -namespace JM.LinqFaster +namespace JM.LinqFasterSpan { - public static partial class LinqFaster + public static partial class LinqFasterSpan { /* * Since ReadOnlySpan is actually a struct and it does not inherit from IEnumerable, diff --git a/LinqFasterSpan/Contains.cs b/LinqFasterSpan/Contains.cs new file mode 100644 index 0000000..e3aea5e --- /dev/null +++ b/LinqFasterSpan/Contains.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + + // -------------------------- this SpanS -------------------------------------------- + + /// + /// Determines whether an array contains a specified element by using the + /// provided IEqualityComparer. + /// + /// An array in which to locate a value. + /// The value to locate. + /// An equality comparer to compare values. + /// true if the source sequence contains an element that has the specified value; otherwise, false. + public static bool ContainsF(this Span source, TSource value, IEqualityComparer comparer = null) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (comparer == null) + { + comparer = EqualityComparer.Default; + } + + + for (int i = 0; i < source.Length;i++) + { + if (comparer.Equals(source[i], value)) + { + return true; + } + } + + return false; + } + + + } +} diff --git a/LinqFasterSpan/Count.cs b/LinqFasterSpan/Count.cs new file mode 100644 index 0000000..3a2f320 --- /dev/null +++ b/LinqFasterSpan/Count.cs @@ -0,0 +1,48 @@ +using System; + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + + // -------------------------- this Spans -------------------------------------------- + + /// + /// Returns a number that represents how many elements in the specified + /// array satisfy a condition. + /// + /// An array that contains elements to be tested and counted. + /// A function to test each element for a condition. + /// A number that represents how many elements in the array satisfy the condition + /// in the predicate function. + public static int CountF(this Span source, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + int count = 0; + for (int i = 0; i < source.Length; i++) + { + checked + { + if (predicate(source[i])) + { + count++; + } + } + } + + return count; + } + + + } +} diff --git a/LinqFasterSpan/DefaultIfEmpty.cs b/LinqFasterSpan/DefaultIfEmpty.cs new file mode 100644 index 0000000..1fb843e --- /dev/null +++ b/LinqFasterSpan/DefaultIfEmpty.cs @@ -0,0 +1,37 @@ +using System; +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global + +namespace JM.LinqFasterSpan +{ + // LINQ's DefaultIfEmpty-method checks if the sequence is empty. + // If that is the case, it will return a singleton sequence: + // A sequence containing exactly one element. + // This one element has the default value of the sequence's type. + // If the sequence does contain elements, the DefaultIfEmpty-method will + // simply return the sequence itself. + // Note: DefaultIfEmpty also has an overload that takes a user-provided default value + public static partial class LinqFasterSpan + { + // -------------------------- Arrays -------------------------------------------- + + /// + /// Returns source or (if needed) an array (For speed) with a single value set to default{T} + /// + /// + /// + /// source or new array{1} + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span DefaultIfEmptyF(this Span source) + { + if ((source == null) + || (source.Length == 0) + ) + { + return new Span < T > (new T[] { default(T) }); + } + return source; + } + } +} diff --git a/LinqFasterSpan/First.cs b/LinqFasterSpan/First.cs new file mode 100644 index 0000000..d33532c --- /dev/null +++ b/LinqFasterSpan/First.cs @@ -0,0 +1,219 @@ +using System; +using System.Runtime.CompilerServices; +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + // -------------------------- Span -------------------------------------------- + #region Normal Span + /// + /// Returns the first element of an Span. + /// + /// The Span to return the first element of. + /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + return source[0]; + } + + /// + /// Returns the first element in an Span that satisfies a specified condition. + /// + /// An Span to return an element from. + /// A function to test each element for a condition. + /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this Span source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + int sourceCount = source.Length; + for (int i = 0; i < sourceCount; i++) + { + if (func(source[i])) + { + return source[i]; + } + } + + throw Error.NoMatch(); + } + + /// + /// Returns the first element of an Span, or a default value if the + /// array contains no elements. + /// + /// The Span to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + return default(T); + } + return source[0]; + } + + /// + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. + /// + /// An Span to return an element from. + /// A function to test each element for a condition. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this Span source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + foreach (T a in source) + { + if (func(a)) + { + return a; + } + } + + return default(T); + } + #endregion Normal Span + + #region ReadOnlySpan + /// + /// Returns the first element of an ReadOnlySpan. + /// + /// The ReadOnlySpan to return the first element of. + /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + return source[0]; + } + + /// + /// Returns the first element in an ReadOnlySpan that satisfies a specified condition. + /// + /// An ReadOnlySpan to return an element from. + /// A function to test each element for a condition. + /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstF(this ReadOnlySpan source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + foreach (T a in source) + { + if (func(a)) + { + return a; + } + } + + throw Error.NoMatch(); + } + + /// + /// Returns the first element of an ReadOnlySpan, or a default value if the + /// array contains no elements. + /// + /// The ReadOnlySpan to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + return default(T); + } + return source[0]; + } + + /// + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. + /// + /// An ReadOnlySpan to return an element from. + /// A function to test each element for a condition. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FirstOrDefaultF(this ReadOnlySpan source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + foreach (T a in source) + { + if (func(a)) + { + return a; + } + } + + return default(T); + } + #endregion ReadOnlySpan + + } +} diff --git a/LinqFasterSpan/Last.cs b/LinqFasterSpan/Last.cs new file mode 100644 index 0000000..3107cc0 --- /dev/null +++ b/LinqFasterSpan/Last.cs @@ -0,0 +1,221 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Runtime.CompilerServices; + +// ReSharper disable ForCanBeConvertedToForeach +// ReSharper disable UnusedMember.Global + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + // -------------------------- Span -------------------------------------------- + #region Normal Span + /// + /// Returns the first element of an Span. + /// + /// The Span to return the first element of. + /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + return source[source.Length - 1]; + } + + /// + /// Returns the first element in an Span that satisfies a specified condition. + /// + /// An Span to return an element from. + /// A function to test each element for a condition. + /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this Span source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + for (int i = source.Length - 1; i >= 0; i--) + { + if (func(source[i])) + { + return source[i]; + } + } + + throw Error.NoMatch(); + } + + /// + /// Returns the first element of an Span, or a default value if the + /// array contains no elements. + /// + /// The Span to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + return default(T); + } + return source[source.Length - 1]; + } + + /// + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. + /// + /// An Span to return an element from. + /// A function to test each element for a condition. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this Span source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + for (int i = source.Length - 1; i >= 0; i--) + { + if (func(source[i])) + { + return source[i]; + } + } + + return default(T); + } + #endregion Normal Span + + #region ReadOnlySpan + /// + /// Returns the first element of an ReadOnlySpan. + /// + /// The ReadOnlySpan to return the first element of. + /// The first element in the specified array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + throw Error.NoElements(); + } + return source[source.Length - 1]; + } + + /// + /// Returns the first element in an ReadOnlySpan that satisfies a specified condition. + /// + /// An ReadOnlySpan to return an element from. + /// A function to test each element for a condition. + /// The first element that satisfies the condition. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastF(this ReadOnlySpan source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + for (int i = source.Length - 1; i >= 0; i--) + { + if (func(source[i])) + { + return source[i]; + } + } + + throw Error.NoMatch(); + } + + /// + /// Returns the first element of an ReadOnlySpan, or a default value if the + /// array contains no elements. + /// + /// The ReadOnlySpan to return the first element of. + /// default value if source is empty, otherwise, the first element + /// in source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this ReadOnlySpan source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (source.Length == 0) + { + return default(T); + } + return source[source.Length - 1]; + } + + /// + /// Returns the first element of the sequence that satisfies a condition or a + /// default value if no such element is found. + /// + /// An ReadOnlySpan to return an element from. + /// A function to test each element for a condition. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T LastOrDefaultF(this ReadOnlySpan source, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull(nameof(func)); + } + + for (int i = source.Length - 1; i >= 0; i--) + { + if (func(source[i])) + { + return source[i]; + } + } + + return default(T); + } + #endregion ReadOnlySpan + } +} diff --git a/LinqFasterSpan/LinqFasterSpan.csproj b/LinqFasterSpan/LinqFasterSpan.csproj new file mode 100644 index 0000000..2e792e2 --- /dev/null +++ b/LinqFasterSpan/LinqFasterSpan.csproj @@ -0,0 +1,41 @@ + + + + netstandard2.0;net462;net48 + 1.0.0 + Jack Mott + Jack Mott + High performance Linq-style extension methods for Span<T> and ReadOnlySpan<T>. + Copyright 2019 (c) Jack Mott. All rights reserved. + https://github.com/jackmott/LinqFaster + https://github.com/jackmott/LinqFaster + https://jackmott.github.io/images/LinqFaster.png + Github + performance linq + Added Span<T> support, improved performance of Take functions. + + JM.LinqFaster.Span + JM.LinqFasterSpan + + + + ..\docs\LinqFasterSpan.xml + True + true + + + + + + + + + + + + + + + + + diff --git a/LinqFaster/MaxSpan.cs b/LinqFasterSpan/MaxSpan.cs similarity index 99% rename from LinqFaster/MaxSpan.cs rename to LinqFasterSpan/MaxSpan.cs index 2808f79..cadf268 100644 --- a/LinqFaster/MaxSpan.cs +++ b/LinqFasterSpan/MaxSpan.cs @@ -5,12 +5,12 @@ // ReSharper disable UnusedMember.Global // ReSharper disable LoopCanBeConvertedToQuery -namespace JM.LinqFaster +namespace JM.LinqFasterSpan { // Common types optimised: int, long, float, double, decimal // Other types will be handled via the templates which are approx 2 time longer than // the above optimised base types - public static partial class LinqFaster + public static partial class LinqFasterSpan { // Note: although there is a lot of shared code in the following // comparers, we do not incorporate it into a base class for perf diff --git a/LinqFaster/MinSpan.cs b/LinqFasterSpan/MinSpan.cs similarity index 99% rename from LinqFaster/MinSpan.cs rename to LinqFasterSpan/MinSpan.cs index ca467b2..e464b6d 100644 --- a/LinqFaster/MinSpan.cs +++ b/LinqFasterSpan/MinSpan.cs @@ -5,12 +5,12 @@ // ReSharper disable UnusedMember.Global // ReSharper disable LoopCanBeConvertedToQuery -namespace JM.LinqFaster +namespace JM.LinqFasterSpan { // Common types optimised: int, long, float, double, decimal // Other types will be handled via the templates which are approx 2 time longer than // the above optimised base types - public static partial class LinqFaster + public static partial class LinqFasterSpan { // Note: although there is a lot of shared code in the following // comparers, we do not incorporate it into a base class for perf diff --git a/LinqFasterSpan/Reverse.cs b/LinqFasterSpan/Reverse.cs new file mode 100644 index 0000000..0065a63 --- /dev/null +++ b/LinqFasterSpan/Reverse.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + + /// + /// Inverts the order of the elements in a sequence. + /// + /// A sequence of values to reverse. + /// A sequence whose elements correspond to those of the input sequence in reverse order. + public static T[] ReverseF(this Span source) + { + T[] result = new T[source.Length]; + int lenLessOne = source.Length - 1; + for (int i = 0; i < result.Length; i++) + { + result[i] = source[lenLessOne - i]; + } + return result; + } + /// + /// Inverts the order of the elements in a sequence in place. + /// + /// A sequence of values to reverse. + public static void ReverseInPlaceF(this Span source) + { + source.Reverse(); + } + + } +} diff --git a/LinqFasterSpan/Select.cs b/LinqFasterSpan/Select.cs new file mode 100644 index 0000000..7889c58 --- /dev/null +++ b/LinqFasterSpan/Select.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; + + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + // -------------------------- this SpanS -------------------------------------------- + + /// + /// Projects each element of a sequence into a new form in place. + /// + /// A sequence of values to invoke a transform function on (map). + /// A transform function to apply (map) to each element. + public static void SelectInPlaceF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + for (int i = 0; i < source.Length; i++) + { + source[i] = selector(source[i]); + } + } + + /// + /// Projects each element of a sequence into a new form, in place, by incorporating the element's index. + /// + /// A sequence of values to invoke a transform function on. + /// A transform function to apply to each source element; the second parameter of the function represents the index of the source element. + public static void SelectInPlaceF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + for (int i = 0; i < source.Length; i++) + { + source[i] = selector(source[i], i); + } + } + + + /// + /// Projects each element of a sequence into a new form. (map in every other language) + /// + /// A sequence of values to invoke a transform function on (map). + /// A transform function to apply (map) to each element. + /// A sequence whose elements are the result of invoking the transform function on each element (mapping) of source. + public static TResult[] SelectF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + TResult[] r = new TResult[source.Length]; + for (int i = 0; i < source.Length; i++) + { + r[i] = selector(source[i]); + } + return r; + } + + + + /// + /// Projects each element of a sequence into a new form by incorporating the element's index. + /// + /// A sequence of values to invoke a transform function on. + /// A transform function to apply to each source element; the second parameter of the function represents the index of the source element. + /// A sequence whose elements are the result of invoking the transform function on each element of source. + public static TResult[] SelectF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + TResult[] r = new TResult[source.Length]; + for (int i = 0; i < source.Length; i++) + { + r[i] = selector(source[i], i); + } + return r; + } + + } +} diff --git a/LinqFasterSpan/SelectMany.cs b/LinqFasterSpan/SelectMany.cs new file mode 100644 index 0000000..17fe051 --- /dev/null +++ b/LinqFasterSpan/SelectMany.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + // -------------------------- this Spans -------------------------------------------- + + /// + /// Projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence. + /// Yo dawg, I heard you like sequences. + /// + /// A sequence of values to project. + /// A transform function to apply to each element. + /// A sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence. + public static TResult[] SelectManyF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + List result = new List(source.Length); + for (int i = 0; i < source.Length; i++) + { + TResult[] va = selector(source[i]); + for (int j = 0; j < va.Length; j++) + { + result.Add(va[j]); + } + } + return result.ToArray(); + } + + /// + /// Projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence + /// utilizing the index of each element. + /// + /// A sequence of values to project. + /// A transform function to apply to each element and it's index. + /// A sequence whose elements are the result of invoking the one-to-many transform function on each element and index of the input sequence. + public static TResult[] SelectManyF(this Span source, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + List result = new List(source.Length); + for (int i = 0; i < source.Length; i++) + { + TResult[] va = selector(source[i], i); + for (int j = 0; j < va.Length; j++) + { + result.Add(va[j]); + } + } + return result.ToArray(); + } + } +} diff --git a/LinqFasterSpan/SelectWhere.cs b/LinqFasterSpan/SelectWhere.cs new file mode 100644 index 0000000..408ae17 --- /dev/null +++ b/LinqFasterSpan/SelectWhere.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + + public static partial class LinqFasterSpan + { + + + // -------------------------- this Spans -------------------------------------------- + + /// + /// Combines Select and Where into a single call for optimal + /// performance. + /// + /// The input sequence to filter and select + /// The transformation to apply before filtering. + /// The predicate with which to filter result. + /// A sequence transformed and then filtered by selector and predicate. + public static TResult[] SelectWhereF(this Span source, Func selector, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + TResult[] result = new TResult[source.Length]; + int idx = 0; + for (int i = 0; i < source.Length; i++) + { + TResult s = selector(source[i]); + if (predicate(s)) + { + result[idx] = s; + idx++; + } + } + Array.Resize(ref result, idx); + return result; + } + + /// + /// Combines Select and Where with indexes into a single call for optimal + /// performance. + /// + /// The input sequence to filter and select + /// The transformation with index to apply before filtering. + /// The predicate with index with which to filter result. + /// A sequence transformed and then filtered by selector and predicate with indexes. + public static TResult[] SelectWhereF(this Span source, Func selector, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + TResult[] result = new TResult[source.Length]; + int idx = 0; + for (int i = 0; i < source.Length; i++) + { + TResult s = selector(source[i], i); + if (predicate(s, i)) + { + result[idx] = s; + idx++; + } + } + Array.Resize(ref result, idx); + return result; + } + + } +} diff --git a/LinqFasterSpan/SequenceEqual.cs b/LinqFasterSpan/SequenceEqual.cs new file mode 100644 index 0000000..d031095 --- /dev/null +++ b/LinqFasterSpan/SequenceEqual.cs @@ -0,0 +1,123 @@ +using System.Collections.Generic; +using System; + +namespace JM.LinqFasterSpan +{ + + public static partial class LinqFasterSpan + { + + /*---- Spans ----*/ + /// + /// Determines whether two sequences are equal by comparing the elements by using the + /// provided comparer or the default equality comparer for their type if none is provided. + /// + /// A sequence to compare to second. + /// A sequence to compare to first. + /// An optional Comparer to use for the comparison. + /// true of the two sources are of equal length and their corresponding + /// elements are equal according to the equality comparer. Otherwise, false. + public static bool SequenceEqualF(this Span first, Span second, IEqualityComparer comparer = null) + { + if (comparer == null) + { + comparer = EqualityComparer.Default; + } + + if (first == null) + { + throw Error.ArgumentNull("first"); + } + + if (second == null) + { + throw Error.ArgumentNull("second"); + } + + if (first.Length != second.Length) return false; + if (first == second) return true; + + for (int i = 0; i < first.Length; i++) + { + if (!comparer.Equals(first[i], second[i])) return false; + } + + return true; + } + + + + /// + /// Determines whether two sequences are equal by comparing the elements by using the + /// provided comparer or the default equality comparer for their type if none is provided. + /// + /// A sequence to compare to second. + /// A sequence to compare to first. + /// An optional Comparer to use for the comparison. + /// true of the two sources are of equal length and their corresponding + /// elements are equal according to the equality comparer. Otherwise, false. + public static bool SequenceEqualF(this Span first, List second, IEqualityComparer comparer = null) + { + if (comparer == null) + { + comparer = EqualityComparer.Default; + } + + if (first == null) + { + throw Error.ArgumentNull("first"); + } + + if (second == null) + { + throw Error.ArgumentNull("second"); + } + + if (first.Length != second.Count) return false; + + for (int i = 0; i < first.Length; i++) + { + if (!comparer.Equals(first[i], second[i])) return false; + } + + return true; + } + + /// + /// Determines whether two sequences are equal by comparing the elements by using the + /// provided comparer or the default equality comparer for their type if none is provided. + /// + /// A sequence to compare to second. + /// A sequence to compare to first. + /// An optional Comparer to use for the comparison. + /// true of the two sources are of equal length and their corresponding + /// elements are equal according to the equality comparer. Otherwise, false. + public static bool SequenceEqualF(this List first, Span second, IEqualityComparer comparer = null) + { + if (comparer == null) + { + comparer = EqualityComparer.Default; + } + + if (first == null) + { + throw Error.ArgumentNull("first"); + } + + if (second == null) + { + throw Error.ArgumentNull("second"); + } + + if (first.Count != second.Length) return false; + + for (int i = 0; i < first.Count; i++) + { + if (!comparer.Equals(first[i], second[i])) return false; + } + + return true; + } + + } +} diff --git a/LinqFasterSpan/Single.cs b/LinqFasterSpan/Single.cs new file mode 100644 index 0000000..9e48504 --- /dev/null +++ b/LinqFasterSpan/Single.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + // --------------------------- Spans ---------------------------- + + /// + /// Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence. + /// + /// A sequence to return the single element of + /// The single element of the input sequence or default if no elements exist. + public static T SingleF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (source.Length == 0) + { + throw Error.NoElements(); + } + + if (source.Length > 1) + { + throw Error.MoreThanOneElement(); + } + + return source[0]; + } + + /// + /// Returns the only element of a sequence, or the default if no elements exist, and throws an exception if there is not exactly one element in the sequence. + /// + /// A sequence to return the single element of + /// The single element of the input sequence + public static T SingleOrDefaultF(this Span source) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (source.Length == 0) + { + return default(T); + } + + if (source.Length > 1) + { + throw Error.MoreThanOneElement(); + } + + return source[0]; + } + + /// + /// Returns the only element of a sequence that satisfies a specified condition, and throws an exception if more than one such element exists. + /// + /// A sequence to return a single element from. + /// A function to test an element for a condition. + /// The single element of the input sequence that satisfies a condition. + public static T SingleF(this Span source, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + T result = default(T); + bool foundMatch = false; + for (int i = 0; i < source.Length; i++) + { + if (predicate(source[i])) + { + if (foundMatch) + { + throw Error.MoreThanOneMatch(); + } + + result = source[i]; + foundMatch = true; + } + } + + if (foundMatch) + { + return result; + } + else + { + throw Error.NoMatch(); + } + } + + /// + /// Returns the only element of a sequence that satisfies a specified condition, or a default value if + /// no such element exists, and throws an exception if more than one such element exists. + /// + /// A sequence to return a single element from. + /// A function to test an element for a condition. + /// The single element of the input sequence that satisfies a condition or default value if no such element is found. + public static T SingleOrDefaultF(this Span source, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + + T result = default(T); + bool foundMatch = false; + for (int i = 0; i < source.Length; i++) + { + if (predicate(source[i])) + { + if (foundMatch) + { + throw Error.MoreThanOneMatch(); + } + + result = source[i]; + foundMatch = true; + } + } + + return result; + } + + } +} diff --git a/LinqFasterSpan/Skip.cs b/LinqFasterSpan/Skip.cs new file mode 100644 index 0000000..dd3377b --- /dev/null +++ b/LinqFasterSpan/Skip.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + + public static partial class LinqFasterSpan + { + + /*------------- SPans ---------------- */ + + /// + /// Bypasses a specified number of elements in a sequence and then returns the remaining elements. + /// + /// A sequence to return elements from. + /// The number of elements to skip before returning the remaining elements. + /// A sequence that contains the elements that occur after the specified index in the input sequence. + public static T[] SkipF(this Span source, int count) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (count < 0) + { + count = 0; + } + else if (count > source.Length) + { + return new T[0]; + } + + T[] result = new T[source.Length - count]; + for (int i = count; i < source.Length; i++) + { + result[i - count] = source[i]; + } + return result; + } + + /// + /// Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. + /// + /// A sequence to return elements from. + /// A function to test each element for a condition. + /// A sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate. + public static T[] SkipWhileF(this Span source, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + int count = 0; + for (; count < source.Length; count++) + { + if (!predicate(source[count])) break; + } + T[] result = new T[source.Length - count]; + for (int i = count; i < source.Length; i++) + { + result[i - count] = source[i]; + } + return result; + } + + } +} diff --git a/LinqFaster/SumSpan.cs b/LinqFasterSpan/SumSpan.cs similarity index 99% rename from LinqFaster/SumSpan.cs rename to LinqFasterSpan/SumSpan.cs index b9b1cbb..62cb45e 100644 --- a/LinqFaster/SumSpan.cs +++ b/LinqFasterSpan/SumSpan.cs @@ -1,14 +1,14 @@ using System; using System.Globalization; using System.Runtime.CompilerServices; - using JM.LinqFaster.Utils; + // ReSharper disable ForCanBeConvertedToForeach // ReSharper disable MemberCanBePrivate.Global -namespace JM.LinqFaster +namespace JM.LinqFasterSpan { - public static partial class LinqFaster + public static partial class LinqFasterSpan { /* * Since Span is actually a struct and it does not inherit from IEnumerable, diff --git a/LinqFasterSpan/Take.cs b/LinqFasterSpan/Take.cs new file mode 100644 index 0000000..15d9dac --- /dev/null +++ b/LinqFasterSpan/Take.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + /*---- spans ---- */ + /// + /// Returns a specified number of contiguous elements from the start of a sequence. + /// + /// The sequence to return elements from. + /// The number of elements to return. + /// A sequence that contains the specified number of elements from the start of the input sequence. + public static T[] TakeF(this Span source, int count) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (count < 0) + { + count = 0; + } + else if (count > source.Length) + { + count = source.Length; + } + + T[] result = new T[count]; + for (int i = 0; i < result.Length; i++) + { + result[i] = source[i]; + } + return result; + } + + + /// + /// Returns elements from a sequence as long as a specified condition is true. + /// + /// A sequence to return elements from. + /// A function to test each element for a condition. + /// A sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes. + public static T[] TakeWhileF(this Span source, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + int count = 0; + for (; count < source.Length; count++) + { + if (!predicate(source[count])) + break; + } + T[] result = new T[count]; + for (int i = 0; i < result.Length; i++) + { + result[i] = source[i]; + } + return result; + } + + /// + /// Returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function. + /// + /// The sequence to return elements from. + /// A function to test each source element for a condition; the second parameter of the function represents the index of the source element. + /// A sequence that contains elements from the input sequence that occur before the element at which the test no longer passes. + public static T[] TakeWhileF(this Span source, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + int count = 0; + for (; count < source.Length; count++) + { + if (!predicate(source[count], count)) + break; + } + T[] result = new T[count]; + for (int i = 0; i < result.Length; i++) + { + result[i] = source[i]; + } + return result; + } + + } +} diff --git a/LinqFasterSpan/Where.cs b/LinqFasterSpan/Where.cs new file mode 100644 index 0000000..4870b9c --- /dev/null +++ b/LinqFasterSpan/Where.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + + public static partial class LinqFasterSpan + { + + // -------------------------- Spans -------------------------------------------- + + /// + /// Filters a sequence of values based on a predicate. + /// + /// A sequence to filter. + /// A function to test each element for a condition. + /// A sequence that contains elements from the input sequence that satisfy the condition. + public static T[] WhereF(this Span source, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + T[] result = new T[source.Length]; + int idx = 0; + for (int i = 0; i < source.Length; i++) + { + if (predicate(source[i])) + { + result[idx] = source[i]; + idx++; + } + } + Array.Resize(ref result, idx); + return result; + } + + /// + /// Filters a sequence of values based on a predicate that includes the index in it's logic. + /// + /// A sequence to filter. + /// A function to test each element for a condition along with the element's index. + /// A sequence that contains elements from the input sequence that satisfy the condition. + public static T[] WhereF(this Span source, Func predicate) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + + T[] result = new T[source.Length]; + int idx = 0; + for (int i = 0; i < source.Length; i++) + { + if (predicate(source[i], i)) + { + result[idx] = source[i]; + idx++; + } + } + Array.Resize(ref result, idx); + return result; + } + + } +} diff --git a/LinqFasterSpan/WhereAggregate.cs b/LinqFasterSpan/WhereAggregate.cs new file mode 100644 index 0000000..a7b4136 --- /dev/null +++ b/LinqFasterSpan/WhereAggregate.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + + public static partial class LinqFasterSpan + { + + // ----------------------------- Spans ------------------ + + /// + /// Combines Where and Aggregate for optimal performance + /// + /// The input to filter then aggregate. + /// The function to filter the input sequence with. + /// The function to aggregate the filtered sequence. + /// The filtered then aggregated sequence. + public static T WhereAggregateF(this Span source, Func predicate, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + if (func == null) + { + throw Error.ArgumentNull("func"); + } + + T result = default(T); + + int i = 0; + for (; i < source.Length; i++) + { + if (predicate(source[i])) + { + result = source[i]; + i++; + break; + } + } + for (; i < source.Length; i++) + { + if (predicate(source[i])) + { + result = func(result, source[i]); + } + } + return result; + } + + /// + /// Combines Where and Aggregate with index for optimal performance + /// + /// The input to filter then aggregate. + /// The function to filter the input sequence and it's index with. + /// The function to aggregate the filtered sequence. + /// The filtered then aggregated sequence. + public static T WhereAggregateF(this Span source, Func predicate, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + T result = default(T); + + int i = 0; + for (; i < source.Length; i++) + { + if (predicate(source[i], i)) + { + result = source[i]; + i++; + break; + } + } + for (; i < source.Length; i++) + { + if (predicate(source[i], i)) + { + result = func(result, source[i]); + } + } + return result; + } + + /// + /// Combines Where and Aggregate for optimal performance with a starting seed. + /// + /// The input to filter then aggregate. + /// The function to filter the input sequence with. + /// The initial value to aggregate on. + /// The function to aggregate the filtered sequence. + /// The filtered then aggregated sequence. + public static TAccumulate WhereAggregateF(this Span source, Func predicate, TAccumulate seed, Func func) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull("func"); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + TAccumulate result = seed; + foreach (TSource v in source) + { + if (predicate(v)) + result = func(result, v); + } + return result; + } + + /// + /// Combines Where and Aggregate for optimal performance with a starting seed and a result transformation. + /// + /// The input to filter then aggregate. + /// The function to filter the input sequence with. + /// The initial value to aggregate on. + /// The function to aggregate the filtered sequence. + /// A function to transform the final result. + /// The filtered then aggregated then transformed sequence. + public static TResult WhereAggregateF(this Span source, Func predicate, TAccumulate seed, Func func, Func resultSelector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (func == null) + { + throw Error.ArgumentNull("func"); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + if (resultSelector == null) + { + throw Error.ArgumentNull("resultSelector"); + } + + TAccumulate result = seed; + int count = 0; + foreach (TSource v in source) + { + if (predicate(v)) + { + result = func(result, v); + count++; + } + } + return resultSelector(result); + } + } +} \ No newline at end of file diff --git a/LinqFasterSpan/WhereSelect.cs b/LinqFasterSpan/WhereSelect.cs new file mode 100644 index 0000000..6110787 --- /dev/null +++ b/LinqFasterSpan/WhereSelect.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + + public static partial class LinqFasterSpan + { + + + // -------------------------- SPANS -------------------------------------------- + + + /// + /// Combined Where and Select for optimal performance. + /// + /// The input sequence to filter then transform. + /// A function to use to filter the sequence. + /// A function to transform the filtered elements. + /// A sequence of filtered and transformed elements. + public static TResult[] WhereSelectF(this Span source, Func predicate, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + if (selector == null) + { + throw Error.ArgumentNull("predicate"); + } + + TResult[] result = new TResult[source.Length]; + int idx = 0; + for (int i = 0; i < source.Length; i++) + { + if (predicate(source[i])) + { + result[idx] = selector(source[i]); + idx++; + } + } + Array.Resize(ref result, idx); + return result; + } + + /// + /// Combined Where and Select for optimal performance that uses the index in the + /// predicate and selector. + /// + /// The input sequence to filter then transform. + /// A function to use to filter the sequence. + /// A function to transform the filtered elements. + /// A sequence of filtered and transformed elements. + public static TResult[] WhereSelectF(this Span source, Func predicate, Func selector) + { + if (source == null) + { + throw Error.ArgumentNull(nameof(source)); + } + + if (predicate == null) + { + throw Error.ArgumentNull("predicate"); + } + + if (selector == null) + { + throw Error.ArgumentNull("predicate"); + } + + TResult[] result = new TResult[source.Length]; + int idx = 0; + for (int i = 0; i < source.Length; i++) + { + if (predicate(source[i], i)) + { + result[idx] = selector(source[i], idx); + idx++; + } + } + Array.Resize(ref result, idx); + return result; + } + + } +} diff --git a/LinqFaster/WhereSumSpan.cs b/LinqFasterSpan/WhereSumSpan.cs similarity index 99% rename from LinqFaster/WhereSumSpan.cs rename to LinqFasterSpan/WhereSumSpan.cs index 39b2bf4..3d00dc6 100644 --- a/LinqFaster/WhereSumSpan.cs +++ b/LinqFasterSpan/WhereSumSpan.cs @@ -6,9 +6,9 @@ // ReSharper disable ForCanBeConvertedToForeach // ReSharper disable MemberCanBePrivate.Global -namespace JM.LinqFaster +namespace JM.LinqFasterSpan { - public static partial class LinqFaster + public static partial class LinqFasterSpan { /* * Since Span is actually a struct and it does not inherit from IEnumerable, diff --git a/LinqFasterSpan/Zip.cs b/LinqFasterSpan/Zip.cs new file mode 100644 index 0000000..2f92f2e --- /dev/null +++ b/LinqFasterSpan/Zip.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; + +namespace JM.LinqFasterSpan +{ + public static partial class LinqFasterSpan + { + + /// + /// Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results. + /// + /// The first sequence to merge. + /// The second sequence to merge. + /// A function that specifies how to merge the elements from the two sequences. + /// A sequence that contains merged elements of two input sequences. + public static R[] ZipF(this Span first, Span second, Func selector) + { + if (first == null) + { + throw Error.ArgumentNull("first"); + } + if (second == null) + { + throw Error.ArgumentNull("second"); + } + if (selector == null) + { + throw Error.ArgumentNull(nameof(selector)); + } + + //maintain array bounds elision + if (first.Length < second.Length) + { + R[] result = new R[first.Length]; + for (int i = 0; i < first.Length; i++) + { + result[i] = selector(first[i], second[i]); + } + return result; + + } + else + { + R[] result = new R[second.Length]; + for (int i = 0; i < second.Length; i++) + { + result[i] = selector(first[i], second[i]); + } + return result; + } + + } + } +} diff --git a/LinqFasterSpan/readme.txt b/LinqFasterSpan/readme.txt new file mode 100644 index 0000000..50c1d24 --- /dev/null +++ b/LinqFasterSpan/readme.txt @@ -0,0 +1,21 @@ +LinqFaster + + +Usage Guide +-------------------------------------------------------------------------- +LinqFasterSpan provides specialized versions of the Linq extensions methods +optimized for working with Span and ReadOnlySpan. LinqFaster methods use the +same names as Linq, but with an F (for Fast) appended to them so that +you can use LinqFaster alongside regular Linq. The semantics are identical +except for OrderBy which does not do a stable sort like Linq does. + +Examples +-------------------------------------------------------------------------- + + + +Limitations +-------------------------------------------------------------------------- +These are purely imperative implementations of the same higher order +functions that Linq provides, but unlike Linq they are not lazily evaluated. +This means that when chaining functions together such as: diff --git a/Tests/AggregateTests.cs b/Tests/AggregateTests.cs index 103a58c..98cb8b3 100644 --- a/Tests/AggregateTests.cs +++ b/Tests/AggregateTests.cs @@ -1,7 +1,11 @@ using System; using System.Linq; + using JM.LinqFaster; +using JM.LinqFasterSpan; + using NUnit.Framework; + using static Tests.Test; namespace Tests diff --git a/Tests/AnyAllTests.cs b/Tests/AnyAllTests.cs index e43ec0c..5b612a0 100644 --- a/Tests/AnyAllTests.cs +++ b/Tests/AnyAllTests.cs @@ -1,27 +1,30 @@ -using NUnit.Framework; +using System.Linq; + using JM.LinqFaster; -using System.Linq; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class AnyAllTests + internal class AnyAllTests { - + [Test] public void AllArray() - { + { bool a = intArray.AllF(x => x % 2 == 0); bool b = intArray.All(x => x % 2 == 0); - Assert.That(a, Is.EqualTo(b)); + Assert.That(a, Is.EqualTo(b)); } [Test] public void AllList() - { + { bool a = intList.AllF(x => x % 2 == 0); bool b = intList.All(x => x % 2 == 0); @@ -31,13 +34,13 @@ public void AllList() [Test] public void AnyArray() { - + bool a = intArray.AnyF(); bool b = intArray.Any(); Assert.That(a, Is.EqualTo(b)); - + a = intArray.AnyF(); b = intArray.Any(); @@ -57,7 +60,7 @@ public void AnyArray() [Test] public void AnyList() - { + { bool a = intList.AnyF(); bool b = intList.Any(); diff --git a/Tests/ContainsTests.cs b/Tests/ContainsTests.cs index e0aab69..ecaddbc 100644 --- a/Tests/ContainsTests.cs +++ b/Tests/ContainsTests.cs @@ -1,24 +1,30 @@ -using NUnit.Framework; -using JM.LinqFaster; +using System.Collections.Generic; using System.Linq; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; -using System.Collections.Generic; namespace Tests { [TestFixture] - class ContainsTests { + internal class ContainsTests + { [Test] - public void ContainsStringArrayTrue() { - bool a = stringArray.ContainsF("0",EqualityComparer.Default); + public void ContainsStringArrayTrue() + { + bool a = stringArray.ContainsF("0", EqualityComparer.Default); bool b = stringArray.Contains("0", EqualityComparer.Default); - Assert.That(a, Is.EqualTo(b)); + Assert.That(a, Is.EqualTo(b)); } [Test] - public void ContainsStringArrayFalse() { + public void ContainsStringArrayFalse() + { bool a = stringArray.ContainsF("No Match", EqualityComparer.Default); bool b = stringArray.Contains("No Match", EqualityComparer.Default); @@ -26,7 +32,8 @@ class ContainsTests { } [Test] - public void ContainsStringListTrue() { + public void ContainsStringListTrue() + { bool a = stringList.ContainsF("0", EqualityComparer.Default); bool b = stringList.Contains("0", EqualityComparer.Default); @@ -34,7 +41,8 @@ class ContainsTests { } [Test] - public void ContainsStringListFalse() { + public void ContainsStringListFalse() + { bool a = stringList.ContainsF("no match", EqualityComparer.Default); bool b = stringList.Contains("no match", EqualityComparer.Default); diff --git a/Tests/CountTests.cs b/Tests/CountTests.cs index 131fd4d..a21726c 100644 --- a/Tests/CountTests.cs +++ b/Tests/CountTests.cs @@ -1,24 +1,30 @@ -using NUnit.Framework; +using System.Linq; + using JM.LinqFaster; -using System.Linq; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class CountTests { + internal class CountTests + { [Test] - public void CountArray() { + public void CountArray() + { int a = intArray.CountF(onlyEvenInts); int b = intArray.Count(onlyEvenInts); - Assert.That(a, Is.EqualTo(b)); + Assert.That(a, Is.EqualTo(b)); } - + [Test] - public void CountList() { + public void CountList() + { int a = intList.CountF(onlyEvenInts); int b = intList.Count(onlyEvenInts); diff --git a/Tests/DistinctTests.cs b/Tests/DistinctTests.cs index 727e6dd..345e577 100644 --- a/Tests/DistinctTests.cs +++ b/Tests/DistinctTests.cs @@ -3,9 +3,10 @@ namespace Tests { [TestFixture] - class DistinctTests { + internal class DistinctTests + { + - } } diff --git a/Tests/FirstTests.cs b/Tests/FirstTests.cs index 7ceaf97..d69f5ad 100644 --- a/Tests/FirstTests.cs +++ b/Tests/FirstTests.cs @@ -1,51 +1,61 @@ -using NUnit.Framework; +using System.Linq; + using JM.LinqFaster; -using System.Linq; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class FirstTests { + internal class FirstTests + { [Test] - public void FirstArray() { + public void FirstArray() + { int a = intArray.FirstF(); int b = intArray.First(); Assert.That(a, Is.EqualTo(b)); } [Test] - public void FirstArrayPredicate() { + public void FirstArrayPredicate() + { int a = intArray.FirstF(x => x > 0); int b = intArray.First(x => x > 0); Assert.That(a, Is.EqualTo(b)); } [Test] - public void FirstOrDefaultArray() { + public void FirstOrDefaultArray() + { int a = intArray.FirstOrDefaultF(x => x > 99999); - int b = intArray.FirstOrDefault(x => x > 99999); + int b = intArray.FirstOrDefault(x => x > 99999); Assert.That(a, Is.EqualTo(b)); } [Test] - public void FirstList() { + public void FirstList() + { int a = intList.FirstF(); int b = intList.First(); Assert.That(a, Is.EqualTo(b)); } [Test] - public void FirstListPredicate() { + public void FirstListPredicate() + { int a = intList.FirstF(x => x > 0); int b = intList.First(x => x > 0); Assert.That(a, Is.EqualTo(b)); } [Test] - public void FirstOrDefaultList() { + public void FirstOrDefaultList() + { int a = intList.FirstOrDefaultF(x => x > 99999); int b = intList.FirstOrDefault(x => x > 99999); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/LastTests.cs b/Tests/LastTests.cs index eb3308c..3c75645 100644 --- a/Tests/LastTests.cs +++ b/Tests/LastTests.cs @@ -1,51 +1,61 @@ -using NUnit.Framework; +using System.Linq; + using JM.LinqFaster; -using System.Linq; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class LastTests { + internal class LastTests + { [Test] - public void LastArray() { + public void LastArray() + { int a = intArray.LastF(); int b = intArray.Last(); Assert.That(a, Is.EqualTo(b)); } [Test] - public void LastArrayPredicate() { + public void LastArrayPredicate() + { int a = intArray.LastF(x => x > 0); int b = intArray.Last(x => x > 0); Assert.That(a, Is.EqualTo(b)); } [Test] - public void LastOrDefaultArray() { + public void LastOrDefaultArray() + { int a = intArray.LastOrDefaultF(x => x > 99999); - int b = intArray.LastOrDefault(x => x > 99999); + int b = intArray.LastOrDefault(x => x > 99999); Assert.That(a, Is.EqualTo(b)); } [Test] - public void LastList() { + public void LastList() + { int a = intList.LastF(); int b = intList.Last(); Assert.That(a, Is.EqualTo(b)); } [Test] - public void LastListPredicate() { + public void LastListPredicate() + { int a = intList.LastF(x => x > 0); int b = intList.Last(x => x > 0); Assert.That(a, Is.EqualTo(b)); } [Test] - public void LastOrDefaultList() { + public void LastOrDefaultList() + { int a = intList.LastOrDefaultF(x => x > 99999); int b = intList.LastOrDefault(x => x > 99999); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/MaxTests.cs b/Tests/MaxTests.cs index ca9d248..303691b 100644 --- a/Tests/MaxTests.cs +++ b/Tests/MaxTests.cs @@ -1,22 +1,25 @@ -using NUnit.Framework; -using JM.LinqFaster; -using System.Linq; +using System; using System.Collections.Generic; -using System; +using System.Linq; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class MaxTests - { + internal class MaxTests + { public void HelperMax(T[] array) where T : IComparable { T a = array.MaxF(); T b = array.Max(); - Assert.That(a, Is.EqualTo(b)); + Assert.That(a, Is.EqualTo(b)); } public void HelperMax(List list) @@ -28,7 +31,7 @@ public void HelperMax(List list) Assert.That(a, Is.EqualTo(b)); } - public void HelperMax(T[] array, Func selector) + public void HelperMax(T[] array, Func selector) where U : IComparable { U a = array.MaxF(selector); @@ -37,7 +40,7 @@ public void HelperMax(List list) //Assert.That(a, Is.EqualTo(b)); } - public void HelperMax(List list, Func selector) + public void HelperMax(List list, Func selector) where U : IComparable { U a = list.MaxF(selector); diff --git a/Tests/OrderByTests.cs b/Tests/OrderByTests.cs index 91ab72e..46a43ef 100644 --- a/Tests/OrderByTests.cs +++ b/Tests/OrderByTests.cs @@ -1,53 +1,62 @@ -using NUnit.Framework; -using JM.LinqFaster; -using System; +using System; using System.Collections.Generic; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class OrderByTests + internal class OrderByTests { [Test] public void OrderByArray() { - Func lambda1 = (x => x*x); + Func lambda1 = (x => x * x); int[] a = intArray.OrderByF(lambda1); - for (int i = 0; i < a.Length-1;i++) + for (int i = 0; i < a.Length - 1; i++) { - Assert.That(lambda1(a[i]), Is.LessThanOrEqualTo(lambda1(a[i+1]))); + Assert.That(lambda1(a[i]), Is.LessThanOrEqualTo(lambda1(a[i + 1]))); } - + } [Test] - public void OrderByDescendingArray() { + public void OrderByDescendingArray() + { Func lambda1 = (x => x * x); int[] a = intArray.OrderByDescendingF(lambda1); - - for (int i = 0; i < a.Length - 1; i++) { + + for (int i = 0; i < a.Length - 1; i++) + { Assert.That(lambda1(a[i]), Is.GreaterThanOrEqualTo(lambda1(a[i + 1]))); } - + } [Test] - public void OrderByList() { + public void OrderByList() + { Func lambda1 = (x => x * x); List a = intList.OrderByF(lambda1); - for (int i = 0; i < a.Count - 1; i++) { + for (int i = 0; i < a.Count - 1; i++) + { Assert.That(lambda1(a[i]), Is.LessThanOrEqualTo(lambda1(a[i + 1]))); } } [Test] - public void OrderByDescendingList() { + public void OrderByDescendingList() + { Func lambda1 = (x => x * x); List a = intList.OrderByDescendingF(lambda1); - for (int i = 0; i < a.Count - 1; i++) { + for (int i = 0; i < a.Count - 1; i++) + { Assert.That(lambda1(a[i]), Is.GreaterThanOrEqualTo(lambda1(a[i + 1]))); } diff --git a/Tests/RangeTests.cs b/Tests/RangeTests.cs index 2932381..7de263c 100644 --- a/Tests/RangeTests.cs +++ b/Tests/RangeTests.cs @@ -1,12 +1,14 @@ using System.Collections.Generic; -using NUnit.Framework; -using JM.LinqFaster; using System.Linq; +using JM.LinqFaster; + +using NUnit.Framework; + namespace Tests { [TestFixture] - class RangeTests + internal class RangeTests { [Test] public void RangeArray() diff --git a/Tests/RepeatTests.cs b/Tests/RepeatTests.cs index 362966a..f8003e3 100644 --- a/Tests/RepeatTests.cs +++ b/Tests/RepeatTests.cs @@ -1,15 +1,18 @@ using System.Collections.Generic; using System.Linq; + using JM.LinqFaster; + using NUnit.Framework; namespace Tests { [TestFixture] - class RepeatTests + internal class RepeatTests { [Test] - public void RepeatArray() { + public void RepeatArray() + { float[] a = LinqFaster.RepeatArrayF(2.0f, 10); List b = Enumerable.Repeat(2.0f, 10).ToList(); diff --git a/Tests/ReverseTests.cs b/Tests/ReverseTests.cs index 848e345..e540ee5 100644 --- a/Tests/ReverseTests.cs +++ b/Tests/ReverseTests.cs @@ -1,17 +1,23 @@ -using NUnit.Framework; -using JM.LinqFaster; -using System.Linq; -using System; +using System; using System.Collections.Generic; +using System.Linq; + +using JM.LinqFaster; +using JM.LinqFasterSpan; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class ReverseTests { + internal class ReverseTests + { [Test] - public void ReverseArray() { + public void ReverseArray() + { int[] a = intArray.ReverseF(); int[] aSpan = intArray.AsSpan().ReverseF(); IEnumerable b = intArray.Reverse(); @@ -21,7 +27,8 @@ class ReverseTests { } [Test] - public void ReverseList() { + public void ReverseList() + { List a = intList.ReverseF(); List b = intList.Select(x => x).ToList(); b.Reverse(); diff --git a/Tests/SelectManyTests.cs b/Tests/SelectManyTests.cs index 4ac04e1..295855c 100644 --- a/Tests/SelectManyTests.cs +++ b/Tests/SelectManyTests.cs @@ -1,13 +1,16 @@ using System.Collections.Generic; -using NUnit.Framework; -using JM.LinqFaster; using System.Linq; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class SelectManyTests + internal class SelectManyTests { [Test] @@ -18,8 +21,8 @@ public void SelectManyArray() Assert.That(a, Is.EqualTo(b)); - a = floatArray.SelectManyF((x,i) => LinqFaster.RepeatArrayF(x+i, 2)); - b = floatArray.SelectMany((x,i) => Enumerable.Repeat(x+i, 2).ToArray()).ToArray(); + a = floatArray.SelectManyF((x, i) => LinqFaster.RepeatArrayF(x + i, 2)); + b = floatArray.SelectMany((x, i) => Enumerable.Repeat(x + i, 2).ToArray()).ToArray(); Assert.That(a, Is.EqualTo(b)); } diff --git a/Tests/SelectTEsts.cs b/Tests/SelectTEsts.cs index 719e524..3dc359c 100644 --- a/Tests/SelectTEsts.cs +++ b/Tests/SelectTEsts.cs @@ -1,14 +1,17 @@ using System; using System.Collections.Generic; -using NUnit.Framework; -using JM.LinqFaster; using System.Linq; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class SelectTests + internal class SelectTests { [Test] public void SelectArray() @@ -19,7 +22,7 @@ public void SelectArray() Assert.That(a, Is.EqualTo(b)); int b1 = Array.AsReadOnly(intArray).SumF(x => x * x); - a = intArray.SelectF((x, i) => x + i); + a = intArray.SelectF((x, i) => x + i); b = intArray.Select((x, i) => x + i); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/SelectWhereTests.cs b/Tests/SelectWhereTests.cs index a9d8577..c774358 100644 --- a/Tests/SelectWhereTests.cs +++ b/Tests/SelectWhereTests.cs @@ -1,30 +1,34 @@ using System.Collections.Generic; -using NUnit.Framework; -using JM.LinqFaster; using System.Linq; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class SelectWhereTests + internal class SelectWhereTests { [Test] public void SelectWhereArray() { - int[] a = intArray.SelectWhereF(squaredInts,onlyEvenInts); + int[] a = intArray.SelectWhereF(squaredInts, onlyEvenInts); IEnumerable b = intArray.Select(squaredInts).Where(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); - a = intArray.SelectWhereF((x, i) => x + i, (x,i) => x % 2 == 0); + a = intArray.SelectWhereF((x, i) => x + i, (x, i) => x % 2 == 0); b = intArray.Select((x, i) => x + i).Where(onlyEvenInts); Assert.That(a, Is.EqualTo(b)); } [Test] - public void SelectWhereList() { + public void SelectWhereList() + { List a = intList.SelectWhereF(squaredInts, onlyEvenInts); IEnumerable b = intList.Select(squaredInts).Where(onlyEvenInts); diff --git a/Tests/SequenceEqualsTests.cs b/Tests/SequenceEqualsTests.cs index 348e9bb..ff925fa 100644 --- a/Tests/SequenceEqualsTests.cs +++ b/Tests/SequenceEqualsTests.cs @@ -1,15 +1,21 @@ -using NUnit.Framework; -using JM.LinqFaster; +using System.Collections.Generic; using System.Linq; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; -using System.Collections.Generic; -namespace Tests { +namespace Tests +{ [TestFixture] - class SequenceEqualsTests { + internal class SequenceEqualsTests + { [Test] - public void SequenceEqualArray() { + public void SequenceEqualArray() + { int[] intArray2 = (int[])intArray.Clone(); bool a = LinqFaster.SequenceEqualF(intArray, intArray2); bool b = Enumerable.SequenceEqual(intArray, intArray2); @@ -18,7 +24,8 @@ class SequenceEqualsTests { } [Test] - public void SequenceNotEqualArray() { + public void SequenceNotEqualArray() + { int[] intArray2 = (int[])intArray.Clone(); intArray2[3] = -10; bool a = LinqFaster.SequenceEqualF(intArray, intArray2); @@ -28,7 +35,8 @@ class SequenceEqualsTests { } [Test] - public void SequenceEqualList() { + public void SequenceEqualList() + { List intList2 = intList.ToList(); bool a = LinqFaster.SequenceEqualF(intList, intList2); bool b = Enumerable.SequenceEqual(intList, intList2); @@ -37,7 +45,8 @@ class SequenceEqualsTests { } [Test] - public void SequenceNotEqualList() { + public void SequenceNotEqualList() + { List testList = intList.ToList(); testList[3] = -10; bool a = LinqFaster.SequenceEqualF(intList, testList); @@ -47,7 +56,8 @@ class SequenceEqualsTests { } [Test] - public void SequenceEqualListAndArray() { + public void SequenceEqualListAndArray() + { bool a = LinqFaster.SequenceEqualF(intList, intArray); bool b = Enumerable.SequenceEqual(intList, intArray); @@ -55,7 +65,8 @@ class SequenceEqualsTests { } [Test] - public void SequenceNotEqualListAndArray() { + public void SequenceNotEqualListAndArray() + { List testList = new List(); int[] testArray = { 1, 2, 3, 4, }; testList.Add(1); diff --git a/Tests/SingleTests.cs b/Tests/SingleTests.cs index 3976896..d718561 100644 --- a/Tests/SingleTests.cs +++ b/Tests/SingleTests.cs @@ -1,40 +1,50 @@ -using NUnit.Framework; +using System; +using System.Collections.Generic; + using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; -using System.Collections.Generic; -using System; namespace Tests { [TestFixture] - class SingleTests { + internal class SingleTests + { - public int SingleArrayFunc() { + public int SingleArrayFunc() + { return intArray.SingleF(onlyEvenInts); } - public int SingleOrDefaultArrayFunc() { + public int SingleOrDefaultArrayFunc() + { return intArray.SingleOrDefaultF(onlyEvenInts); } - public int SingleListFunc() { + public int SingleListFunc() + { return intList.SingleF(onlyEvenInts); } - public int SingleOrDefaultListFunc() { + public int SingleOrDefaultListFunc() + { return intList.SingleOrDefaultF(onlyEvenInts); } [Test] - public void SingleArrayMoreThanOne() { + public void SingleArrayMoreThanOne() + { Assert.Throws(() => intArray.SingleF()); Assert.That(SingleArrayFunc, Throws.Exception); } [Test] - public void SingleArrayOne() { + public void SingleArrayOne() + { int[] test = { 4 }; int a = test.SingleF(); @@ -46,7 +56,8 @@ class SingleTests { } [Test] - public void SingleArrayDefaultOne() { + public void SingleArrayDefaultOne() + { int[] test = { 4 }; int a = test.SingleOrDefaultF(); @@ -57,7 +68,8 @@ class SingleTests { } [Test] - public void SingleArrayDefaultEmpty() { + public void SingleArrayDefaultEmpty() + { int[] test = { }; int a = test.SingleOrDefaultF(); @@ -68,7 +80,8 @@ class SingleTests { } [Test] - public void SingleArrayDefaultMoreThanOne() { + public void SingleArrayDefaultMoreThanOne() + { Assert.Throws(() => intArray.SingleOrDefaultF()); Assert.That(SingleOrDefaultArrayFunc, Throws.Exception); } @@ -76,15 +89,19 @@ class SingleTests { // List [Test] - public void SingleListMoreThanOne() { + public void SingleListMoreThanOne() + { Assert.Throws(() => intList.SingleF()); Assert.That(SingleListFunc, Throws.Exception); } [Test] - public void SingleListOne() { - List test = new List(); - test.Add(4); + public void SingleListOne() + { + List test = new List + { + 4 + }; int a = test.SingleF(); int b = test.SingleF(onlyEvenInts); @@ -93,9 +110,12 @@ class SingleTests { } [Test] - public void SingleListDefaultOne() { - List test = new List(); - test.Add(4); + public void SingleListDefaultOne() + { + List test = new List + { + 4 + }; int a = test.SingleOrDefaultF(); int b = test.SingleOrDefaultF(onlyEvenInts); @@ -105,8 +125,9 @@ class SingleTests { } [Test] - public void SingleListDefaultEmpty() { - List test = new List(); + public void SingleListDefaultEmpty() + { + List test = new List(); int a = test.SingleOrDefaultF(); int b = test.SingleOrDefaultF(onlyEvenInts); @@ -115,7 +136,8 @@ class SingleTests { } [Test] - public void SingleListDefaultMoreThanOne() { + public void SingleListDefaultMoreThanOne() + { Assert.Throws(() => intList.SingleOrDefaultF()); Assert.That(SingleOrDefaultListFunc, Throws.Exception); } diff --git a/Tests/SkipTests.cs b/Tests/SkipTests.cs index dfd1ac3..6314186 100644 --- a/Tests/SkipTests.cs +++ b/Tests/SkipTests.cs @@ -1,27 +1,33 @@ using System.Collections.Generic; -using NUnit.Framework; -using JM.LinqFaster; using System.Linq; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class SkipTests { + internal class SkipTests + { [Test] [TestCase(0)] [TestCase(5)] [TestCase(Test.TEST_SIZE)] - public void SkipArray(int count) { + public void SkipArray(int count) + { int[] a = intArray.SkipF(count); IEnumerable b = intArray.Skip(count); Assert.That(a, Is.EqualTo(b)); } - [Test] - public void SkipWhileArray() { + [Test] + public void SkipWhileArray() + { int[] a = intArray.SkipWhileF(onlyEvenInts); IEnumerable b = intArray.SkipWhile(onlyEvenInts); @@ -32,7 +38,8 @@ class SkipTests { [TestCase(0)] [TestCase(5)] [TestCase(Test.TEST_SIZE)] - public void SkipList(int count) { + public void SkipList(int count) + { List a = intList.SkipF(count); IEnumerable b = intList.Skip(count); @@ -40,7 +47,8 @@ class SkipTests { } [Test] - public void SkipWhileList() { + public void SkipWhileList() + { List a = intList.SkipWhileF(onlyEvenInts); IEnumerable b = intList.SkipWhile(onlyEvenInts); diff --git a/Tests/TakeTests.cs b/Tests/TakeTests.cs index 0577de7..63b5ef9 100644 --- a/Tests/TakeTests.cs +++ b/Tests/TakeTests.cs @@ -1,20 +1,26 @@ -using NUnit.Framework; -using JM.LinqFaster; -using System.Linq; -using System; +using System; using System.Collections.Generic; +using System.Linq; + +using JM.LinqFaster; +using JM.LinqFasterSpan; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class TakeTests { + internal class TakeTests + { [Test] [TestCase(0)] [TestCase(5)] [TestCase(TEST_SIZE)] - public void TakeArray(int count) { + public void TakeArray(int count) + { int[] a = intArray.TakeF(count); int[] aSpan = intArray.AsSpan().TakeF(count); @@ -25,7 +31,8 @@ class TakeTests { } [Test] - public void TakeWhileArray() { + public void TakeWhileArray() + { int[] a = intArray.TakeWhileF(onlyEvenInts); int[] aSpan = intArray.AsSpan().TakeWhileF(onlyEvenInts); IEnumerable b = intArray.TakeWhile(onlyEvenInts); @@ -39,7 +46,8 @@ class TakeTests { [TestCase(0)] [TestCase(5)] [TestCase(TEST_SIZE)] - public void TakeList(int count) { + public void TakeList(int count) + { List a = intList.TakeF(count); IEnumerable b = intList.Take(count); @@ -48,7 +56,8 @@ class TakeTests { } [Test] - public void TakeWhileList() { + public void TakeWhileList() + { List a = intList.TakeWhileF(onlyEvenInts); IEnumerable b = intList.TakeWhile(onlyEvenInts); diff --git a/Tests/Test.cs b/Tests/Test.cs index 120f3f6..00ebf94 100644 --- a/Tests/Test.cs +++ b/Tests/Test.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; + using NUnit.Framework; namespace Tests @@ -63,11 +64,11 @@ public void Setup() longArray = new long[TEST_SIZE]; longList = new List(TEST_SIZE); Random rand = new Random(); - for (int i = 0; i < intArray.Length;i++) + for (int i = 0; i < intArray.Length; i++) { intArray[i] = rand.Next(-100, 100); - byteArray[i] = (byte) intArray[i]; - shortArray[i] = (short) intArray[i]; + byteArray[i] = (byte)intArray[i]; + shortArray[i] = (short)intArray[i]; intNullArray[i] = intArray[i]; intList.Add(intArray[i]); longArray[i] = intArray[i]; @@ -90,6 +91,6 @@ public Test() } - + } } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 92a5bda..18153f3 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -127,6 +127,10 @@ {050c43b5-4a4f-45d9-be0c-9b2a6acc189e} LinqFasterSIMD + + {68835792-9274-4ddc-8312-29700ef16f62} + LinqFasterSpan + {5b2f0f9f-6dda-4f06-a999-26e43ae04f86} LinqFaster diff --git a/Tests/WhereAggregateTests.cs b/Tests/WhereAggregateTests.cs index ea40341..8596808 100644 --- a/Tests/WhereAggregateTests.cs +++ b/Tests/WhereAggregateTests.cs @@ -1,12 +1,15 @@ -using NUnit.Framework; +using System.Linq; + using JM.LinqFaster; -using System.Linq; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class WhereAggregateTests + internal class WhereAggregateTests { [Test] public void WhereAggregateSumArray() @@ -19,25 +22,27 @@ public void WhereAggregateSumArray() int c = intArray.Where(onlyEvenInts).Sum(); Assert.That(a, Is.EqualTo(c)); - Assert.That(b, Is.EqualTo(c)); + Assert.That(b, Is.EqualTo(c)); } [Test] - public void WhereAggregateSelectorArray() { + public void WhereAggregateSelectorArray() + { int a = - intArray.WhereAggregateF(onlyEvenInts, 0, (acc, x) => acc += x, acc =>acc/2); - + intArray.WhereAggregateF(onlyEvenInts, 0, (acc, x) => acc += x, acc => acc / 2); - int b = intArray.Where(onlyEvenInts).Sum()/2; + + int b = intArray.Where(onlyEvenInts).Sum() / 2; Assert.That(a, Is.EqualTo(b)); - + } [Test] - public void WhereAggregateSumList() { + public void WhereAggregateSumList() + { int a = intList.WhereAggregateF(onlyEvenInts, 0, (acc, x) => acc += x); @@ -51,7 +56,8 @@ public void WhereAggregateSumArray() } [Test] - public void WhereAggregateSelectorList() { + public void WhereAggregateSelectorList() + { int a = intList.WhereAggregateF(onlyEvenInts, 0, (acc, x) => acc += x, acc => acc / 2); diff --git a/Tests/WhereSelectTests.cs b/Tests/WhereSelectTests.cs index d0c3983..87fe613 100644 --- a/Tests/WhereSelectTests.cs +++ b/Tests/WhereSelectTests.cs @@ -1,23 +1,26 @@ -using NUnit.Framework; -using JM.LinqFaster; -using System.Linq; -using System; +using System; using System.Collections.Generic; +using System.Linq; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class WhereSelectTests + internal class WhereSelectTests { [Test] public void WhereSelectArray() - { - int[] a = intArray.WhereSelectF(onlyEvenInts,squaredInts); + { + int[] a = intArray.WhereSelectF(onlyEvenInts, squaredInts); IEnumerable b = intArray.Where(onlyEvenInts).Select(squaredInts); Assert.That(a, Is.EqualTo(b)); - Func lambda2 = (x => x == "no matches"); + Func lambda2 = (x => x == "no matches"); string[] c = stringArray.WhereSelectF(lambda2, x => x + "append"); IEnumerable d = stringArray.Where(lambda2).Select(x => x + "append"); @@ -27,14 +30,16 @@ public void WhereSelectArray() } [Test] - public void WhereSelectIndexArray() { - int[] a = intArray.WhereSelectF((x,i) => x+i % 2 == 0, (x,i) => x+i); + public void WhereSelectIndexArray() + { + int[] a = intArray.WhereSelectF((x, i) => x + i % 2 == 0, (x, i) => x + i); IEnumerable b = intArray.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); - Assert.That(a, Is.EqualTo(b)); + Assert.That(a, Is.EqualTo(b)); } [Test] - public void WhereSelectList() { + public void WhereSelectList() + { List a = intList.WhereSelectF(onlyEvenInts, squaredInts); IEnumerable b = intList.Where(onlyEvenInts).Select(squaredInts); Assert.That(a, Is.EqualTo(b)); @@ -49,7 +54,8 @@ public void WhereSelectArray() } [Test] - public void WhereSelectIndexList() { + public void WhereSelectIndexList() + { List a = intList.WhereSelectF((x, i) => x + i % 2 == 0, (x, i) => x + i); IEnumerable b = intList.Where((x, i) => x + i % 2 == 0).Select((x, i) => x + i); Assert.That(a, Is.EqualTo(b)); diff --git a/Tests/WhereSumTEsts.cs b/Tests/WhereSumTEsts.cs index 87b85c2..517b46f 100644 --- a/Tests/WhereSumTEsts.cs +++ b/Tests/WhereSumTEsts.cs @@ -1,18 +1,21 @@ -using NUnit.Framework; +using System.Linq; + using JM.LinqFaster; -using System.Linq; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class WhereSumTests + internal class WhereSumTests { [Test] - public void WhereSumArray() + public void WhereSumArray() { int a = intArray.WhereSumF(x => x % 2 == 0); - int b = intArray.Where(x=>x%2==0).Sum(); + int b = intArray.Where(x => x % 2 == 0).Sum(); Assert.That(a, Is.EqualTo(b)); @@ -24,14 +27,15 @@ public void WhereSumArray() } [Test] - public void WhereSumArraySelector() { - int a = intArray.WhereSumF(x => x % 2 == 0,x=>x+1); - int b = intArray.Where(x => x % 2 == 0).Sum(x=>x+1); + public void WhereSumArraySelector() + { + int a = intArray.WhereSumF(x => x % 2 == 0, x => x + 1); + int b = intArray.Where(x => x % 2 == 0).Sum(x => x + 1); Assert.That(a, Is.EqualTo(b)); - float c = floatArray.WhereSumF(x => x > 0.0f,x => x / 2.0f); - float d = floatArray.Where(x => x > 0.0f).Sum(x => x/2.0f); + float c = floatArray.WhereSumF(x => x > 0.0f, x => x / 2.0f); + float d = floatArray.Where(x => x > 0.0f).Sum(x => x / 2.0f); Assert.That(c, Is.EqualTo(d)); @@ -52,7 +56,8 @@ public void WhereSumList() } [Test] - public void WhereSumListSelector() { + public void WhereSumListSelector() + { int a = intList.WhereSumF(x => x % 2 == 0, x => x + 1); int b = intList.Where(x => x % 2 == 0).Sum(x => x + 1); diff --git a/Tests/WhereTests.cs b/Tests/WhereTests.cs index e04c28a..9e585d5 100644 --- a/Tests/WhereTests.cs +++ b/Tests/WhereTests.cs @@ -1,14 +1,17 @@ -using NUnit.Framework; -using JM.LinqFaster; -using System.Linq; -using System; +using System; using System.Collections.Generic; +using System.Linq; + +using JM.LinqFaster; + +using NUnit.Framework; + using static Tests.Test; namespace Tests { [TestFixture] - class WhereTests + internal class WhereTests { [Test] @@ -22,7 +25,7 @@ public void WhereEmpty() List emptyList = new System.Collections.Generic.List(0); List b = emptyList.WhereF(x => x == 0); }); - + } diff --git a/docs/LinqFasterSpan.xml b/docs/LinqFasterSpan.xml new file mode 100644 index 0000000..09de7d5 --- /dev/null +++ b/docs/LinqFasterSpan.xml @@ -0,0 +1,1497 @@ + + + + JM.LinqFaster.Span + + + + + Provides faster array and list specific extension methods with + the same semantics as the Linq extensions methods. + + + + + Applies an accumulator function over a Span{T}. + + A Span{T} to aggregate over. + An accumulator function to be invoked on each element + The final accumulator value + + + + Applies an accumulator function over a Span{T}. The specified seed + value is used as the initial accumulator value. + + A Span{T} to aggregate over. + The initial accumulator value. + An accumulator function to be invoked on each element + The final accumulator value + + + + Applies an accumulator function over a Span{T}. The specified seed + value is used as the initial accumulator value, and the specified + function is used to select the result value. + + A Span{T} to aggregate over. + The initial accumulator value. + An accumulator function to be invoked on each element + A function to transform the final accumulator value into the result value. + The transformed final accumulator value + + + + Applies an accumulator function over a ReadOnlySpan{T}. + + A ReadOnlySpan{T} to aggregate over. + An accumulator function to be invoked on each element + The final accumulator value + + + + Applies an accumulator function over a ReadOnlySpan{T}. The specified seed + value is used as the initial accumulator value. + + A ReadOnlySpan{T} to aggregate over. + The initial accumulator value. + An accumulator function to be invoked on each element + The final accumulator value + + + + Applies an accumulator function over a ReadOnlySpan{T}. The specified seed + value is used as the initial accumulator value, and the specified + function is used to select the result value. + + A ReadOnlySpan{T} to aggregate over. + The initial accumulator value. + An accumulator function to be invoked on each element + A function to transform the final accumulator value into the result value. + The transformed final accumulator value + + + + Determines whether an array contains any elements + + The array to check for emptiness + true if the source array contains any elements, otherwise, false/ + + + + Determines whether any element of an array satisfies a condition. + + An array whose elements to apply the predicate to. + A function to test each element for a condition. + true if any elements in the source array pass the test in the specified predicate; otherwise, false. + + + + Determines whether all elements of an array satisfy a condition. + + An array that contains the elements to apply the predicate to. + A function to test each element for a condition. + true if every element of the source array passes the test in the specified + predicate, or if the array is empty; otherwise, false + + + + Computes the average of values obtained by invoking a transform function on + each element of the input array. + + The array to calculate the transformed average of. + A transform function to apply to each element. + The average of the array. + + Special case for floats to be equivalent to IEnumerable ! + + + + + Computes the average of values obtained by invoking a transform function on + each element of the input array. + + The array to calculate the transformed average of. + A transform function to apply to each element. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of values obtained by invoking a transform function on + each element of the input array. + + The array to calculate the transformed average of. + A transform function to apply to each element. + The average of the array. + + Special case for floats to be equivalent to IEnumerable ! + + + + + Computes the average of values obtained by invoking a transform function on + each element of the input array. + + The array to calculate the transformed average of. + A transform function to apply to each element. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Computes the average of an array + + The array to calculate the average of. + The average of the array. + + + + Determines whether an array contains a specified element by using the + provided IEqualityComparer. + + An array in which to locate a value. + The value to locate. + An equality comparer to compare values. + true if the source sequence contains an element that has the specified value; otherwise, false. + + + + Returns a number that represents how many elements in the specified + array satisfy a condition. + + An array that contains elements to be tested and counted. + A function to test each element for a condition. + A number that represents how many elements in the array satisfy the condition + in the predicate function. + + + + Returns source or (if needed) an array (For speed) with a single value set to default{T} + + + + source or new array{1} + + + + Returns the first element of an Span. + + The Span to return the first element of. + The first element in the specified array. + + + + Returns the first element in an Span that satisfies a specified condition. + + An Span to return an element from. + A function to test each element for a condition. + The first element that satisfies the condition. + + + + Returns the first element of an Span, or a default value if the + array contains no elements. + + The Span to return the first element of. + default value if source is empty, otherwise, the first element + in source. + + + + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. + + An Span to return an element from. + A function to test each element for a condition. + + + + + Returns the first element of an ReadOnlySpan. + + The ReadOnlySpan to return the first element of. + The first element in the specified array. + + + + Returns the first element in an ReadOnlySpan that satisfies a specified condition. + + An ReadOnlySpan to return an element from. + A function to test each element for a condition. + The first element that satisfies the condition. + + + + Returns the first element of an ReadOnlySpan, or a default value if the + array contains no elements. + + The ReadOnlySpan to return the first element of. + default value if source is empty, otherwise, the first element + in source. + + + + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. + + An ReadOnlySpan to return an element from. + A function to test each element for a condition. + + + + + Returns the first element of an Span. + + The Span to return the first element of. + The first element in the specified array. + + + + Returns the first element in an Span that satisfies a specified condition. + + An Span to return an element from. + A function to test each element for a condition. + The first element that satisfies the condition. + + + + Returns the first element of an Span, or a default value if the + array contains no elements. + + The Span to return the first element of. + default value if source is empty, otherwise, the first element + in source. + + + + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. + + An Span to return an element from. + A function to test each element for a condition. + + + + + Returns the first element of an ReadOnlySpan. + + The ReadOnlySpan to return the first element of. + The first element in the specified array. + + + + Returns the first element in an ReadOnlySpan that satisfies a specified condition. + + An ReadOnlySpan to return an element from. + A function to test each element for a condition. + The first element that satisfies the condition. + + + + Returns the first element of an ReadOnlySpan, or a default value if the + array contains no elements. + + The ReadOnlySpan to return the first element of. + default value if source is empty, otherwise, the first element + in source. + + + + Returns the first element of the sequence that satisfies a condition or a + default value if no such element is found. + + An ReadOnlySpan to return an element from. + A function to test each element for a condition. + + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the maximum value in a sequence of values. + + A sequence of values to determine the maximum of. + The maximum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the maximum value. + + A sequence of values to determine the maximum value of. + A transform function to apply to each element. + The maximum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Returns the Minimum value in a sequence of values. + + A sequence of values to determine the Minimum of. + The Minimum value in the sequence + + + + Invokes a transform function on each element of a sequence and returns the Minimum value. + + A sequence of values to determine the Minimum value of. + A transform function to apply to each element. + The Minimum value in the transform of the sequence. + + + + Inverts the order of the elements in a sequence. + + A sequence of values to reverse. + A sequence whose elements correspond to those of the input sequence in reverse order. + + + + Inverts the order of the elements in a sequence in place. + + A sequence of values to reverse. + + + + Projects each element of a sequence into a new form in place. + + A sequence of values to invoke a transform function on (map). + A transform function to apply (map) to each element. + + + + Projects each element of a sequence into a new form, in place, by incorporating the element's index. + + A sequence of values to invoke a transform function on. + A transform function to apply to each source element; the second parameter of the function represents the index of the source element. + + + + Projects each element of a sequence into a new form. (map in every other language) + + A sequence of values to invoke a transform function on (map). + A transform function to apply (map) to each element. + A sequence whose elements are the result of invoking the transform function on each element (mapping) of source. + + + + Projects each element of a sequence into a new form by incorporating the element's index. + + A sequence of values to invoke a transform function on. + A transform function to apply to each source element; the second parameter of the function represents the index of the source element. + A sequence whose elements are the result of invoking the transform function on each element of source. + + + + Projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence. + Yo dawg, I heard you like sequences. + + A sequence of values to project. + A transform function to apply to each element. + A sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence. + + + + Projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence + utilizing the index of each element. + + A sequence of values to project. + A transform function to apply to each element and it's index. + A sequence whose elements are the result of invoking the one-to-many transform function on each element and index of the input sequence. + + + + Combines Select and Where into a single call for optimal + performance. + + The input sequence to filter and select + The transformation to apply before filtering. + The predicate with which to filter result. + A sequence transformed and then filtered by selector and predicate. + + + + Combines Select and Where with indexes into a single call for optimal + performance. + + The input sequence to filter and select + The transformation with index to apply before filtering. + The predicate with index with which to filter result. + A sequence transformed and then filtered by selector and predicate with indexes. + + + + Determines whether two sequences are equal by comparing the elements by using the + provided comparer or the default equality comparer for their type if none is provided. + + A sequence to compare to second. + A sequence to compare to first. + An optional Comparer to use for the comparison. + true of the two sources are of equal length and their corresponding + elements are equal according to the equality comparer. Otherwise, false. + + + + Determines whether two sequences are equal by comparing the elements by using the + provided comparer or the default equality comparer for their type if none is provided. + + A sequence to compare to second. + A sequence to compare to first. + An optional Comparer to use for the comparison. + true of the two sources are of equal length and their corresponding + elements are equal according to the equality comparer. Otherwise, false. + + + + Determines whether two sequences are equal by comparing the elements by using the + provided comparer or the default equality comparer for their type if none is provided. + + A sequence to compare to second. + A sequence to compare to first. + An optional Comparer to use for the comparison. + true of the two sources are of equal length and their corresponding + elements are equal according to the equality comparer. Otherwise, false. + + + + Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence. + + A sequence to return the single element of + The single element of the input sequence or default if no elements exist. + + + + Returns the only element of a sequence, or the default if no elements exist, and throws an exception if there is not exactly one element in the sequence. + + A sequence to return the single element of + The single element of the input sequence + + + + Returns the only element of a sequence that satisfies a specified condition, and throws an exception if more than one such element exists. + + A sequence to return a single element from. + A function to test an element for a condition. + The single element of the input sequence that satisfies a condition. + + + + Returns the only element of a sequence that satisfies a specified condition, or a default value if + no such element exists, and throws an exception if more than one such element exists. + + A sequence to return a single element from. + A function to test an element for a condition. + The single element of the input sequence that satisfies a condition or default value if no such element is found. + + + + Bypasses a specified number of elements in a sequence and then returns the remaining elements. + + A sequence to return elements from. + The number of elements to skip before returning the remaining elements. + A sequence that contains the elements that occur after the specified index in the input sequence. + + + + Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. + + A sequence to return elements from. + A function to test each element for a condition. + A sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A transformation function. + The sum of the transformed elements. + + + + Returns a specified number of contiguous elements from the start of a sequence. + + The sequence to return elements from. + The number of elements to return. + A sequence that contains the specified number of elements from the start of the input sequence. + + + + Returns elements from a sequence as long as a specified condition is true. + + A sequence to return elements from. + A function to test each element for a condition. + A sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes. + + + + Returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function. + + The sequence to return elements from. + A function to test each source element for a condition; the second parameter of the function represents the index of the source element. + A sequence that contains elements from the input sequence that occur before the element at which the test no longer passes. + + + + Filters a sequence of values based on a predicate. + + A sequence to filter. + A function to test each element for a condition. + A sequence that contains elements from the input sequence that satisfy the condition. + + + + Filters a sequence of values based on a predicate that includes the index in it's logic. + + A sequence to filter. + A function to test each element for a condition along with the element's index. + A sequence that contains elements from the input sequence that satisfy the condition. + + + + Combines Where and Aggregate for optimal performance + + The input to filter then aggregate. + The function to filter the input sequence with. + The function to aggregate the filtered sequence. + The filtered then aggregated sequence. + + + + Combines Where and Aggregate with index for optimal performance + + The input to filter then aggregate. + The function to filter the input sequence and it's index with. + The function to aggregate the filtered sequence. + The filtered then aggregated sequence. + + + + Combines Where and Aggregate for optimal performance with a starting seed. + + The input to filter then aggregate. + The function to filter the input sequence with. + The initial value to aggregate on. + The function to aggregate the filtered sequence. + The filtered then aggregated sequence. + + + + Combines Where and Aggregate for optimal performance with a starting seed and a result transformation. + + The input to filter then aggregate. + The function to filter the input sequence with. + The initial value to aggregate on. + The function to aggregate the filtered sequence. + A function to transform the final result. + The filtered then aggregated then transformed sequence. + + + + Combined Where and Select for optimal performance. + + The input sequence to filter then transform. + A function to use to filter the sequence. + A function to transform the filtered elements. + A sequence of filtered and transformed elements. + + + + Combined Where and Select for optimal performance that uses the index in the + predicate and selector. + + The input sequence to filter then transform. + A function to use to filter the sequence. + A function to transform the filtered elements. + A sequence of filtered and transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A function to filter the sequence with before summing. + A transformation function. + The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A function to filter the sequence with before summing. + A transformation function. + The sum of the transformed elements. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A function to filter the sequence with before summing. + A transformation function. + The sum of the transformed elements. + + Special case for floats, as IEnumerable does the sums on doubles before returning the type. + + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds a sequence of values. + + The sequence to add. + A function to filter the sequence with before summing. + The sum of the sequence. + + + + Adds the transformed sequence of elements. + + The sequence of values to transform then sum. + A function to filter the sequence with before summing. + A transformation function. + The sum of the transformed elements. + + + + Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results. + + The first sequence to merge. + The second sequence to merge. + A function that specifies how to merge the elements from the two sequences. + A sequence that contains merged elements of two input sequences. + + + + checked will be done at the for LOOP level + + + + diff --git a/docs/linqfaster.xml b/docs/linqfaster.xml index 4ad1165..860170b 100644 --- a/docs/linqfaster.xml +++ b/docs/linqfaster.xml @@ -40,66 +40,6 @@ A function to transform the final accumulator value into the result value. The transformed final accumulator value - - - Applies an accumulator function over a Span{T}. - - A Span{T} to aggregate over. - An accumulator function to be invoked on each element - The final accumulator value - - - - Applies an accumulator function over a Span{T}. The specified seed - value is used as the initial accumulator value. - - A Span{T} to aggregate over. - The initial accumulator value. - An accumulator function to be invoked on each element - The final accumulator value - - - - Applies an accumulator function over a Span{T}. The specified seed - value is used as the initial accumulator value, and the specified - function is used to select the result value. - - A Span{T} to aggregate over. - The initial accumulator value. - An accumulator function to be invoked on each element - A function to transform the final accumulator value into the result value. - The transformed final accumulator value - - - - Applies an accumulator function over a ReadOnlySpan{T}. - - A ReadOnlySpan{T} to aggregate over. - An accumulator function to be invoked on each element - The final accumulator value - - - - Applies an accumulator function over a ReadOnlySpan{T}. The specified seed - value is used as the initial accumulator value. - - A ReadOnlySpan{T} to aggregate over. - The initial accumulator value. - An accumulator function to be invoked on each element - The final accumulator value - - - - Applies an accumulator function over a ReadOnlySpan{T}. The specified seed - value is used as the initial accumulator value, and the specified - function is used to select the result value. - - A ReadOnlySpan{T} to aggregate over. - The initial accumulator value. - An accumulator function to be invoked on each element - A function to transform the final accumulator value into the result value. - The transformed final accumulator value - Determines whether an array contains any elements @@ -124,30 +64,6 @@ true if every element of the source array passes the test in the specified predicate, or if the array is empty; otherwise, false - - - Determines whether an array contains any elements - - The array to check for emptiness - true if the source array contains any elements, otherwise, false/ - - - - Determines whether any element of an array satisfies a condition. - - An array whose elements to apply the predicate to. - A function to test each element for a condition. - true if any elements in the source array pass the test in the specified predicate; otherwise, false. - - - - Determines whether all elements of an array satisfy a condition. - - An array that contains the elements to apply the predicate to. - A function to test each element for a condition. - true if every element of the source array passes the test in the specified - predicate, or if the array is empty; otherwise, false - Determines whether a list contains any elements @@ -356,202 +272,6 @@ The array to calculate the average of. The average of the array. - - - Computes the average of values obtained by invoking a transform function on - each element of the input array. - - The array to calculate the transformed average of. - A transform function to apply to each element. - The average of the array. - - Special case for floats to be equivalent to IEnumerable ! - - - - - Computes the average of values obtained by invoking a transform function on - each element of the input array. - - The array to calculate the transformed average of. - A transform function to apply to each element. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of values obtained by invoking a transform function on - each element of the input array. - - The array to calculate the transformed average of. - A transform function to apply to each element. - The average of the array. - - Special case for floats to be equivalent to IEnumerable ! - - - - - Computes the average of values obtained by invoking a transform function on - each element of the input array. - - The array to calculate the transformed average of. - A transform function to apply to each element. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - - - - Computes the average of an array - - The array to calculate the average of. - The average of the array. - Determines whether an array contains a specified element by using the @@ -562,16 +282,6 @@ An equality comparer to compare values. true if the source sequence contains an element that has the specified value; otherwise, false. - - - Determines whether an array contains a specified element by using the - provided IEqualityComparer. - - An array in which to locate a value. - The value to locate. - An equality comparer to compare values. - true if the source sequence contains an element that has the specified value; otherwise, false. - Determines whether a list contains a specified element by using the @@ -592,16 +302,6 @@ A number that represents how many elements in the array satisfy the condition in the predicate function. - - - Returns a number that represents how many elements in the specified - array satisfy a condition. - - An array that contains elements to be tested and counted. - A function to test each element for a condition. - A number that represents how many elements in the array satisfy the condition - in the predicate function. - Returns a number that represents how many elements in the specified @@ -728,82 +428,16 @@ A function to test each element for a condition. - + - Returns the first element of an Span. + Returns the last element of a sequence. - The Span to return the first element of. - The first element in the specified array. + An sequence to return the last element of. + The value at the last position in the source sequence. - + - Returns the first element in an Span that satisfies a specified condition. - - An Span to return an element from. - A function to test each element for a condition. - The first element that satisfies the condition. - - - - Returns the first element of an Span, or a default value if the - array contains no elements. - - The Span to return the first element of. - default value if source is empty, otherwise, the first element - in source. - - - - Returns the first element of the sequence that satisfies a condition or a - default value if no such element is found. - - An Span to return an element from. - A function to test each element for a condition. - - - - - Returns the first element of an ReadOnlySpan. - - The ReadOnlySpan to return the first element of. - The first element in the specified array. - - - - Returns the first element in an ReadOnlySpan that satisfies a specified condition. - - An ReadOnlySpan to return an element from. - A function to test each element for a condition. - The first element that satisfies the condition. - - - - Returns the first element of an ReadOnlySpan, or a default value if the - array contains no elements. - - The ReadOnlySpan to return the first element of. - default value if source is empty, otherwise, the first element - in source. - - - - Returns the first element of the sequence that satisfies a condition or a - default value if no such element is found. - - An ReadOnlySpan to return an element from. - A function to test each element for a condition. - - - - - Returns the last element of a sequence. - - An sequence to return the last element of. - The value at the last position in the source sequence. - - - - Returns the last element of a sequence that satisfies a specified condition. + Returns the last element of a sequence that satisfies a specified condition. A sequence to return an element from. A function to test each element for a condition. @@ -893,72 +527,6 @@ A function to test each element for a condition. - - - Returns the first element of an Span. - - The Span to return the first element of. - The first element in the specified array. - - - - Returns the first element in an Span that satisfies a specified condition. - - An Span to return an element from. - A function to test each element for a condition. - The first element that satisfies the condition. - - - - Returns the first element of an Span, or a default value if the - array contains no elements. - - The Span to return the first element of. - default value if source is empty, otherwise, the first element - in source. - - - - Returns the first element of the sequence that satisfies a condition or a - default value if no such element is found. - - An Span to return an element from. - A function to test each element for a condition. - - - - - Returns the first element of an ReadOnlySpan. - - The ReadOnlySpan to return the first element of. - The first element in the specified array. - - - - Returns the first element in an ReadOnlySpan that satisfies a specified condition. - - An ReadOnlySpan to return an element from. - A function to test each element for a condition. - The first element that satisfies the condition. - - - - Returns the first element of an ReadOnlySpan, or a default value if the - array contains no elements. - - The ReadOnlySpan to return the first element of. - default value if source is empty, otherwise, the first element - in source. - - - - Returns the first element of the sequence that satisfies a condition or a - default value if no such element is found. - - An ReadOnlySpan to return an element from. - A function to test each element for a condition. - - Returns the maximum value in a sequence of values. @@ -1184,475 +752,87 @@ - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the maximum value in a sequence of values. - - A sequence of values to determine the maximum of. - The maximum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the maximum value. - - A sequence of values to determine the maximum value of. - A transform function to apply to each element. - The maximum value in the transform of the sequence. - - - - Returns the Minimum value in a sequence of values. - - A sequence of values to determine the Minimum of. - The Minimum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the Minimum value. - - A sequence of values to determine the Minimum value of. - A transform function to apply to each element. - The Minimum value in the transform of the sequence. - - - - Returns the Minimum value in a sequence of values. - - A sequence of values to determine the Minimum of. - The Minimum value in the sequence - - This is faster than the templated functions above. - Probably because the comparator function os only run once and there is not stack invloved - - - - - Invokes a transform function on each element of a sequence and returns the Minimum value. - - A sequence of values to determine the Minimum value of. - A transform function to apply to each element. - The Minimum value in the transform of the sequence. - - This is faster than the templated functions above. - Probably because the comparator function os only run once and there is not stack invloved - - - - - Returns the Minimum value in a sequence of values. - - A sequence of values to determine the Minimum of. - The Minimum value in the sequence - - This is faster than the templated functions above. - Probably because the comparator function os only run once and there is not stack invloved - - - - - Invokes a transform function on each element of a sequence and returns the Minimum value. - - A sequence of values to determine the Minimum value of. - A transform function to apply to each element. - The Minimum value in the transform of the sequence. - - This is faster than the templated functions above. - Probably because the comparator function os only run once and there is not stack invloved - - - - - Returns the Minimum value in a sequence of values. - - A sequence of values to determine the Minimum of. - The Minimum value in the sequence - - Special case to deal with NAN's - - - - - Invokes a transform function on each element of a sequence and returns the Minimum value. - - A sequence of values to determine the Minimum value of. - A transform function to apply to each element. - The Minimum value in the transform of the sequence. - - Special case to deal with NAN's - - - - - Returns the Minimum value in a sequence of values. - - A sequence of values to determine the Minimum of. - The Minimum value in the sequence - - Special case to deal with NAN's - - - - - Invokes a transform function on each element of a sequence and returns the Minimum value. - - A sequence of values to determine the Minimum value of. - A transform function to apply to each element. - The Minimum value in the transform of the sequence. - - Special case to deal with NAN's - - - - - Returns the Minimum value in a sequence of values. - - A sequence of values to determine the Minimum of. - The Minimum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the Minimum value. - - A sequence of values to determine the Minimum value of. - A transform function to apply to each element. - The Minimum value in the transform of the sequence. - - - - Returns the Minimum value in a sequence of values. - - A sequence of values to determine the Minimum of. - The Minimum value in the sequence - - - - Invokes a transform function on each element of a sequence and returns the Minimum value. - - A sequence of values to determine the Minimum value of. - A transform function to apply to each element. - The Minimum value in the transform of the sequence. - - - - Returns the Minimum value in a sequence of values. + Returns the maximum value in a sequence of values. - A sequence of values to determine the Minimum of. - The Minimum value in the sequence + A sequence of values to determine the maximum of. + The maximum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the Minimum value. + Invokes a transform function on each element of a sequence and returns the maximum value. - A sequence of values to determine the Minimum value of. + A sequence of values to determine the maximum value of. A transform function to apply to each element. - The Minimum value in the transform of the sequence. + The maximum value in the transform of the sequence. - + - Returns the Minimum value in a sequence of values. + Returns the maximum value in a sequence of values. - A sequence of values to determine the Minimum of. - The Minimum value in the sequence + A sequence of values to determine the maximum of. + The maximum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the Minimum value. + Invokes a transform function on each element of a sequence and returns the maximum value. - A sequence of values to determine the Minimum value of. + A sequence of values to determine the maximum value of. A transform function to apply to each element. - The Minimum value in the transform of the sequence. + The maximum value in the transform of the sequence. - + - Returns the Minimum value in a sequence of values. + Returns the maximum value in a sequence of values. - A sequence of values to determine the Minimum of. - The Minimum value in the sequence + A sequence of values to determine the maximum of. + The maximum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the Minimum value. + Invokes a transform function on each element of a sequence and returns the maximum value. - A sequence of values to determine the Minimum value of. + A sequence of values to determine the maximum value of. A transform function to apply to each element. - The Minimum value in the transform of the sequence. + The maximum value in the transform of the sequence. - + - Returns the Minimum value in a sequence of values. + Returns the maximum value in a sequence of values. - A sequence of values to determine the Minimum of. - The Minimum value in the sequence + A sequence of values to determine the maximum of. + The maximum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the Minimum value. + Invokes a transform function on each element of a sequence and returns the maximum value. - A sequence of values to determine the Minimum value of. + A sequence of values to determine the maximum value of. A transform function to apply to each element. - The Minimum value in the transform of the sequence. + The maximum value in the transform of the sequence. - + - Returns the Minimum value in a sequence of values. + Returns the maximum value in a sequence of values. - A sequence of values to determine the Minimum of. - The Minimum value in the sequence + A sequence of values to determine the maximum of. + The maximum value in the sequence - + - Invokes a transform function on each element of a sequence and returns the Minimum value. + Invokes a transform function on each element of a sequence and returns the maximum value. - A sequence of values to determine the Minimum value of. + A sequence of values to determine the maximum value of. A transform function to apply to each element. - The Minimum value in the transform of the sequence. + The maximum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1660,74 +840,102 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + - + Invokes a transform function on each element of a sequence and returns the Minimum value. A sequence of values to determine the Minimum value of. A transform function to apply to each element. The Minimum value in the transform of the sequence. + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + - + Invokes a transform function on each element of a sequence and returns the Minimum value. A sequence of values to determine the Minimum value of. A transform function to apply to each element. The Minimum value in the transform of the sequence. + + This is faster than the templated functions above. + Probably because the comparator function os only run once and there is not stack invloved + - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence + + Special case to deal with NAN's + - + Invokes a transform function on each element of a sequence and returns the Minimum value. A sequence of values to determine the Minimum value of. A transform function to apply to each element. The Minimum value in the transform of the sequence. + + Special case to deal with NAN's + - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence + + Special case to deal with NAN's + - + Invokes a transform function on each element of a sequence and returns the Minimum value. A sequence of values to determine the Minimum value of. A transform function to apply to each element. The Minimum value in the transform of the sequence. + + Special case to deal with NAN's + - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1735,14 +943,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1750,14 +958,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1765,14 +973,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1780,14 +988,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1795,14 +1003,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1810,14 +1018,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1825,14 +1033,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1840,14 +1048,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1855,14 +1063,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1870,14 +1078,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1885,14 +1093,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -1900,14 +1108,14 @@ A transform function to apply to each element. The Minimum value in the transform of the sequence. - + Returns the Minimum value in a sequence of values. A sequence of values to determine the Minimum of. The Minimum value in the sequence - + Invokes a transform function on each element of a sequence and returns the Minimum value. @@ -2000,19 +1208,6 @@ A sequence of values to reverse. - - - Inverts the order of the elements in a sequence. - - A sequence of values to reverse. - A sequence whose elements correspond to those of the input sequence in reverse order. - - - - Inverts the order of the elements in a sequence in place. - - A sequence of values to reverse. - Inverts the order of the elements in a sequence. @@ -2056,36 +1251,6 @@ A transform function to apply to each source element; the second parameter of the function represents the index of the source element. A sequence whose elements are the result of invoking the transform function on each element of source. - - - Projects each element of a sequence into a new form in place. - - A sequence of values to invoke a transform function on (map). - A transform function to apply (map) to each element. - - - - Projects each element of a sequence into a new form, in place, by incorporating the element's index. - - A sequence of values to invoke a transform function on. - A transform function to apply to each source element; the second parameter of the function represents the index of the source element. - - - - Projects each element of a sequence into a new form. (map in every other language) - - A sequence of values to invoke a transform function on (map). - A transform function to apply (map) to each element. - A sequence whose elements are the result of invoking the transform function on each element (mapping) of source. - - - - Projects each element of a sequence into a new form by incorporating the element's index. - - A sequence of values to invoke a transform function on. - A transform function to apply to each source element; the second parameter of the function represents the index of the source element. - A sequence whose elements are the result of invoking the transform function on each element of source. - Projects each element of a sequence into a new form in place. @@ -2134,24 +1299,6 @@ A transform function to apply to each element and it's index. A sequence whose elements are the result of invoking the one-to-many transform function on each element and index of the input sequence. - - - Projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence. - Yo dawg, I heard you like sequences. - - A sequence of values to project. - A transform function to apply to each element. - A sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence. - - - - Projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence - utilizing the index of each element. - - A sequence of values to project. - A transform function to apply to each element and it's index. - A sequence whose elements are the result of invoking the one-to-many transform function on each element and index of the input sequence. - Projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence. @@ -2190,26 +1337,6 @@ The predicate with index with which to filter result. A sequence transformed and then filtered by selector and predicate with indexes. - - - Combines Select and Where into a single call for optimal - performance. - - The input sequence to filter and select - The transformation to apply before filtering. - The predicate with which to filter result. - A sequence transformed and then filtered by selector and predicate. - - - - Combines Select and Where with indexes into a single call for optimal - performance. - - The input sequence to filter and select - The transformation with index to apply before filtering. - The predicate with index with which to filter result. - A sequence transformed and then filtered by selector and predicate with indexes. - Combines Select and Where into a single call for optimal @@ -2230,39 +1357,7 @@ The predicate with index with which to filter result. A sequence transformed and then filtered by selector and predicate with indexes. - - - Determines whether two sequences are equal by comparing the elements by using the - provided comparer or the default equality comparer for their type if none is provided. - - A sequence to compare to second. - A sequence to compare to first. - An optional Comparer to use for the comparison. - true of the two sources are of equal length and their corresponding - elements are equal according to the equality comparer. Otherwise, false. - - - - Determines whether two sequences are equal by comparing the elements by using the - provided comparer or the default equality comparer for their type if none is provided. - - A sequence to compare to second. - A sequence to compare to first. - An optional Comparer to use for the comparison. - An array of integers, where the value corresponds to IComparer.Compare indicating less than, greater than, or equals - - - - Determines whether two sequences are equal by comparing the elements by using the - provided comparer or the default equality comparer for their type if none is provided. - - A sequence to compare to second. - A sequence to compare to first. - An optional Comparer to use for the comparison. - true of the two sources are of equal length and their corresponding - elements are equal according to the equality comparer. Otherwise, false. - - + Determines whether two sequences are equal by comparing the elements by using the provided comparer or the default equality comparer for their type if none is provided. @@ -2271,9 +1366,9 @@ A sequence to compare to first. An optional Comparer to use for the comparison. true of the two sources are of equal length and their corresponding - elements are equal according to the equality comparer. Otherwise, false. + elements are equal according to the equality comparer. Otherwise, false. - + Determines whether two sequences are equal by comparing the elements by using the provided comparer or the default equality comparer for their type if none is provided. @@ -2281,10 +1376,9 @@ A sequence to compare to second. A sequence to compare to first. An optional Comparer to use for the comparison. - true of the two sources are of equal length and their corresponding - elements are equal according to the equality comparer. Otherwise, false. + An array of integers, where the value corresponds to IComparer.Compare indicating less than, greater than, or equals - + Determines whether two sequences are equal by comparing the elements by using the provided comparer or the default equality comparer for their type if none is provided. @@ -2295,7 +1389,7 @@ true of the two sources are of equal length and their corresponding elements are equal according to the equality comparer. Otherwise, false. - + Determines whether two sequences are equal by comparing the elements by using the provided comparer or the default equality comparer for their type if none is provided. @@ -2348,37 +1442,6 @@ A function to test an element for a condition. The single element of the input sequence that satisfies a condition or default value if no such element is found. - - - Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence. - - A sequence to return the single element of - The single element of the input sequence or default if no elements exist. - - - - Returns the only element of a sequence, or the default if no elements exist, and throws an exception if there is not exactly one element in the sequence. - - A sequence to return the single element of - The single element of the input sequence - - - - Returns the only element of a sequence that satisfies a specified condition, and throws an exception if more than one such element exists. - - A sequence to return a single element from. - A function to test an element for a condition. - The single element of the input sequence that satisfies a condition. - - - - Returns the only element of a sequence that satisfies a specified condition, or a default value if - no such element exists, and throws an exception if more than one such element exists. - - A sequence to return a single element from. - A function to test an element for a condition. - The single element of the input sequence that satisfies a condition or default value if no such element is found. - Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence. @@ -2426,22 +1489,6 @@ A function to test each element for a condition. A sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate. - - - Bypasses a specified number of elements in a sequence and then returns the remaining elements. - - A sequence to return elements from. - The number of elements to skip before returning the remaining elements. - A sequence that contains the elements that occur after the specified index in the input sequence. - - - - Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. - - A sequence to return elements from. - A function to test each element for a condition. - A sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate. - Bypasses a specified number of elements in a sequence and then returns the remaining elements. @@ -2823,198 +1870,6 @@ The sequence to add. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - - Special case for floats, as IEnumerable does the sums on doubles before returning the type. - - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - - Special case for floats, as IEnumerable does the sums on doubles before returning the type. - - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - The sum of the sequence. - - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A transformation function. - The sum of the transformed elements. - Returns a specified number of contiguous elements from the start of a sequence. @@ -3039,30 +1894,6 @@ A function to test each source element for a condition; the second parameter of the function represents the index of the source element. A sequence that contains elements from the input sequence that occur before the element at which the test no longer passes. - - - Returns a specified number of contiguous elements from the start of a sequence. - - The sequence to return elements from. - The number of elements to return. - A sequence that contains the specified number of elements from the start of the input sequence. - - - - Returns elements from a sequence as long as a specified condition is true. - - A sequence to return elements from. - A function to test each element for a condition. - A sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes. - - - - Returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function. - - The sequence to return elements from. - A function to test each source element for a condition; the second parameter of the function represents the index of the source element. - A sequence that contains elements from the input sequence that occur before the element at which the test no longer passes. - Returns a specified number of contiguous elements from the start of a sequence. @@ -3084,26 +1915,10 @@ Returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function. The sequence to return elements from. - A function to test each source element for a condition; the second parameter of the function represents the index of the source element. - A sequence that contains elements from the input sequence that occur before the element at which the test no longer passes. - - - - Filters a sequence of values based on a predicate. - - A sequence to filter. - A function to test each element for a condition. - A sequence that contains elements from the input sequence that satisfy the condition. - - - - Filters a sequence of values based on a predicate that includes the index in it's logic. - - A sequence to filter. - A function to test each element for a condition along with the element's index. - A sequence that contains elements from the input sequence that satisfy the condition. + A function to test each source element for a condition; the second parameter of the function represents the index of the source element. + A sequence that contains elements from the input sequence that occur before the element at which the test no longer passes. - + Filters a sequence of values based on a predicate. @@ -3111,7 +1926,7 @@ A function to test each element for a condition. A sequence that contains elements from the input sequence that satisfy the condition. - + Filters a sequence of values based on a predicate that includes the index in it's logic. @@ -3174,45 +1989,6 @@ A function to transform the final result. The filtered then aggregated then transformed sequence. - - - Combines Where and Aggregate for optimal performance - - The input to filter then aggregate. - The function to filter the input sequence with. - The function to aggregate the filtered sequence. - The filtered then aggregated sequence. - - - - Combines Where and Aggregate with index for optimal performance - - The input to filter then aggregate. - The function to filter the input sequence and it's index with. - The function to aggregate the filtered sequence. - The filtered then aggregated sequence. - - - - Combines Where and Aggregate for optimal performance with a starting seed. - - The input to filter then aggregate. - The function to filter the input sequence with. - The initial value to aggregate on. - The function to aggregate the filtered sequence. - The filtered then aggregated sequence. - - - - Combines Where and Aggregate for optimal performance with a starting seed and a result transformation. - - The input to filter then aggregate. - The function to filter the input sequence with. - The initial value to aggregate on. - The function to aggregate the filtered sequence. - A function to transform the final result. - The filtered then aggregated then transformed sequence. - Combines Where and Aggregate for optimal performance @@ -3271,25 +2047,6 @@ A function to transform the filtered elements. A sequence of filtered and transformed elements. - - - Combined Where and Select for optimal performance. - - The input sequence to filter then transform. - A function to use to filter the sequence. - A function to transform the filtered elements. - A sequence of filtered and transformed elements. - - - - Combined Where and Select for optimal performance that uses the index in the - predicate and selector. - - The input sequence to filter then transform. - A function to use to filter the sequence. - A function to transform the filtered elements. - A sequence of filtered and transformed elements. - Combined Where and Select for optimal performance. @@ -3724,224 +2481,6 @@ A function to filter the sequence with before summing. The sum of the sequence. - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. - - Special case for floats, as IEnumerable does the sums on doubles before returning the type. - - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. - - Special case for floats, as IEnumerable does the sums on doubles before returning the type. - - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds a sequence of values. - - The sequence to add. - A function to filter the sequence with before summing. - The sum of the sequence. - - - - Adds the transformed sequence of elements. - - The sequence of values to transform then sum. - A function to filter the sequence with before summing. - A transformation function. - The sum of the transformed elements. - Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results. @@ -3951,15 +2490,6 @@ A function that specifies how to merge the elements from the two sequences. A sequence that contains merged elements of two input sequences. - - - Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results. - - The first sequence to merge. - The second sequence to merge. - A function that specifies how to merge the elements from the two sequences. - A sequence that contains merged elements of two input sequences. - Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results. From 25c68fcb037ec0408e5fbff9b0525e70acdc5e46 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Thu, 8 Aug 2019 11:38:43 +0100 Subject: [PATCH 24/30] - Attempt to fic AppVeyor --- Benchmarks/BenchmarkAggregate.cs | 24 +++---- Benchmarks/BenchmarkAverage.cs | 12 ++-- Benchmarks/BenchmarkFirst.cs | 22 +++---- Benchmarks/BenchmarkLast.cs | 22 +++---- Benchmarks/BenchmarkOrderBy.cs | 4 +- Benchmarks/BenchmarkSelect.cs | 6 +- Benchmarks/BenchmarkSequenceEqual.cs | 10 +-- Benchmarks/BenchmarkSum.cs | 78 +++++++++++------------ Benchmarks/BenchmarkWhereSum.cs | 86 +++++++++++++------------- Benchmarks/BenchmarksMax.cs | 40 ++++++------ Benchmarks/BenchmarksMin.cs | 42 ++++++------- Benchmarks/BenchmarksRepeat.cs | 8 +-- Benchmarks/BenchmarksWhereAggregate.cs | 4 +- BenchmarksCore/BenchmarksCore.csproj | 4 +- 14 files changed, 182 insertions(+), 180 deletions(-) diff --git a/Benchmarks/BenchmarkAggregate.cs b/Benchmarks/BenchmarkAggregate.cs index 12da968..d302e62 100644 --- a/Benchmarks/BenchmarkAggregate.cs +++ b/Benchmarks/BenchmarkAggregate.cs @@ -14,31 +14,31 @@ public class BenchmarksAggregate { private static readonly Func mulXInts = (acc, x) => acc += x * x; - [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("BAg_IntArrayAggregate"), Benchmark(Baseline = true)] public double IntArrayAggregateLinq() { return Benchmarks.intArray.Aggregate(0.0D, mulXInts); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark] + [BenchmarkCategory("BAg_IntArrayAggregate"), Benchmark] public double IntArrayAggregateFast() { return Benchmarks.intArray.AggregateF(0.0D, mulXInts); } - [BenchmarkCategory("IntReadOnlyArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("BAg_IntReadOnlyArrayAggregate"), Benchmark(Baseline = true)] public double IntReadOnlyArrayAggregateLinq() { return Array.AsReadOnly(Benchmarks.intArray).Aggregate(0.0D, mulXInts); } - [BenchmarkCategory("IntReadOnlyArrayAggregate"), Benchmark] + [BenchmarkCategory("BAg_IntReadOnlyArrayAggregate"), Benchmark] public double IntReadOnlyArrayAggregateFast() { return Array.AsReadOnly(Benchmarks.intArray).AggregateF(0.0D, mulXInts); } - [BenchmarkCategory("IntSpanAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("BAg_IntSpanAggregate"), Benchmark(Baseline = true)] public double IntSpanAggregateForEach() { //return intArray.AsSpan().Aggregate(0.0, mulXInts); @@ -50,43 +50,43 @@ public double IntSpanAggregateForEach() return result; } - [BenchmarkCategory("IntSpanAggregate"), Benchmark] + [BenchmarkCategory("BAg_IntSpanAggregate"), Benchmark] public double IntSpanAggregateFast() { return Benchmarks.intArray.AsSpan().AggregateF(0.0, mulXInts); } - [BenchmarkCategory("intList.Aggregate.Select"), Benchmark(Baseline = true)] + [BenchmarkCategory("BAg_intList.Aggregate.Select"), Benchmark(Baseline = true)] public double IntArrayAggregateLinqSelector() { return Benchmarks.intArray.Aggregate(0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); } - [BenchmarkCategory("intList.Aggregate.Select"), Benchmark] + [BenchmarkCategory("BAg_intList.Aggregate.Select"), Benchmark] public double IntArrayAggregateFastSelector() { return Benchmarks.intArray.AggregateF(0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); } - [BenchmarkCategory("intList.Aggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("BAg_intList.Aggregate"), Benchmark(Baseline = true)] public double IntListAggregateLinq() { return Benchmarks.intList.Aggregate(0.0, mulXInts); } - [BenchmarkCategory("intList.Aggregate"), Benchmark] + [BenchmarkCategory("BAg_intList.Aggregate"), Benchmark] public double IntListAggregateFast() { return Benchmarks.intList.AggregateF(0.0, mulXInts); } - [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BAg_intList.AsReadOnly"), Benchmark(Baseline = true)] public double IntReadOnlyListAggregateLinq() { return Benchmarks.intList.AsReadOnly().Aggregate(0.0, mulXInts); } - [BenchmarkCategory("intList.AsReadOnly"), Benchmark] + [BenchmarkCategory("BAg_intList.AsReadOnly"), Benchmark] public double IntReadOnlyListAggregateFast() { return Benchmarks.intList.AsReadOnly().AggregateF(0.0, mulXInts); diff --git a/Benchmarks/BenchmarkAverage.cs b/Benchmarks/BenchmarkAverage.cs index 45b9b56..b089008 100644 --- a/Benchmarks/BenchmarkAverage.cs +++ b/Benchmarks/BenchmarkAverage.cs @@ -12,38 +12,38 @@ namespace Tests public class BenchmarksAverage { - [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BAvintArray"), Benchmark(Baseline = true)] public double IntArrayAverageLinq() { return Benchmarks.intArray.Average(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BAvintArray"), Benchmark] public double IntArrayAverageFast() { return Benchmarks.intArray.AverageF(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BAvintArray"), Benchmark] public double IntArrayAverageFastSIMD() { return Benchmarks.intArray.AverageS(); } - [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BAvintList"), Benchmark(Baseline = true)] public double IntListAverageLinq() { return Benchmarks.intList.Average(); } - [BenchmarkCategory("intList"), Benchmark] + [BenchmarkCategory("BAvintList"), Benchmark] public double IntListAverageFast() { return Benchmarks.intList.AverageF(); } - //[BenchmarkCategory("intList"), Benchmark] + //[BenchmarkCategory("BAvintList"), Benchmark] //public double IntListAverageFastSIMD() //{ // return Benchmarks.intList.AverageS(); diff --git a/Benchmarks/BenchmarkFirst.cs b/Benchmarks/BenchmarkFirst.cs index e1ca96f..591e6ed 100644 --- a/Benchmarks/BenchmarkFirst.cs +++ b/Benchmarks/BenchmarkFirst.cs @@ -14,27 +14,27 @@ public class BenchmarksFirst { private static readonly Func firstInts = (x) => x > 0; - [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BFintArray"), Benchmark(Baseline = true)] public double IntArrayFirstLinqSelector() { return Benchmarks.intArray.First(firstInts); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BFintArray"), Benchmark] public double IntArrayFirstArrayFindSelector() { Predicate predicate = new Predicate(firstInts); return Array.Find(Benchmarks.intArray, predicate); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BFintArray"), Benchmark] public double IntArrayFirstFastSelector() { return Benchmarks.intArray.FirstF(firstInts); } - [BenchmarkCategory("localArray.AsSpan"), Benchmark(Baseline = true)] + [BenchmarkCategory("BFlocalArray.AsSpan"), Benchmark(Baseline = true)] public double IntSpanFirstForEachSelector() { int[] localArray = Benchmarks.intArray; @@ -50,7 +50,7 @@ public double IntSpanFirstForEachSelector() return 0; } - [BenchmarkCategory("localArray.AsSpan"), Benchmark] + [BenchmarkCategory("BFlocalArray.AsSpan"), Benchmark] public double IntSpanFirstFastSelector() { int[] localArray = Benchmarks.intArray; @@ -58,37 +58,37 @@ public double IntSpanFirstFastSelector() return asSpan.FirstF(firstInts); } - [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BFintList"), Benchmark(Baseline = true)] public double IntListFirstLinqSelector() { return Benchmarks.intList.First(firstInts); } - [BenchmarkCategory("intList"), Benchmark] + [BenchmarkCategory("BFintList"), Benchmark] public double IntListFirstFastSelector() { return Benchmarks.intList.FirstF(firstInts); } - [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BFintList.AsReadOnly"), Benchmark(Baseline = true)] public double IntAsListReadOnlyFirstLinqSelector() { return Benchmarks.intList.AsReadOnly().First(firstInts); } - [BenchmarkCategory("intList.AsReadOnly"), Benchmark] + [BenchmarkCategory("BFintList.AsReadOnly"), Benchmark] public double IntAsListReadOnlyFirstFastSelector() { return Benchmarks.intList.AsReadOnly().FirstF(firstInts); } - [BenchmarkCategory("Array.AsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BFArray.AsReadOnly"), Benchmark(Baseline = true)] public double IntArrayAsReadOnlyFirstLinqSelector() { return Array.AsReadOnly(Benchmarks.intArray).First(firstInts); } - [BenchmarkCategory("Array.AsReadOnly"), Benchmark] + [BenchmarkCategory("BFArray.AsReadOnly"), Benchmark] public double IntArrayAsReadOnlyFirstFastSelector() { return Array.AsReadOnly(Benchmarks.intArray).FirstF(firstInts); diff --git a/Benchmarks/BenchmarkLast.cs b/Benchmarks/BenchmarkLast.cs index 25d0e9c..0dba2fb 100644 --- a/Benchmarks/BenchmarkLast.cs +++ b/Benchmarks/BenchmarkLast.cs @@ -15,20 +15,20 @@ public class BenchmarksLast private static readonly Func LastInts = (x) => x > 0; - [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BLintArray"), Benchmark(Baseline = true)] public double IntArrayLastLinqSelector() { return Benchmarks.intArray.Last(LastInts); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BLintArray"), Benchmark] public double IntArrayLastArrayFindSelector() { Predicate predicate = new Predicate(LastInts); return Array.FindLast(Benchmarks.intArray, predicate); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BLintArray"), Benchmark] public double IntArrayLastFastSelector() { return Benchmarks.intArray.LastF(LastInts); @@ -36,7 +36,7 @@ public double IntArrayLastFastSelector() - [BenchmarkCategory("localArray.AsSpan"), Benchmark(Baseline = true)] + [BenchmarkCategory("BLlocalArray.AsSpan"), Benchmark(Baseline = true)] public double IntSpanLastForEachSelector() { int[] localArray = Benchmarks.intArray; @@ -52,7 +52,7 @@ public double IntSpanLastForEachSelector() return 0; } - [BenchmarkCategory("localArray.AsSpan"), Benchmark] + [BenchmarkCategory("BLlocalArray.AsSpan"), Benchmark] public double IntSpanLastFastSelector() { int[] localArray = Benchmarks.intArray; @@ -60,37 +60,37 @@ public double IntSpanLastFastSelector() return asSpan.LastF(LastInts); } - [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BLintList"), Benchmark(Baseline = true)] public double IntListLastLinqSelector() { return Benchmarks.intList.Last(LastInts); } - [BenchmarkCategory("intList"), Benchmark] + [BenchmarkCategory("BLintList"), Benchmark] public double IntListLastFastSelector() { return Benchmarks.intList.LastF(LastInts); } - [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BLintList.AsReadOnly"), Benchmark(Baseline = true)] public double IntAsListReadOnlyLastLinqSelector() { return Benchmarks.intList.AsReadOnly().Last(LastInts); } - [BenchmarkCategory("intList.AsReadOnly"), Benchmark] + [BenchmarkCategory("BLintList.AsReadOnly"), Benchmark] public double IntAsListReadOnlyLastFastSelector() { return Benchmarks.intList.AsReadOnly().LastF(LastInts); } - [BenchmarkCategory("Array.AsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BLArray.AsReadOnly"), Benchmark(Baseline = true)] public double IntArrayAsReadOnlyLastLinqSelector() { return Array.AsReadOnly(Benchmarks.intArray).Last(LastInts); } - [BenchmarkCategory("Array.AsReadOnly"), Benchmark] + [BenchmarkCategory("BLArray.AsReadOnly"), Benchmark] public double IntArrayAsReadOnlyLastFastSelector() { return Array.AsReadOnly(Benchmarks.intArray).LastF(LastInts); diff --git a/Benchmarks/BenchmarkOrderBy.cs b/Benchmarks/BenchmarkOrderBy.cs index c7a095b..7b44846 100644 --- a/Benchmarks/BenchmarkOrderBy.cs +++ b/Benchmarks/BenchmarkOrderBy.cs @@ -13,13 +13,13 @@ public class BenchmarkOrderBy { private static readonly Func orderBy = (x) => x - 1; - [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BOBintArray"), Benchmark(Baseline = true)] public int IntArrayOrderByLinq() { return Benchmarks.intArray.OrderBy(orderBy).Sum(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BOBintArray"), Benchmark] public int IntArrayOrderByFast() { return Benchmarks.intArray.OrderByF(orderBy).Sum(); diff --git a/Benchmarks/BenchmarkSelect.cs b/Benchmarks/BenchmarkSelect.cs index 9cc8892..b175aa6 100644 --- a/Benchmarks/BenchmarkSelect.cs +++ b/Benchmarks/BenchmarkSelect.cs @@ -11,19 +11,19 @@ namespace Tests [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class BenchmarkSelect { - [BenchmarkCategory("intArray.Select"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSintArray.Select"), Benchmark(Baseline = true)] public int[] IntArraySelectLinq() { return Benchmarks.intArray.Select(x => x * x).ToArray(); } - [BenchmarkCategory("intArray.Select"), Benchmark] + [BenchmarkCategory("BSintArray.Select"), Benchmark] public int[] IntArraySelectFast() { return Benchmarks.intArray.SelectF(x => x * x); } - [BenchmarkCategory("intArray.Select"), Benchmark] + [BenchmarkCategory("BSintArray.Select"), Benchmark] public int[] IntArraySelectFastSIMD() { return Benchmarks.intArray.SelectS(x => x * x, x => x * x); diff --git a/Benchmarks/BenchmarkSequenceEqual.cs b/Benchmarks/BenchmarkSequenceEqual.cs index 126ce59..63e509e 100644 --- a/Benchmarks/BenchmarkSequenceEqual.cs +++ b/Benchmarks/BenchmarkSequenceEqual.cs @@ -14,32 +14,32 @@ namespace Tests [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class BenchmarkSequenceEqual { - [Benchmark(Baseline = true)] + [BenchmarkCategory("BSEintArray"), Benchmark(Baseline = true)] public bool IntArraySequenceEqual() { return Benchmarks.intArray.SequenceEqual(Benchmarks.array2); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BSEintArray"), Benchmark] public bool IntArraySequenceEqualF() { return Benchmarks.intArray.SequenceEqualF(Benchmarks.array2); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BSEintArray"), Benchmark] public bool IntArraySequenceEqualP() { return Benchmarks.intArray.SequenceEqualP(Benchmarks.array2); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BSEintArray"), Benchmark] public bool IntArraySequenceEqualS() { return Benchmarks.intArray.SequenceEqualS(Benchmarks.array2); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BSEintArray"), Benchmark] public bool IntArraySequenceEqualSP() { return Benchmarks.intArray.SequenceEqualSP(Benchmarks.array2); diff --git a/Benchmarks/BenchmarkSum.cs b/Benchmarks/BenchmarkSum.cs index f81d8b1..c7d7cc0 100644 --- a/Benchmarks/BenchmarkSum.cs +++ b/Benchmarks/BenchmarkSum.cs @@ -15,51 +15,51 @@ public class BenchmarkSum { private static readonly Func sumDivide = (x) => x / 2; - [BenchmarkCategory("byteArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumbyteArray"), Benchmark(Baseline = true)] public int ByteArraySumLinq() { return Benchmarks.byteArray.Aggregate(0, (current, b1) => current + b1); } - [BenchmarkCategory("byteArray"), Benchmark] + [BenchmarkCategory("BSumbyteArray"), Benchmark] public uint ByteArraySumFast() { return Benchmarks.byteArray.SumF(); } - [BenchmarkCategory("shortArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumshortArray"), Benchmark(Baseline = true)] public int ShortArraySumLinq() { return Benchmarks.shortArray.Aggregate(0, (current, s1) => current + s1); } - [BenchmarkCategory("shortArray"), Benchmark] + [BenchmarkCategory("BSumshortArray"), Benchmark] public int ShortArraySumFast() { return Benchmarks.shortArray.SumF(); } - [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumintArray"), Benchmark(Baseline = true)] public int IntArraySumLinq() { return Benchmarks.intArray.Sum(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BSumintArray"), Benchmark] public int IntArraySumFast() { return Benchmarks.intArray.SumF(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BSumintArray"), Benchmark] public int IntArraySumFastSIMD() { return Benchmarks.intArray.SumS(); } - [BenchmarkCategory("intArraySpan"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumintArraySpan"), Benchmark(Baseline = true)] public int IntSpanSumFor() { int val = 0; @@ -72,189 +72,189 @@ public int IntSpanSumFor() return val; } - [BenchmarkCategory("intArraySpan"), Benchmark] + [BenchmarkCategory("BSumintArraySpan"), Benchmark] public int IntSpanSumFast() { return Benchmarks.intArray.AsSpan().SumF(); } - [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumintList"), Benchmark(Baseline = true)] public int IntListSumLinq() { return Benchmarks.intList.Sum(); } - [BenchmarkCategory("intList"), Benchmark] + [BenchmarkCategory("BSumintList"), Benchmark] public int IntListSumFast() { return Benchmarks.intList.SumF(); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumIntArrayAggregate"), Benchmark(Baseline = true)] public int IntArraySumLinqSelect() { return Benchmarks.intArray.Sum(sumDivide); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark] + [BenchmarkCategory("BSumIntArrayAggregate"), Benchmark] public int IntArraySumFastSelect() { return Benchmarks.intArray.SumF(sumDivide); } - [BenchmarkCategory("intArrayAsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumintArrayAsReadOnly"), Benchmark(Baseline = true)] public double IntReadOnlyArraySumWithSelectLinq() { return Array.AsReadOnly(Benchmarks.intArray).Sum(sumDivide); } - [BenchmarkCategory("intArrayAsReadOnly"), Benchmark] + [BenchmarkCategory("BSumintArrayAsReadOnly"), Benchmark] public double IntReadOnlyArraySumWithSelectFast() { return Array.AsReadOnly(Benchmarks.intArray).SumF(sumDivide); } - [BenchmarkCategory("intNullArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumintNullArray"), Benchmark(Baseline = true)] public int? IntNullArraySumLinq() { return Benchmarks.intNullArray.Sum(); } - [BenchmarkCategory("intNullArray"), Benchmark] + [BenchmarkCategory("BSumintNullArray"), Benchmark] public int? IntNullArraySumFast() { return Benchmarks.intNullArray.SumF(); } - [BenchmarkCategory("intNullArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumintNullArraySelect"), Benchmark(Baseline = true)] public int IntNullArraySumLinqSelect() { return Benchmarks.intNullArray.Sum(x => x / 2 ?? 0); } - [BenchmarkCategory("intNullArraySelect"), Benchmark] + [BenchmarkCategory("BSumintNullArraySelect"), Benchmark] public int IntNullArraySumFastSelect() { return Benchmarks.intNullArray.SumF(x => x / 2 ?? 0); } - [BenchmarkCategory("floatArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumfloatArray"), Benchmark(Baseline = true)] public float FloatArraySumLinq() { return Benchmarks.floatArray.Sum(); } - [BenchmarkCategory("floatArray"), Benchmark] + [BenchmarkCategory("BSumfloatArray"), Benchmark] public float FloatArraySumFast() { return Benchmarks.floatArray.SumF(); } - [BenchmarkCategory("floatList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumfloatList"), Benchmark(Baseline = true)] public float FloatListSumLinq() { return Benchmarks.floatList.Sum(); } - [BenchmarkCategory("floatList"), Benchmark] + [BenchmarkCategory("BSumfloatList"), Benchmark] public float FloatListSumFast() { return Benchmarks.floatList.SumF(); } - [BenchmarkCategory("floatArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumfloatArraySelect"), Benchmark(Baseline = true)] public float FloatArraySumLinqSelect() { return Benchmarks.floatArray.Sum(x => x / 2); } - [BenchmarkCategory("floatArraySelect"), Benchmark] + [BenchmarkCategory("BSumfloatArraySelect"), Benchmark] public float FloatArraySumFastSelect() { return Benchmarks.floatArray.SumF(x => x / 2); } - [BenchmarkCategory("floatNullArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumfloatNullArray"), Benchmark(Baseline = true)] public float? FloatNullArraySumLinq() { return Benchmarks.floatNullArray.Sum(); } - [BenchmarkCategory("floatNullArray"), Benchmark] + [BenchmarkCategory("BSumfloatNullArray"), Benchmark] public float? FloatNullArraySumFast() { return Benchmarks.floatNullArray.SumF(); } - [BenchmarkCategory("floatNullArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumfloatNullArraySelect"), Benchmark(Baseline = true)] public float FloatNullArraySumLinqSelect() { return Benchmarks.floatNullArray.Sum(x => x / 2 ?? 0); } - [BenchmarkCategory("floatNullArraySelect"), Benchmark] + [BenchmarkCategory("BSumfloatNullArraySelect"), Benchmark] public float FloatNullArraySumFastSelect() { return Benchmarks.floatNullArray.SumF(x => x / 2 ?? 0); } - [BenchmarkCategory("doubleArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumdoubleArray"), Benchmark(Baseline = true)] public double DoubleArraySumLinq() { return Benchmarks.doubleArray.Sum(); } - [BenchmarkCategory("doubleArray"), Benchmark] + [BenchmarkCategory("BSumdoubleArray"), Benchmark] public double DoubleArraySumFast() { return Benchmarks.doubleArray.SumF(); } - [BenchmarkCategory("doubleList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumdoubleList"), Benchmark(Baseline = true)] public double DoubleListSumLinq() { return Benchmarks.doubleList.Sum(); } - [BenchmarkCategory("doubleList"), Benchmark] + [BenchmarkCategory("BSumdoubleList"), Benchmark] public double DoubleListSumFast() { return Benchmarks.doubleList.SumF(); } - [BenchmarkCategory("doubleArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumdoubleArraySelect"), Benchmark(Baseline = true)] public double DoubleArraySumLinqSelect() { return Benchmarks.doubleArray.Sum(x => x / 2); } - [BenchmarkCategory("doubleArraySelect"), Benchmark] + [BenchmarkCategory("BSumdoubleArraySelect"), Benchmark] public double DoubleArraySumFastSelect() { return Benchmarks.doubleArray.SumF(x => x / 2); } - [BenchmarkCategory("doubleNullArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumdoubleNullArray"), Benchmark(Baseline = true)] public double? DoubleNullArraySumLinq() { return Benchmarks.doubleNullArray.Sum(); } - [BenchmarkCategory("doubleNullArray"), Benchmark] + [BenchmarkCategory("BSumdoubleNullArray"), Benchmark] public double? DoubleNullArraySumFast() { return Benchmarks.doubleNullArray.SumF(); } - [BenchmarkCategory("doubleNullArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BSumdoubleNullArraySelect"), Benchmark(Baseline = true)] public double? DoubleNullArraySumLinqSelect() { return Benchmarks.doubleNullArray.Sum(x => x / 2 ?? 0); } - [BenchmarkCategory("doubleNullArraySelect"), Benchmark] + [BenchmarkCategory("BSumdoubleNullArraySelect"), Benchmark] public double? DoubleNullArraySumFastSelect() { return Benchmarks.doubleNullArray.SumF(x => x / 2 ?? 0); diff --git a/Benchmarks/BenchmarkWhereSum.cs b/Benchmarks/BenchmarkWhereSum.cs index 550dec4..5efe4ed 100644 --- a/Benchmarks/BenchmarkWhereSum.cs +++ b/Benchmarks/BenchmarkWhereSum.cs @@ -13,46 +13,46 @@ namespace Tests public class BenchmarkWhereSum { - [BenchmarkCategory("byteArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSbyteArray"), Benchmark(Baseline = true)] public int ByteArrayWhereSumLinq() { return Benchmarks.byteArray.Where(x => x > 0).Aggregate(0, (current, b1) => current + b1); } - [BenchmarkCategory("byteArray"), Benchmark] + [BenchmarkCategory("BWSbyteArray"), Benchmark] public uint ByteArrayWhereSumFast() { return Benchmarks.byteArray.WhereSumF(x => x > 0); } - [BenchmarkCategory("shortArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSshortArray"), Benchmark(Baseline = true)] public int ShortArrayWhereSumLinq() { return Benchmarks.shortArray.Where(x => x > 0).Aggregate(0, (current, s1) => current + s1); } - [BenchmarkCategory("shortArray"), Benchmark] + [BenchmarkCategory("BWSshortArray"), Benchmark] public int ShortArrayWhereSumFast() { return Benchmarks.shortArray.WhereSumF(x => x > 0); } - [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSintArray"), Benchmark(Baseline = true)] public int IntArrayWhereSumLinq() { return Benchmarks.intArray.Where(x => x > 0).Sum(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BWSintArray"), Benchmark] public int IntArrayWhereSumFast() { return Benchmarks.intArray.WhereSumF(x => x > 0); } /* - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BWSintArray"), Benchmark] public int IntArrayWhereSumFastSIMD() { return intArray.WhereSumS(x => x > 0); @@ -60,7 +60,7 @@ public int IntArrayWhereSumFastSIMD() */ - [BenchmarkCategory("intArray.AsSpan"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSintArray.AsSpan"), Benchmark(Baseline = true)] public int IntSpanWhereSumFor() { int val = 0; @@ -76,214 +76,214 @@ public int IntSpanWhereSumFor() return val; } - [BenchmarkCategory("intArray.AsSpan"), Benchmark] + [BenchmarkCategory("BWSintArray.AsSpan"), Benchmark] public int IntSpanWhereSumFast() { return Benchmarks.intArray.AsSpan().WhereSumF(x => x > 0); } - [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSintList"), Benchmark(Baseline = true)] public int IntListWhereSumLinq() { return Benchmarks.intList.Where(x => x > 0).Sum(); } - [BenchmarkCategory("intList"), Benchmark] + [BenchmarkCategory("BWSintList"), Benchmark] public int IntListWhereSumFast() { return Benchmarks.intList.WhereSumF(x => x > 0); } - [BenchmarkCategory("intArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSintArraySelect"), Benchmark(Baseline = true)] public int IntArrayWhereSumLinqSelect() { return Benchmarks.intArray.Where(x => x > 0).Sum(x => x / 2); } - [BenchmarkCategory("intArraySelect"), Benchmark] + [BenchmarkCategory("BWSintArraySelect"), Benchmark] public int IntArrayWhereSumFastSelect() { return Benchmarks.intArray.WhereSumF(x => x > 0, x => x / 2); } - [BenchmarkCategory("Array.AsReadOnlySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSArray.AsReadOnlySelect"), Benchmark(Baseline = true)] public double IntReadOnlyArraySumWithSelectLinq() { return Array.AsReadOnly(Benchmarks.intArray).Where(x => x > 0).Sum(x => x / 2); } - [BenchmarkCategory("Array.AsReadOnlySelect"), Benchmark] + [BenchmarkCategory("BWSArray.AsReadOnlySelect"), Benchmark] public double IntReadOnlyArraySumWithSelectFast() { return Array.AsReadOnly(Benchmarks.intArray).WhereSumF(x => x > 0, x => x / 2); } - [BenchmarkCategory("intNullArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSintNullArray"), Benchmark(Baseline = true)] public int? IntNullArrayWhereSumLinq() { return Benchmarks.intNullArray.Where(x => x > 0).Sum(); } - [BenchmarkCategory("intNullArray"), Benchmark] + [BenchmarkCategory("BWSintNullArray"), Benchmark] public int? IntNullArrayWhereSumFast() { return Benchmarks.intNullArray.WhereSumF(x => x > 0); } - [BenchmarkCategory("intNullArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSintNullArraySelect"), Benchmark(Baseline = true)] public int IntNullArrayWhereSumLinqSelect() { return Benchmarks.intNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); } - [BenchmarkCategory("intNullArraySelect"), Benchmark] + [BenchmarkCategory("BWSintNullArraySelect"), Benchmark] public int IntNullArrayWhereSumFastSelect() { return Benchmarks.intNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); } - [BenchmarkCategory("floatArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSfloatArray"), Benchmark(Baseline = true)] public float FloatArrayWhereSumLinq() { return Benchmarks.floatArray.Where(x => x > 0).Sum(); } - [BenchmarkCategory("floatArray"), Benchmark] + [BenchmarkCategory("BWSfloatArray"), Benchmark] public float FloatArrayWhereSumFast() { return Benchmarks.floatArray.WhereSumF(x => x > 0); } - [BenchmarkCategory("floatList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSfloatList"), Benchmark(Baseline = true)] public float FloatListWhereSumLinq() { return Benchmarks.floatList.Where(x => x > 0).Sum(); } - [BenchmarkCategory("floatList"), Benchmark] + [BenchmarkCategory("BWSfloatList"), Benchmark] public float FloatListWhereSumFast() { return Benchmarks.floatList.WhereSumF(x => x > 0); } - [BenchmarkCategory("floatArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSfloatArraySelect"), Benchmark(Baseline = true)] public float FloatArrayWhereSumLinqSelect() { return Benchmarks.floatArray.Where(x => x > 0).Sum(x => x / 2); } - [BenchmarkCategory("floatArraySelect"), Benchmark] + [BenchmarkCategory("BWSfloatArraySelect"), Benchmark] public float FloatArrayWhereSumFastSelect() { return Benchmarks.floatArray.WhereSumF(x => x > 0, x => x / 2); } - [BenchmarkCategory("floatNullArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSfloatNullArray"), Benchmark(Baseline = true)] public float? FloatNullArrayWhereSumLinq() { return Benchmarks.floatNullArray.Where(x => x > 0).Sum(); } - [BenchmarkCategory("floatNullArray"), Benchmark] + [BenchmarkCategory("BWSfloatNullArray"), Benchmark] public float? FloatNullArrayWhereSumFast() { return Benchmarks.floatNullArray.WhereSumF(x => x > 0); } - [BenchmarkCategory("floatNullArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSfloatNullArraySelect"), Benchmark(Baseline = true)] public float FloatNullArrayWhereSumLinqSelect() { return Benchmarks.floatNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); } - [BenchmarkCategory("floatNullArraySelect"), Benchmark] + [BenchmarkCategory("BWSfloatNullArraySelect"), Benchmark] public float FloatNullArrayWhereSumFastSelect() { return Benchmarks.floatNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); } - [BenchmarkCategory("doubleArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSdoubleArray"), Benchmark(Baseline = true)] public double DoubleArrayWhereSumLinq() { return Benchmarks.doubleArray.Where(x => x > 0).Sum(); } - [BenchmarkCategory("doubleArray"), Benchmark] + [BenchmarkCategory("BWSdoubleArray"), Benchmark] public double DoubleArrayWhereSumFast() { return Benchmarks.doubleArray.WhereSumF(x => x > 0); } - [BenchmarkCategory("doubleList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSdoubleList"), Benchmark(Baseline = true)] public double DoubleListWhereSumLinq() { return Benchmarks.doubleList.Where(x => x > 0).Sum(); } - [BenchmarkCategory("doubleList"), Benchmark] + [BenchmarkCategory("BWSdoubleList"), Benchmark] public double DoubleListWhereSumFast() { return Benchmarks.doubleList.WhereSumF(x => x > 0); } - [BenchmarkCategory("doubleArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSdoubleArraySelect"), Benchmark(Baseline = true)] public double DoubleArrayWhereSumLinqSelect() { return Benchmarks.doubleArray.Where(x => x > 0).Sum(x => x / 2); } - [BenchmarkCategory("doubleArraySelect"), Benchmark] + [BenchmarkCategory("BWSdoubleArraySelect"), Benchmark] public double DoubleArrayWhereSumFastSelect() { return Benchmarks.doubleArray.WhereSumF(x => x > 0, x => x / 2); } - [BenchmarkCategory("doubleNullArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSdoubleNullArray"), Benchmark(Baseline = true)] public double? DoubleNullArrayWhereSumLinq() { return Benchmarks.doubleNullArray.Where(x => x > 0).Sum(); } - [BenchmarkCategory("doubleNullArray"), Benchmark] + [BenchmarkCategory("BWSdoubleNullArray"), Benchmark] public double? DoubleNullArrayWhereSumFast() { return Benchmarks.doubleNullArray.WhereSumF(x => x > 0); } - [BenchmarkCategory("doubleNullArraySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSdoubleNullArraySelect"), Benchmark(Baseline = true)] public double? DoubleNullArrayWhereSumLinqSelect() { return Benchmarks.doubleNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); } - [BenchmarkCategory("doubleNullArraySelect"), Benchmark] + [BenchmarkCategory("BWSdoubleNullArraySelect"), Benchmark] public double? DoubleNullArrayWhereSumFastSelect() { return Benchmarks.doubleNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); } - [BenchmarkCategory("intListSelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSintListSelect"), Benchmark(Baseline = true)] public int IntListSumWithSelectLinq() { return Benchmarks.intList.Where(x => x > 0).Sum(x => x / 2); } - [BenchmarkCategory("intListSelect"), Benchmark] + [BenchmarkCategory("BWSintListSelect"), Benchmark] public int IntListSumWithSelectFast() { return Benchmarks.intList.WhereSumF(x => x > 0, x => x / 2); } - [BenchmarkCategory("intList.AsReadOnlySelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWSintList.AsReadOnlySelect"), Benchmark(Baseline = true)] public double IntReadOnlyListSumWithSelectLinq() { return Benchmarks.intList.AsReadOnly().Where(x => x > 0).Sum(x => x / 2); } - [BenchmarkCategory("intList.AsReadOnlySelect"), Benchmark] + [BenchmarkCategory("BWSintList.AsReadOnlySelect"), Benchmark] public double IntReadOnlyListSumWithSelectFast() { return Benchmarks.intList.AsReadOnly().WhereSumF(x => x > 0, x => x / 2); diff --git a/Benchmarks/BenchmarksMax.cs b/Benchmarks/BenchmarksMax.cs index 1625cdc..72073b9 100644 --- a/Benchmarks/BenchmarksMax.cs +++ b/Benchmarks/BenchmarksMax.cs @@ -14,19 +14,19 @@ public class BenchmarksMax { private static readonly Func MaxInts = (x) => x + 1; - [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxintArray"), Benchmark(Baseline = true)] public double IntArrayMaxLinq() { return Benchmarks.intArray.Max(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BMaxintArray"), Benchmark] public double IntArrayMaxFast() { return Benchmarks.intArray.MaxF(); } - [BenchmarkCategory("localArray.AsSpan"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxlocalArray.AsSpan"), Benchmark(Baseline = true)] public double IntSpanMaxForEach() { int[] localArray = Benchmarks.intArray; @@ -43,7 +43,7 @@ public double IntSpanMaxForEach() return max; } - [BenchmarkCategory("localArray.AsSpan"), Benchmark] + [BenchmarkCategory("BMaxlocalArray.AsSpan"), Benchmark] public double IntSpanMaxFast() { int[] localArray = Benchmarks.intArray; @@ -51,56 +51,56 @@ public double IntSpanMaxFast() return asSpan.MaxF(); } - [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxintList"), Benchmark(Baseline = true)] public double IntListMaxLinq() { return Benchmarks.intList.Max(); } - [BenchmarkCategory("intList"), Benchmark] + [BenchmarkCategory("BMaxintList"), Benchmark] public double IntListMaxFast() { return Benchmarks.intList.MaxF(); } - [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxintList.AsReadOnly"), Benchmark(Baseline = true)] public double IntAsListReadOnlyMaxLinq() { return Benchmarks.intList.AsReadOnly().Max(); } - [BenchmarkCategory("intList.AsReadOnly"), Benchmark] + [BenchmarkCategory("BMaxintList.AsReadOnly"), Benchmark] public double IntAsListReadOnlyMaxFast() { return Benchmarks.intList.AsReadOnly().MaxF(); } - [BenchmarkCategory("Array.AsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxArray.AsReadOnly"), Benchmark(Baseline = true)] public double IntArrayAsReadOnlyMaxLinq() { return Array.AsReadOnly(Benchmarks.intArray).Max(); } - [BenchmarkCategory("Array.AsReadOnly"), Benchmark] + [BenchmarkCategory("BMaxArray.AsReadOnly"), Benchmark] public double IntArrayAsReadOnlyMaxFast() { return Array.AsReadOnly(Benchmarks.intArray).MaxF(); } - [BenchmarkCategory("intArraySelector"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxintArraySelector"), Benchmark(Baseline = true)] public double IntArrayMaxLinqSelector() { return Benchmarks.intArray.Max(MaxInts); } - [BenchmarkCategory("intArraySelector"), Benchmark] + [BenchmarkCategory("BMaxintArraySelector"), Benchmark] public double IntArrayMaxFastSelector() { return Benchmarks.intArray.MaxF(MaxInts); } - [BenchmarkCategory("localArray.AsSpanSelector"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxlocalArray.AsSpanSelector"), Benchmark(Baseline = true)] public double IntSpanMaxForEachSelector() { int[] localArray = Benchmarks.intArray; @@ -118,7 +118,7 @@ public double IntSpanMaxForEachSelector() return max; } - [BenchmarkCategory("localArray.AsSpanSelector"), Benchmark] + [BenchmarkCategory("BMaxlocalArray.AsSpanSelector"), Benchmark] public double IntSpanMaxFastSelector() { int[] localArray = Benchmarks.intArray; @@ -126,37 +126,37 @@ public double IntSpanMaxFastSelector() return asSpan.MaxF(MaxInts); } - [BenchmarkCategory("intListSelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxintListSelect"), Benchmark(Baseline = true)] public double IntListMaxLinqSelector() { return Benchmarks.intList.Max(MaxInts); } - [BenchmarkCategory("intListSelect"), Benchmark] + [BenchmarkCategory("BMaxintListSelect"), Benchmark] public double IntListMaxFastSelector() { return Benchmarks.intList.MaxF(MaxInts); } - [BenchmarkCategory("intList.AsReadOnlySelector"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxintList.AsReadOnlySelector"), Benchmark(Baseline = true)] public double IntAsListReadOnlyMaxLinqSelector() { return Benchmarks.intList.AsReadOnly().Max(MaxInts); } - [BenchmarkCategory("intList.AsReadOnlySelector"), Benchmark] + [BenchmarkCategory("BMaxintList.AsReadOnlySelector"), Benchmark] public double IntAsListReadOnlyMaxFastSelector() { return Benchmarks.intList.AsReadOnly().MaxF(MaxInts); } - [BenchmarkCategory("Array.AsReadOnlySelector"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMaxArray.AsReadOnlySelector"), Benchmark(Baseline = true)] public double IntArrayAsReadOnlyMaxLinqSelector() { return Array.AsReadOnly(Benchmarks.intArray).Max(MaxInts); } - [BenchmarkCategory("Array.AsReadOnlySelector"), Benchmark] + [BenchmarkCategory("BMaxArray.AsReadOnlySelector"), Benchmark] public double IntArrayAsReadOnlyMaxFastSelector() { return Array.AsReadOnly(Benchmarks.intArray).MaxF(MaxInts); diff --git a/Benchmarks/BenchmarksMin.cs b/Benchmarks/BenchmarksMin.cs index f6b84e0..46f1df8 100644 --- a/Benchmarks/BenchmarksMin.cs +++ b/Benchmarks/BenchmarksMin.cs @@ -15,25 +15,25 @@ public class BenchmarksMin { private static readonly Func MinInts = (x) => x + 1; - [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinintArray"), Benchmark(Baseline = true)] public double IntArrayMinLinq() { return Benchmarks.intArray.Min(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BMinintArray"), Benchmark] public double IntArrayMinFast() { return Benchmarks.intArray.MinF(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BMinintArray"), Benchmark] public int IntArrayMinFastSIMD() { return Benchmarks.intArray.MinS(); } - [BenchmarkCategory("localArray.AsSpan"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinlocalArray.AsSpan"), Benchmark(Baseline = true)] public double IntSpanMinForEach() { int[] localArray = Benchmarks.intArray; @@ -50,7 +50,7 @@ public double IntSpanMinForEach() return Min; } - [BenchmarkCategory("localArray.AsSpan"), Benchmark] + [BenchmarkCategory("BMinlocalArray.AsSpan"), Benchmark] public double IntSpanMinFast() { int[] localArray = Benchmarks.intArray; @@ -58,56 +58,56 @@ public double IntSpanMinFast() return asSpan.MinF(); } - [BenchmarkCategory("intList"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinintList"), Benchmark(Baseline = true)] public double IntListMinLinq() { return Benchmarks.intList.Min(); } - [BenchmarkCategory("intList"), Benchmark] + [BenchmarkCategory("BMinintList"), Benchmark] public double IntListMinFast() { return Benchmarks.intList.MinF(); } - [BenchmarkCategory("intList.AsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinintList.AsReadOnly"), Benchmark(Baseline = true)] public double IntAsListReadOnlyMinLinq() { return Benchmarks.intList.AsReadOnly().Min(); } - [BenchmarkCategory("Array.AsReadOnly"), Benchmark] + [BenchmarkCategory("BMinArray.AsReadOnly"), Benchmark] public double IntAsListReadOnlyMinFast() { return Benchmarks.intList.AsReadOnly().MinF(); } - [BenchmarkCategory("Array.AsReadOnly"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinArray.AsReadOnly"), Benchmark(Baseline = true)] public double IntArrayAsReadOnlyMinLinq() { return Array.AsReadOnly(Benchmarks.intArray).Min(); } - [BenchmarkCategory("intArraySelector"), Benchmark] + [BenchmarkCategory("BMinintArraySelector"), Benchmark] public double IntArrayAsReadOnlyMinFast() { return Array.AsReadOnly(Benchmarks.intArray).MinF(); } - [BenchmarkCategory("intArraySelector"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinintArraySelector"), Benchmark(Baseline = true)] public double IntArrayMinLinqSelector() { return Benchmarks.intArray.Min(MinInts); } - [BenchmarkCategory("IntArrayAggregate"), Benchmark] + [BenchmarkCategory("BMinIntArrayAggregate"), Benchmark] public double IntArrayMinFastSelector() { return Benchmarks.intArray.MinF(MinInts); } - [BenchmarkCategory("localArray.AsSpanSelector"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinlocalArray.AsSpanSelector"), Benchmark(Baseline = true)] public double IntSpanMinForEachSelector() { int[] localArray = Benchmarks.intArray; @@ -125,7 +125,7 @@ public double IntSpanMinForEachSelector() return Min; } - [BenchmarkCategory("localArray.AsSpanSelector"), Benchmark] + [BenchmarkCategory("BMinlocalArray.AsSpanSelector"), Benchmark] public double IntSpanMinFastSelector() { int[] localArray = Benchmarks.intArray; @@ -133,37 +133,37 @@ public double IntSpanMinFastSelector() return asSpan.MinF(MinInts); } - [BenchmarkCategory("intListSelector"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinintListSelector"), Benchmark(Baseline = true)] public double IntListMinLinqSelector() { return Benchmarks.intList.Min(MinInts); } - [BenchmarkCategory("intListSelector"), Benchmark] + [BenchmarkCategory("BMinintListSelector"), Benchmark] public double IntListMinFastSelector() { return Benchmarks.intList.MinF(MinInts); } - [BenchmarkCategory("intList.AsReadOnlySelector"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinintList.AsReadOnlySelector"), Benchmark(Baseline = true)] public double IntAsListReadOnlyMinLinqSelector() { return Benchmarks.intList.AsReadOnly().Min(MinInts); } - [BenchmarkCategory("intList.AsReadOnlySelector"), Benchmark] + [BenchmarkCategory("BMinintList.AsReadOnlySelector"), Benchmark] public double IntAsListReadOnlyMinFastSelector() { return Benchmarks.intList.AsReadOnly().MinF(MinInts); } - [BenchmarkCategory("Array.AsReadOnlySelector"), Benchmark(Baseline = true)] + [BenchmarkCategory("BMinArray.AsReadOnlySelector"), Benchmark(Baseline = true)] public double IntArrayAsReadOnlyMinLinqSelector() { return Array.AsReadOnly(Benchmarks.intArray).Min(MinInts); } - [BenchmarkCategory("Array.AsReadOnlySelector"), Benchmark] + [BenchmarkCategory("BMinArray.AsReadOnlySelector"), Benchmark] public double IntArrayAsReadOnlyMinFastSelector() { return Array.AsReadOnly(Benchmarks.intArray).MinF(MinInts); diff --git a/Benchmarks/BenchmarksRepeat.cs b/Benchmarks/BenchmarksRepeat.cs index c9b8999..455d436 100644 --- a/Benchmarks/BenchmarksRepeat.cs +++ b/Benchmarks/BenchmarksRepeat.cs @@ -12,26 +12,26 @@ namespace Tests public class BenchmarksRepeat { - [BenchmarkCategory("intArray"), Benchmark(Baseline = true)] + [BenchmarkCategory("BRintArray"), Benchmark(Baseline = true)] public int[] IntArrayRepeatLinq() { return Enumerable.Repeat(5, Benchmarks.TEST_SIZE).ToArray(); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BRintArray"), Benchmark] public int[] IntArrayRepeatFast() { return LinqFaster.RepeatArrayF(5, Benchmarks.TEST_SIZE); } - [BenchmarkCategory("intArray"), Benchmark] + [BenchmarkCategory("BRintArray"), Benchmark] public int[] IntArrayRepeatFastSIMD() { return LinqFasterSIMD.RepeatS(5, Benchmarks.TEST_SIZE); } - //[BenchmarkCategory("intArray"), Benchmark] + //[BenchmarkCategory("BRintArray"), Benchmark] //public int[] IntArrayRepeatFastSIMDB() //{ // return LinqFasterSIMD.RepeatSB(5, Benchmarks.TEST_SIZE); diff --git a/Benchmarks/BenchmarksWhereAggregate.cs b/Benchmarks/BenchmarksWhereAggregate.cs index 8ebb2e6..cdc8b7d 100644 --- a/Benchmarks/BenchmarksWhereAggregate.cs +++ b/Benchmarks/BenchmarksWhereAggregate.cs @@ -14,13 +14,13 @@ public class BenchmarksWhereAggregate private static readonly Func mulXInts = (acc, x) => acc += x * x; - [BenchmarkCategory("intArray.WhereAggregateSelect"), Benchmark(Baseline = true)] + [BenchmarkCategory("BWAintArray.WhereAggregateSelect"), Benchmark(Baseline = true)] public double IntArrayWhereAggregateLinq() { return Benchmarks.intArray.Where(x => x % 2 == 0).Aggregate(0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); } - [BenchmarkCategory("intArray.WhereAggregateSelect"), Benchmark] + [BenchmarkCategory("BWAintArray.WhereAggregateSelect"), Benchmark] public double IntArrayWhereAggregateFast() { return Benchmarks.intArray.WhereAggregateF(x => x % 2 == 0, 0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); diff --git a/BenchmarksCore/BenchmarksCore.csproj b/BenchmarksCore/BenchmarksCore.csproj index cac2e16..6fa1f1d 100644 --- a/BenchmarksCore/BenchmarksCore.csproj +++ b/BenchmarksCore/BenchmarksCore.csproj @@ -1,4 +1,4 @@ - + Exe @@ -33,6 +33,8 @@ + + From 064760cfae6d484620a5b430e5a0516f462aa487 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Thu, 8 Aug 2019 12:04:10 +0100 Subject: [PATCH 25/30] - Another Attempt to satisfy Appveyor --- Benchmarks/Config.cs | 2 +- BenchmarksCore/BenchmarksCore.csproj | 92 ++++++++++--------- LinqFasterParallel/LinqFasterParallel.csproj | 2 +- .../LinqFasterParallelSIMD.csproj | 2 +- README.md | 16 +++- 5 files changed, 66 insertions(+), 48 deletions(-) diff --git a/Benchmarks/Config.cs b/Benchmarks/Config.cs index 6ed862b..ea96589 100644 --- a/Benchmarks/Config.cs +++ b/Benchmarks/Config.cs @@ -8,7 +8,7 @@ internal class Config : ManualConfig { public Config() { - KeepBenchmarkFiles = true; + // KeepBenchmarkFiles = true; //Add(Job.Default.With(CsProjClassicNetToolchain.Net472)); Add(Job.Default.With(CsProjClassicNetToolchain.From("net48"))); diff --git a/BenchmarksCore/BenchmarksCore.csproj b/BenchmarksCore/BenchmarksCore.csproj index 6fa1f1d..52144d6 100644 --- a/BenchmarksCore/BenchmarksCore.csproj +++ b/BenchmarksCore/BenchmarksCore.csproj @@ -1,48 +1,52 @@  - - Exe - netcoreapp2.1 - - - - true - - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Exe + netcoreapp2.1 + + + + true + + + + true + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + diff --git a/LinqFasterParallel/LinqFasterParallel.csproj b/LinqFasterParallel/LinqFasterParallel.csproj index b868301..7512985 100644 --- a/LinqFasterParallel/LinqFasterParallel.csproj +++ b/LinqFasterParallel/LinqFasterParallel.csproj @@ -1,7 +1,7 @@  - netstandard1.3;netstandard2.0;net461;net48 + netstandard2.0;net461;net48 LinqFaster.Parallel 1.0.2 Jack Mott diff --git a/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj b/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj index d10dc78..ef7dcb9 100644 --- a/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj +++ b/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj @@ -1,7 +1,7 @@  - netstandard1.3;netstandard2.0;net461;net48 + netstandard2.0;net461;net48 1.0.2 Jack Mott Jack Mott diff --git a/README.md b/README.md index 8a0a3fc..24aa2a0 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ will be continually updated. * [LinqFaster.SIMD](#linqfastersimd) * [LinqFaster.Parallel](#linqfasterparallel) * [LinqFaster.SIMD.Parallel](#linqfastersimdparallel) +* [LinqFaster.Span](#linqfasterspan) * [Limitations](#limitations) As well, all functions are properly documented so as to be explorable via intellisense. @@ -210,7 +211,20 @@ myArray.SelectSP(x=>x*x,10000); // split the array into ranges of 10,000 element // for very expensive operations. ``` -# Limitations +### LinqFaster.Span +Applies to Span and ReadonlySpan
+Currently in Development
+e.g.: +```c# + var Span mySpan = new Span(100) + var sum2 = mySpan.SumF(x => x*x); + var average2 = mySpan.AverageF(x => x*x); + var min2 = mySpan.MinF(x => x*x); + var max2 = mySpan.MaxF(x => x*x); + +``` + +### Limitations These are purely imperative implementations of the same higher order functions that Linq provides, but unlike Linq they are not lazily evaluated. This means that when chaining From 66e84c4ccce6d946e9757a6ce5f395e918a06d12 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Thu, 8 Aug 2019 12:16:57 +0100 Subject: [PATCH 26/30] - Appveyor again - Reset the bindingRedirects --- Benchmarks/App.config | 104 ++++---------------- Benchmarks/Benchmarks.csproj | 179 ++++++++++++++++++++++++++--------- 2 files changed, 155 insertions(+), 128 deletions(-) diff --git a/Benchmarks/App.config b/Benchmarks/App.config index 3388e30..ccadb30 100644 --- a/Benchmarks/App.config +++ b/Benchmarks/App.config @@ -3,88 +3,24 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 77dbde4..1b0c507 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -38,6 +38,51 @@ 4 true
+ + + + + + + + + + + + + + + + + + + + Designer + + + + + + {f13bac10-bcbe-4440-b9f0-3a2778ca9221} + LinqFasterParallelSIMD + + + {1b6d88e4-8745-4a0e-b459-53f7add04a12} + LinqFasterParallel + + + {050c43b5-4a4f-45d9-be0c-9b2a6acc189e} + LinqFasterSIMD + + + {68835792-9274-4ddc-8312-29700ef16f62} + LinqFasterSpan + + + {5b2f0f9f-6dda-4f06-a999-26e43ae04f86} + LinqFaster + + ..\packages\BenchmarkDotNet.0.11.5\lib\netstandard2.0\BenchmarkDotNet.dll @@ -64,19 +109,81 @@ ..\packages\Microsoft.Win32.Registry.4.5.0\lib\net461\Microsoft.Win32.Registry.dll + + ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll + True + True + ..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll - + + + ..\packages\System.Console.4.3.1\lib\net46\System.Console.dll + True + True + + + ..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll + True + True + + + ..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll + True + True + + + ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll + True + True + + + ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll + True + True + + + ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll + True + True + + + ..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll ..\packages\System.Reflection.TypeExtensions.4.5.1\lib\net461\System.Reflection.TypeExtensions.dll + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + ..\packages\System.Security.AccessControl.4.5.0\lib\net461\System.Security.AccessControl.dll + + ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll + True + True + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + ..\packages\System.Security.Principal.Windows.4.5.1\lib\net461\System.Security.Principal.Windows.dll @@ -86,56 +193,40 @@ ..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + + ..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll + True + True + ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + + + + ..\packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll + True + True + + + ..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll + True + True + + + ..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll + True + True + + + ..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll + True + True + ..\packages\System.Xml.XPath.XmlDocument.4.3.0\lib\net46\System.Xml.XPath.XmlDocument.dll - - - - - - - - - - - - - - - - - - - - - - - - {f13bac10-bcbe-4440-b9f0-3a2778ca9221} - LinqFasterParallelSIMD - - - {1b6d88e4-8745-4a0e-b459-53f7add04a12} - LinqFasterParallel - - - {050c43b5-4a4f-45d9-be0c-9b2a6acc189e} - LinqFasterSIMD - - - {68835792-9274-4ddc-8312-29700ef16f62} - LinqFasterSpan - - - {5b2f0f9f-6dda-4f06-a999-26e43ae04f86} - LinqFaster - - From 19634896f728e7a213f50d48ded601c831ec6ed7 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Thu, 8 Aug 2019 12:29:13 +0100 Subject: [PATCH 27/30] - Look Apveyor Use the correct system.memry version will ya ! --- Benchmarks/App.config | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Benchmarks/App.config b/Benchmarks/App.config index ccadb30..b801039 100644 --- a/Benchmarks/App.config +++ b/Benchmarks/App.config @@ -1,6 +1,6 @@  - + @@ -21,6 +21,10 @@ + + + + From 37f256c7b57edc611d26cb9ce428442a5091e571 Mon Sep 17 00:00:00 2001 From: Smurf-IV Date: Thu, 8 Aug 2019 12:55:01 +0100 Subject: [PATCH 28/30] - (Maybe) Seems like the App.config is being ignored, so be explicit in the csproj file... --- Benchmarks/Benchmarks.csproj | 485 ++++++++++++++++++----------------- 1 file changed, 248 insertions(+), 237 deletions(-) diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 1b0c507..8835329 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -1,244 +1,255 @@  - - - - Debug - AnyCPU - {42DD1432-5209-49B3-81D7-B487A9DBF2F3} - Exe - Properties - Tests - Benchmarks - v4.6.1 - 512 - true - - - - - - x64 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - x64 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - {f13bac10-bcbe-4440-b9f0-3a2778ca9221} - LinqFasterParallelSIMD - - - {1b6d88e4-8745-4a0e-b459-53f7add04a12} - LinqFasterParallel - - - {050c43b5-4a4f-45d9-be0c-9b2a6acc189e} - LinqFasterSIMD - - - {68835792-9274-4ddc-8312-29700ef16f62} - LinqFasterSpan - - - {5b2f0f9f-6dda-4f06-a999-26e43ae04f86} - LinqFaster - - - - - ..\packages\BenchmarkDotNet.0.11.5\lib\netstandard2.0\BenchmarkDotNet.dll - - - ..\packages\BenchmarkDotNet.Annotations.0.11.5\lib\netstandard2.0\BenchmarkDotNet.Annotations.dll - - - ..\packages\CommandLineParser.2.5.0\lib\net461\CommandLine.dll - - - ..\packages\Microsoft.CodeAnalysis.Common.3.1.0\lib\netstandard2.0\Microsoft.CodeAnalysis.dll - - - ..\packages\Microsoft.CodeAnalysis.CSharp.3.1.0\lib\netstandard2.0\Microsoft.CodeAnalysis.CSharp.dll - - - ..\packages\Microsoft.DotNet.InternalAbstractions.1.0.0\lib\net451\Microsoft.DotNet.InternalAbstractions.dll - - - ..\packages\Microsoft.DotNet.PlatformAbstractions.2.1.0\lib\net45\Microsoft.DotNet.PlatformAbstractions.dll - - - ..\packages\Microsoft.Win32.Registry.4.5.0\lib\net461\Microsoft.Win32.Registry.dll - - - - ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll - True - True - - - ..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll - - - - ..\packages\System.Console.4.3.1\lib\net46\System.Console.dll - True - True - - - ..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll - True - True - - - ..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll - True - True - - - ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll - True - True - - - ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll - True - True - - - ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll - True - True - - - - - ..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll - - - ..\packages\System.Reflection.TypeExtensions.4.5.1\lib\net461\System.Reflection.TypeExtensions.dll - - - ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll - True - True - - - ..\packages\System.Security.AccessControl.4.5.0\lib\net461\System.Security.AccessControl.dll - - - ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll - True - True - - - ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll - True - True - - - ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll - True - True - - - ..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll - True - True - - - ..\packages\System.Security.Principal.Windows.4.5.1\lib\net461\System.Security.Principal.Windows.dll - - - ..\packages\System.Text.Encoding.CodePages.4.5.1\lib\net461\System.Text.Encoding.CodePages.dll - - - ..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll - - - ..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll - True - True - - - ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll - - - - - ..\packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll - True - True - - - ..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll - True - True - - - ..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll - True - True - - - ..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll - True - True - - - ..\packages\System.Xml.XPath.XmlDocument.4.3.0\lib\net46\System.Xml.XPath.XmlDocument.dll - - - - - - - - + + - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + Debug + AnyCPU + {42DD1432-5209-49B3-81D7-B487A9DBF2F3} + Exe + Properties + Tests + Benchmarks + v4.6.1 + 512 + true + + + - - -