├── .gitignore
├── .travis.yml
├── Benchmarks.md
├── LICENSE
├── LinqFasterParallel
├── AverageParallel.cs
├── ContainsParallel.cs
├── CountParallel.cs
├── LinqFasterParallel.csproj
├── MaxParallel.cs
├── MinParallel.cs
├── SelectParallel.cs
├── SelectWhereParallel.cs
├── SequenceEqualParallel.cs
├── SumParallel.cs
├── WhereAggregateParallel.cs
├── WhereParallel.cs
└── WhereSelectParallel.cs
├── LinqFasterParallelSIMD
├── AverageSIMDParallel.cs
├── LinqFasterParallelSIMD.csproj
├── SelectSIMDParallel.cs
├── SequenceEqualSIMDParallel.cs
└── SumSIMDParallel.cs
├── LinqFasterSIMD
├── AverageSIMD.cs
├── ContainsSIMD.cs
├── LinqFasterSIMD.csproj
├── MaxSIMD.cs
├── MinSIMD.cs
├── RangeSIMD.cs
├── RepeatSIMD.cs
├── SelectSIMD.cs
├── SequenceEqualSIMD.cs
└── SumSIMD.cs
├── LinqFasterer.Benchmark
├── Benchmarkable.cs
├── Benchmarks
│ ├── AggregateBenchmark.cs
│ ├── AllBenchmark.cs
│ ├── AnyBenchmark.cs
│ ├── AppendBenchmark.cs
│ ├── AverageBenchmark.cs
│ ├── ConcatBenchmark.cs
│ ├── ContainsBenchmark.cs
│ ├── CountBenchmark.cs
│ ├── DefaultIfEmptyBenchmark.cs
│ ├── DistinctBenchmark.cs
│ ├── ElementAtBenchmark.cs
│ ├── EmptyBenchmark.cs
│ ├── ExceptBenchmark.cs
│ ├── FirstBenchmark.cs
│ ├── IntersectBenchmark.cs
│ ├── LastBenchmark.cs
│ ├── MaxBenchmark.cs
│ ├── MinBenchmark.cs
│ ├── OrderByBenchmark.cs
│ ├── PrependBenchmark.cs
│ ├── RangeBenchmark.cs
│ ├── RepeatBenchmark.cs
│ ├── ReverseBenchmark.cs
│ ├── SelectBenchmark.cs
│ ├── SelectManyBenchmark.cs
│ ├── SequenceEqualBenchmark.cs
│ ├── SingleBenchmark.cs
│ ├── SkipBenchmark.cs
│ ├── SumBenchmark.cs
│ ├── TakeBenchmark.cs
│ ├── ToCastBenchmark.cs
│ ├── UnionBenchmark.cs
│ ├── WhereBenchmark.cs
│ └── ZipBenchmark.cs
├── LinqFasterer.Benchmarks.csproj
└── Program.cs
├── LinqFasterer.Shared
├── LinqFasterer.Shared.projitems
├── LinqFasterer.Shared.shproj
└── Utilities.cs
├── LinqFasterer.Tests
├── AggregateTests.cs
├── AllNullTests.cs
├── AllTests.cs
├── AnyTests.cs
├── AppendTests.cs
├── AverageTests.cs
├── BinarySearchTests.cs
├── ClearTests.cs
├── CloneTests.cs
├── ConcatTests.cs
├── ContainsNullTests.cs
├── ContainsTests.cs
├── CountTests.cs
├── DefaultIfEmptyTests.cs
├── DistinctTests.cs
├── ElementAtTests.cs
├── EmptyTests.cs
├── ExceptTests.cs
├── FillTests.cs
├── FirstTests.cs
├── ForEachTests.cs
├── IntersectTests.cs
├── IsOrderedByTests.cs
├── IsSortedTests.cs
├── LastTests.cs
├── LinqFasterer.Tests.csproj
├── MaxTests.cs
├── MinTests.cs
├── OrderByTests.cs
├── PrependTests.cs
├── RangeTests.cs
├── RepeatTests.cs
├── ReverseTests.cs
├── SelectManyTests.cs
├── SelectTests.cs
├── SelfTests.cs
├── SequenceEqualTests.cs
├── SingleTests.cs
├── SkipTests.cs
├── SortTests.cs
├── Sum16Tests.cs
├── Sum1Tests.cs
├── Sum4Tests.cs
├── SumTests.cs
├── TakeTests.cs
├── ToCastTests.cs
├── UnionTests.cs
├── WhereTests.cs
└── ZipTests.cs
├── LinqFasterer.sln
├── LinqFasterer.sln.DotSettings
├── LinqFasterer
├── Aggregate.cs
├── All.cs
├── AllNullF.cs
├── Any.cs
├── Append.cs
├── Average.cs
├── BinarySearch.cs
├── Clear.cs
├── Clone.cs
├── Concat.cs
├── Contains.cs
├── ContainsNull.cs
├── Count.cs
├── DefaultIfEmpty.cs
├── Distinct.cs
├── ElementAt.cs
├── Empty.cs
├── Enumerable.cs
├── Except.cs
├── Fill.cs
├── First.cs
├── ForEach.cs
├── Intersect.cs
├── IsOrderedBy.cs
├── IsSorted.cs
├── Last.cs
├── LinqFasterer.csproj
├── Max.cs
├── Min.cs
├── OrderBy.cs
├── Prepend.cs
├── Range.cs
├── Repeat.cs
├── Reverse.cs
├── Select.cs
├── SelectMany.cs
├── SequenceEqual.cs
├── Single.cs
├── Skip.cs
├── Sort.cs
├── Sum.cs
├── Sum1.cs
├── Sum16.cs
├── Sum4.cs
├── Take.cs
├── ToCast.cs
├── Union.cs
├── Utils
│ ├── ComparerMagic.cs
│ ├── CustomPartition.cs
│ ├── Error.cs
│ ├── GenericOperators.cs
│ └── SliceHelper.cs
├── Where.cs
└── Zip.cs
├── README.md
├── benchmarks
├── LinqFasterer.Benchmarks.Benchmarks.AggregateBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.AllBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.AnyBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.AppendBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.AverageBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ConcatBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ConcatMultipleBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ConcatMultipleStrBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ContainsBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ContainsComparerBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.CountBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.CountPredicateBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.DefaultIfEmptyBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.DistinctBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ElementAtBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.EmptyBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ExceptBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.FirstBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.FirstPredicateBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.IntersectBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.LastBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.LastPredicateBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.MaxBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.MinBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.OrderByBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.OrderByDescendingBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.PrependBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.RangeBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.RepeatBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.RepeatSequenceBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ReverseBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.SelectBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.SelectManyBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.SequenceEqualBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.SingleBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.SkipBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.SkipLastBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.SumBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.TakeBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.TakeLastBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ToArrayBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ToArrayFromListBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ToListBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.UnionBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.WhereBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.WhereIndexedBenchmark-report-github.md
├── LinqFasterer.Benchmarks.Benchmarks.ZipBenchmark-report-github.md
└── LinqFasterer.Benchmarks.Benchmarks.ZipSelectorBenchmark-report-github.md
├── docs
└── linqfaster.xml
└── resources
├── icon-24.png
├── icon-32.png
├── icon-48.png
├── icon-64.png
├── icon.png
└── icon.xcf
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: csharp
2 | dotnet: 5.0.201
3 | mono: none
4 |
5 | before_script:
6 | - dotnet restore
7 |
8 | script:
9 | - dotnet build -c Debug
10 | - dotnet build -c Release
11 |
12 | - dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
13 | - bash <(curl -s https://codecov.io/bash)
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Original work Copyright (c) 2017 Jack Mott
4 | Modified work Copyright (c) 2021 Kamil Monicz
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
--------------------------------------------------------------------------------
/LinqFasterParallel/LinqFasterParallel.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.3
5 | LinqFaster.Parallel
6 | 1.0.1
7 | Jack Mott
8 | Jack Mott
9 | LinqFaster Parallel
10 | Provides multithreaded Linq-Like extensions for arrays and lists.
11 | Copyright 2017 (c) Jack Mott. All rights reserved.
12 | https://github.com/jackmott/LinqFaster
13 | https://jackmott.github.io/images/LinqFaster.png
14 | https://github.com/jackmott/LinqFaster
15 | Github
16 | performance parallel multithreaded linq
17 | Added SequenceEqual
18 |
19 |
20 |
21 | ..\docs\linqfaster-parallel.xml
22 | true
23 |
24 |
25 |
26 | true
27 |
28 |
29 |
30 | true
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/LinqFasterParallelSIMD/AverageSIMDParallel.cs:
--------------------------------------------------------------------------------
1 | using static JM.LinqFaster.Utils.GenericOperators;
2 |
3 | namespace JM.LinqFaster.SIMD.Parallel
4 | {
5 |
6 | ///
7 | /// Provides Linq style extension methods that use both
8 | /// SIMD and multiple threads / tasks.
9 | ///
10 | public static partial class LinqFasterSIMDParallel
11 | {
12 |
13 | ///
14 | /// Calculates the average value of an array using SIMD and
15 | /// multiple threads/tasks.
16 | ///
17 | /// The sequence of primitive values to average
18 | /// Optional. Specify a batch size for Tasks to operate over.
19 | /// The average of the sequence of values as a double
20 | public static double AverageSP(this T[] source, int? batchSize = null) where T : struct
21 | {
22 | return Divide(SumSP(source,batchSize),source.Length);
23 | }
24 |
25 | ///
26 | /// Calculates the average value of an array using SIMD and
27 | /// multiple threads/tasks.
28 | ///
29 | /// The sequence of primitive values to average
30 | /// Optional. Specify a batch size for Tasks to operate over.
31 | /// The average of the sequence of values as a double
32 | public static float AverageSPf(this T[] source, int? batchSize = null) where T : struct
33 | {
34 | return DivideFloat(SumSP(source,batchSize), source.Length);
35 | }
36 |
37 | /*
38 | public static double AverageSP(this T[] source, Func,Vector> selectorSIMD, Func selector, int? batchSize = null )
39 | where T : struct
40 | where U : struct
41 | {
42 | return Divide(SumSP(source,selectorSIMD,selector,batchSize), source.Length);
43 | }
44 |
45 | public static float AverageSPf(this T[] source, Func, Vector> selectorSIMD, Func selector, int? batchSize = null)
46 | where T : struct
47 | where U : struct
48 | {
49 | return DivideFloat(SumSP(source, selectorSIMD, selector, batchSize), source.Length);
50 | }
51 | */
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/LinqFasterParallelSIMD/LinqFasterParallelSIMD.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.3
5 | 1.0.1
6 | Jack Mott
7 |
8 | High performance Linq-style extension methods that are multithreaded and use System.Numerics SIMD for arrays and lists.
9 | Copyright 2017 (c) Jack Mott. All rights reserved.
10 | https://github.com/jackmott/LinqFaster
11 | https://github.com/jackmott/LinqFaster
12 | https://jackmott.github.io/images/LinqFaster.png
13 | Github
14 | performance linq simd system.numerics multithreaded parallel
15 | Added SequenceEqual
16 |
17 | LinqFaster.SIMD.Parallel
18 | LinqFaster.SIMD.Parallel
19 |
20 |
21 |
22 | ..\docs\linqfaster-parallel-simd.xml
23 | true
24 |
25 |
26 |
27 | true
28 |
29 |
30 |
31 | true
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/LinqFasterParallelSIMD/SelectSIMDParallel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Numerics;
3 | using static JM.LinqFaster.Utils.CustomPartition;
4 |
5 | namespace JM.LinqFaster.SIMD.Parallel
6 | {
7 |
8 | public static partial class LinqFasterSIMDParallel
9 | {
10 |
11 | ///
12 | /// Projects each element of a sequence into a new form with SIMD and
13 | /// multiple threads / tasks.
14 | ///
15 | /// The sequence of primitive values to transform.
16 | /// A transformation function that operates on Vectors.
17 | /// An optional selection function to transform the leftover values.
18 | /// Optional. Specify a batch size for Tasks to operate over.
19 | /// A sequence of transformed values.
20 | public static U[] SelectSP(this T[] source, Func, Vector> selectorSIMD, Func selector = null, int? batchSize = null)
21 | where T : struct
22 | where U : struct
23 | {
24 | if (source == null)
25 | {
26 | throw Error.ArgumentNull("source");
27 | }
28 |
29 | var count = Vector.Count;
30 |
31 | if (count != Vector.Count)
32 | {
33 | throw Error.ArgumentOutOfRange("Vector widths do not match.");
34 | }
35 |
36 | var result = new U[source.Length];
37 | var rangePartitioner = MakeSIMDPartition(source.Length, count, batchSize);
38 | System.Threading.Tasks.Parallel.ForEach(rangePartitioner,
39 | (range, s) =>
40 | {
41 | var index = range.Item1 * count;
42 | for (var i = range.Item1; i < range.Item2; i++)
43 | {
44 | selectorSIMD(new Vector(source, index)).CopyTo(result, index);
45 | index += count;
46 | }
47 |
48 | });
49 |
50 | if (selector != null)
51 | {
52 | for (var i = source.Length - source.Length % count; i < source.Length; i++)
53 | {
54 | result[i] = selector(source[i]);
55 | }
56 | }
57 |
58 |
59 | return result;
60 | }
61 |
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/LinqFasterParallelSIMD/SequenceEqualSIMDParallel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Numerics;
3 | using System.Threading;
4 | using static JM.LinqFaster.Utils.CustomPartition;
5 |
6 | namespace JM.LinqFaster.SIMD.Parallel
7 | {
8 |
9 | public static partial class LinqFasterSIMDParallel
10 | {
11 |
12 | ///
13 | /// Determines whether two sequences are equal by comparing the elements using bitwise comparison
14 | ///
15 | /// A sequence to compare to second.
16 | /// A sequence to compare to first.
17 | /// Optional. Specify a batch size for Tasks to operate over.
18 | /// true of the two sources are of equal length and their corresponding
19 | /// elements are equal according to the equality comparer. Otherwise, false.
20 | public static bool SequenceEqualSP(this T[] first, T[] second,int? batchSize = null) where T: struct
21 | {
22 |
23 | if (first == null)
24 | {
25 | throw Error.ArgumentNull("first");
26 | }
27 |
28 | if (second == null)
29 | {
30 | throw Error.ArgumentNull("second");
31 | }
32 |
33 | if (first.Length != second.Length) return false;
34 | if (first == second) return true;
35 |
36 | var count = Vector.Count;
37 | var nonEqualCount = 0;
38 | var rangePartitioner = MakeSIMDPartition(first.Length, count, batchSize);
39 | System.Threading.Tasks.Parallel.ForEach(rangePartitioner,
40 | (range, loopState) =>
41 | {
42 |
43 | var index = range.Item1 * count;
44 | for (var i = range.Item1; i < range.Item2; i++)
45 | {
46 | if (!Vector.EqualsAll(new Vector(first, index), new Vector(second, index)))
47 | {
48 | Interlocked.Increment(ref nonEqualCount);
49 | loopState.Break();
50 | }
51 | index += count;
52 | }
53 |
54 | });
55 | if (nonEqualCount != 0) return false;
56 | var comparer = EqualityComparer.Default;
57 | for (var i = first.Length - (first.Length % count); i < first.Length; i++)
58 | {
59 | if (!comparer.Equals(first[i], second[i])) return false;
60 | }
61 | return true;
62 | }
63 |
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/LinqFasterParallelSIMD/SumSIMDParallel.cs:
--------------------------------------------------------------------------------
1 | using System.Numerics;
2 | using static JM.LinqFaster.Utils.GenericOperators;
3 | using static JM.LinqFaster.Utils.CustomPartition;
4 |
5 | namespace JM.LinqFaster.SIMD.Parallel
6 | {
7 |
8 | public static partial class LinqFasterSIMDParallel
9 | {
10 |
11 | ///
12 | /// Sums the values in source using SIMD and multiple Tasks/Threads.
13 | ///
14 | /// A sequence to sum.
15 | /// Optional. Specify a batch size for Tasks to operate over.
16 | ///
17 | public static T SumSP(this T[] source, int? batchSize = null) where T : struct
18 | {
19 | if (source == null)
20 | {
21 | throw Error.ArgumentNull("source");
22 | }
23 |
24 | var count = Vector.Count;
25 | var sum = Vector.Zero;
26 | var LOCK = new object();
27 |
28 | var rangePartitioner = MakeSIMDPartition(source.Length, count, batchSize);
29 | System.Threading.Tasks.Parallel.ForEach(rangePartitioner,
30 | () => Vector.Zero,
31 | (range, s, acc) =>
32 | {
33 | var index = range.Item1 * count;
34 | for (var i = range.Item1; i < range.Item2; i++)
35 | {
36 | acc += new Vector(source, index);
37 | index += count;
38 | }
39 |
40 | return acc;
41 | },
42 | acc =>
43 | {
44 | lock (LOCK)
45 | {
46 | sum = sum + acc;
47 | }
48 | });
49 |
50 | var result = default(T);
51 | for (var i = 0; i < count; i++)
52 | {
53 | result = Add(result, sum[i]);
54 | }
55 | return result;
56 | }
57 |
58 |
59 |
60 |
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/LinqFasterSIMD/AverageSIMD.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Numerics;
3 | using static JM.LinqFaster.Utils.GenericOperators;
4 |
5 | namespace JM.LinqFaster.SIMD
6 | {
7 | ///
8 | /// SIMD accelerated Linq-style extension methods for arrays.
9 | ///
10 | public static partial class LinqFasterSIMD
11 | {
12 | ///
13 | /// Calculates the average value of an array using SIMD.
14 | ///
15 | /// The sequence of primitive values to average
16 | /// The average of the sequence of values as a double
17 | public static double AverageS(this T[] source) where T : struct
18 | {
19 | return Divide(SumS(source),source.Length);
20 | }
21 |
22 | ///
23 | /// Calculates the average value of an array via a selector using SIMD.
24 | ///
25 | /// The sequence of primitive values to transform then average
26 | /// A transformation function to operate on vectors.
27 | /// A transformation function to operate on leftover elements.
28 | /// The average of the transformed sequence of values as a double
29 | public static double AverageS(this T[] source, Func, Vector> selectorSIMD, Func selector = null)
30 | where T : struct
31 | where U : struct
32 | {
33 |
34 | return Divide(SumS(source,selectorSIMD,selector), source.Length);
35 | }
36 |
37 | ///
38 | /// Calculates the average value of an array using SIMD.
39 | ///
40 | /// The sequence of primitive values to average
41 | /// The average of the sequence of values as a float
42 | public static float AverageSf(this T[] source) where T : struct
43 | {
44 | return DivideFloat(SumS(source), source.Length);
45 | }
46 |
47 | ///
48 | /// Calculates the average value of an array via a selector using SIMD.
49 | ///
50 | /// The sequence of primitive values to transform then average
51 | /// A transformation function to operate on vectors.
52 | /// A transformation function to operate on leftover elements.
53 | /// The average of the transformed sequence of values as a double
54 | public static float AverageSf(this T[] source, Func, Vector> selectorSIMD, Func selector = null)
55 | where T : struct
56 | where U : struct
57 | {
58 |
59 | return DivideFloat(SumS(source, selectorSIMD, selector), source.Length);
60 | }
61 |
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/LinqFasterSIMD/ContainsSIMD.cs:
--------------------------------------------------------------------------------
1 | using System.Numerics;
2 | using JM.LinqFaster.Utils;
3 |
4 | namespace JM.LinqFaster.SIMD
5 | {
6 |
7 | public static partial class LinqFasterSIMD
8 | {
9 |
10 | ///
11 | /// Determines whether an array contains a specified element
12 | /// using SIMD.
13 | ///
14 | /// An array in which to locate a value.
15 | /// The value to locate.
16 | /// true if the source sequence contains an element that has the specified value; otherwise, false.
17 | public static bool ContainsS(this T[] source, T value)
18 | where T : struct
19 | {
20 | if (source == null)
21 | {
22 | throw Error.ArgumentNull("source");
23 | }
24 |
25 | var count = Vector.Count;
26 | var vectorValue = new Vector(value);
27 | for (var i = 0; i < source.Length-count;i+=count)
28 | {
29 | if (Vector.EqualsAny(new Vector(source,i),vectorValue))
30 | {
31 | return true;
32 | }
33 | }
34 | for (var i = source.Length-(source.Length%count); i < source.Length;i++)
35 | {
36 | if (GenericOperators.Equals(source[i],value)) return true;
37 | }
38 | return false;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/LinqFasterSIMD/LinqFasterSIMD.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | 1.0.2
6 | Jack Mott
7 |
8 | High performance Linq-style extension methods that use System.Numerics SIMD for arrays.
9 | Copyright 2017 (c) Jack Mott. All rights reserved.
10 | https://github.com/jackmott/LinqFaster
11 | https://github.com/jackmott/LinqFaster
12 | https://jackmott.github.io/images/LinqFaster.png
13 | Github
14 | performance linq simd system.numerics
15 | Added SequenceCompre and fixed bug in SequenceEqual
16 |
17 | LinqFaster.SIMD
18 | LinqFaster.SIMD
19 |
20 |
21 |
22 | ..\docs\linqfaster-simd.xml
23 | true
24 |
25 |
26 |
27 | true
28 |
29 |
30 |
31 | true
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/LinqFasterSIMD/MaxSIMD.cs:
--------------------------------------------------------------------------------
1 | using System.Numerics;
2 | using static JM.LinqFaster.Utils.GenericOperators;
3 |
4 | namespace JM.LinqFaster.SIMD
5 | {
6 |
7 | public static partial class LinqFasterSIMD
8 | {
9 | ///
10 | /// Finds the maximum value the sequence using SIMD
11 | ///
12 | /// A sequence of primitive values
13 | /// The maximum value in the sequence
14 | public static T MaxS (this T[] source)
15 | where T : struct
16 | {
17 | if (source == null)
18 | {
19 | throw Error.ArgumentNull("source");
20 | }
21 |
22 | if (source.Length == 0)
23 | {
24 | throw Error.NoElements();
25 | }
26 |
27 | var max = source[0];
28 | var count = Vector.Count;
29 | if (count <= source.Length)
30 | {
31 | var vMax = new Vector(source, 0);
32 | for (var i = count; i <= source.Length-count; i+=count)
33 | {
34 | var v = new Vector(source, i);
35 | vMax = Vector.Max(v, vMax);
36 | }
37 |
38 | max = vMax[0];
39 | for (var i = 1; i < count; i++)
40 | {
41 | if (GreaterThan(vMax[i], max)) max = vMax[i];
42 | }
43 | }
44 |
45 | for (var i = source.Length-source.Length%count; i < source.Length;i++)
46 | {
47 | if (GreaterThan(source[i],max)) max = source[i];
48 | }
49 | return max;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/LinqFasterSIMD/MinSIMD.cs:
--------------------------------------------------------------------------------
1 | using System.Numerics;
2 | using static JM.LinqFaster.Utils.GenericOperators;
3 |
4 | namespace JM.LinqFaster.SIMD
5 | {
6 |
7 | public static partial class LinqFasterSIMD
8 | {
9 |
10 | ///
11 | /// Finds the minimum value in a sequence using SIMD.
12 | ///
13 | /// A sequence of primitive values
14 | /// The minimum value in the sequence
15 | public static T MinS (this T[] source)
16 | where T : struct
17 | {
18 | if (source == null)
19 | {
20 | throw Error.ArgumentNull("source");
21 | }
22 |
23 | if (source.Length == 0)
24 | {
25 | throw Error.NoElements();
26 | }
27 |
28 | var min = source[0];
29 | var count = Vector.Count;
30 | if (count <= source.Length)
31 | {
32 | var vMin = new Vector(source, 0);
33 | for (var i = count; i <= source.Length-count; i+=count)
34 | {
35 | var v = new Vector(source, i);
36 | vMin = Vector.Min(v, vMin);
37 | }
38 |
39 | min = vMin[0];
40 | for (var i = 1; i < count; i++)
41 | {
42 | if (LessThan(vMin[i], min)) min = vMin[i];
43 | }
44 | }
45 |
46 | for (var i = source.Length-source.Length%count; i < source.Length;i++)
47 | {
48 | if (LessThan(source[i],min)) min = source[i];
49 | }
50 | return min;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/LinqFasterSIMD/RangeSIMD.cs:
--------------------------------------------------------------------------------
1 | using System.Numerics;
2 |
3 | namespace JM.LinqFaster.SIMD
4 | {
5 |
6 | public static partial class LinqFasterSIMD
7 | {
8 |
9 | ///
10 | /// Generates a sequence of integral numbers within a specified range
11 | /// using SIMD
12 | ///
13 | /// The value of the first integer in the sequence.
14 | /// The number of sequential integers to generate.
15 | /// A sequence that contains a range of sequential integral numbers.
16 | public static int[] RangeS(int start, int len)
17 | {
18 | var max = ((long)start) + len - 1;
19 | if (len < 0 || max > int.MaxValue) {
20 | throw Error.ArgumentOutOfRange("len");
21 | }
22 |
23 | var count = Vector.Count;
24 | var result = new int[len];
25 | if (len >= count) {
26 | //use result array for double duty to save memory
27 |
28 | for (var i = 0; i < count; i++) {
29 | result[i] = i + start;
30 | }
31 |
32 | var V = new Vector(result);
33 | var Increment = new Vector(count);
34 | V = V + Increment;
35 | for (var i = count; i <= len - count; i += count) {
36 | V.CopyTo(result, i);
37 | V = V + Increment;
38 | }
39 | }
40 |
41 | for (var i = len - len % count; i < len; i++) {
42 | result[i] = i + start;
43 | }
44 |
45 | return result;
46 |
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/LinqFasterSIMD/RepeatSIMD.cs:
--------------------------------------------------------------------------------
1 | using System.Numerics;
2 |
3 | namespace JM.LinqFaster.SIMD
4 | {
5 |
6 | public static partial class LinqFasterSIMD
7 | {
8 | ///
9 | /// Generates a sequence that contains one repeated value using SIMD.
10 | ///
11 | /// The value to be repeated.
12 | /// The number of times to repeat the value in the generated sequence.
13 | /// A sequence that contains a repeated value
14 | public static T[] RepeatS(T e, int count)
15 | where T : struct
16 | {
17 | if (count < 0)
18 | {
19 | throw Error.ArgumentOutOfRange("count");
20 | }
21 |
22 | var result = new T[count];
23 | var v = new Vector(e);
24 | var vCount = Vector.Count;
25 |
26 | var i = 0;
27 | for (; i <= result.Length-vCount; i += vCount)
28 | {
29 | v.CopyTo(result, i);
30 | }
31 |
32 | for (i = count-count%vCount;i < result.Length;i++)
33 | {
34 | result[i] = e;
35 | }
36 |
37 | return result;
38 |
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/LinqFasterSIMD/SelectSIMD.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Numerics;
3 |
4 | namespace JM.LinqFaster.SIMD
5 | {
6 |
7 | public static partial class LinqFasterSIMD
8 | {
9 |
10 | ///
11 | /// Projects each element of a sequence into a new form with SIMD.
12 | ///
13 | /// The sequence of primitive values to transform.
14 | /// A transformation function that operates on Vectors.
15 | /// An optional selection function to transform the leftover values.
16 | /// A sequence of transformed values.
17 | public static U[] SelectS(this T[] source, Func,Vector> slectorSIMD, Func selector = null)
18 | where T : struct
19 | where U : struct
20 | {
21 | if (source == null)
22 | {
23 | throw Error.ArgumentNull("source");
24 | }
25 | if (slectorSIMD == null)
26 | {
27 | throw Error.ArgumentNull("selectorSIMD");
28 | }
29 |
30 | var count = Vector.Count;
31 |
32 | if (count != Vector.Count)
33 | {
34 | throw Error.ArgumentOutOfRange("selectorSIMD");
35 | }
36 |
37 | var result = new U[source.Length];
38 |
39 | var i = 0;
40 | for (; i <= source.Length-count;i+=count)
41 | {
42 | slectorSIMD(new Vector(source, i)).CopyTo(result, i);
43 | }
44 |
45 | if (selector != null)
46 | {
47 | i = source.Length - source.Length % count;
48 | for (; i < result.Length; i++)
49 | {
50 | result[i] = selector(source[i]);
51 | }
52 | }
53 | return result;
54 | }
55 |
56 | ///
57 | /// Selects/Maps in place each element of a sequence into a new form with SIMD.
58 | ///
59 | /// The sequence of primitive values to transform.
60 | /// A transformation function that operates on Vectors.
61 | /// An optional selection function to transform the leftover values.
62 | public static void SelectInPlaceS(this T[] source, Func, Vector> slectorSIMD, Func selector = null)
63 | where T : struct
64 | {
65 | if (source == null)
66 | {
67 | throw Error.ArgumentNull("source");
68 | }
69 | if (slectorSIMD == null)
70 | {
71 | throw Error.ArgumentNull("selectorSIMD");
72 | }
73 |
74 | var count = Vector.Count;
75 |
76 |
77 | var i = 0;
78 | for (; i <= source.Length - count; i += count)
79 | {
80 | slectorSIMD(new Vector(source, i)).CopyTo(source, i);
81 | }
82 |
83 | if (selector != null)
84 | {
85 | i = source.Length - source.Length % count;
86 | for (; i < source.Length; i++)
87 | {
88 | source[i] = selector(source[i]);
89 | }
90 | }
91 | }
92 |
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/LinqFasterSIMD/SumSIMD.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Numerics;
3 | using static JM.LinqFaster.Utils.GenericOperators;
4 |
5 |
6 | namespace JM.LinqFaster.SIMD
7 | {
8 |
9 | public static partial class LinqFasterSIMD
10 | {
11 |
12 | ///
13 | /// Computes the sum of a sequence using SIMD
14 | ///
15 | /// A sequence of primitive values to sum.
16 | /// The sum of the sequence of values.
17 | public static T SumS(this T[] source) where T:struct
18 | {
19 | if (source == null)
20 | {
21 | throw Error.ArgumentNull("source");
22 | }
23 |
24 | var state = Vector.Zero;
25 | var count = Vector.Count;
26 |
27 | for (var i = 0; i <= source.Length - count; i+=count)
28 | {
29 | state = state + new Vector(source, i);
30 | }
31 |
32 | var result = default(T);
33 |
34 | for (var i = source.Length-source.Length % count; i < source.Length;i++)
35 | {
36 | result = Add(result,source[i]);
37 | }
38 |
39 | for (var i = 0; i < count; i++)
40 | {
41 | result = Add(result, state[i]);
42 | }
43 |
44 | return result;
45 | }
46 |
47 |
48 | ///
49 | /// Computes the sum of a sequence of transformed values using SIMD
50 | ///
51 | /// A sequence of elements to transform then sum.
52 | /// A transformation function that operates on vectors.
53 | /// An optional transformation function to transform any leftover elements.
54 | /// The sum of the sequence of transformed values.
55 | public static U SumS(this T[] source, Func,Vector> selectorSIMD, Func selector = null)
56 | where T : struct
57 | where U : struct
58 | {
59 | if (source == null)
60 | {
61 | throw Error.ArgumentNull("source");
62 | }
63 | if (selectorSIMD == null)
64 | {
65 | throw Error.ArgumentNull("selectorSIMD");
66 | }
67 |
68 | var state = Vector.Zero;
69 | var count = Vector.Count;
70 |
71 | for (var i = 0; i <= source.Length-count; i += count)
72 | {
73 | state = state + selectorSIMD(new Vector(source, i));
74 | }
75 |
76 | var result = default(U);
77 |
78 | if (selector != null)
79 | {
80 | for (var i = source.Length - source.Length % count; i < source.Length; i++)
81 | {
82 | result = Add(result, selector(source[i]));
83 | }
84 | }
85 |
86 | for (var i = 0; i < count; i++)
87 | {
88 | result = Add(result, state[i]);
89 | }
90 |
91 | return result;
92 | }
93 |
94 |
95 |
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarkable.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks
5 | {
6 | //[SimpleJob(launchCount:1, warmupCount:1, targetCount:4)]
7 | [SimpleJob(launchCount:1, warmupCount:2, targetCount:10)]
8 | public class Benchmarkable
9 | {
10 | //[Params(50000)]
11 | [Params(0, 1, 3, 5, 10, 50, 100, 250, 500, 1000, 1500, 2000, 2500, 3000, 5000, 10_000, 50_000, 100_000, 500_000, 1_000_000)]
12 | // ReSharper disable once UnassignedField.Global
13 | protected int N;
14 |
15 | protected int[] Data;
16 | protected int[] DataSecondary;
17 |
18 | [GlobalSetup]
19 | public void GlobalSetup()
20 | {
21 | Data = Shared.Utilities.TestArray(typeof(int), N, 0, 1000).ToArray()[0][0] as int[];
22 | DataSecondary = Shared.Utilities.TestArray(typeof(int), N, 500, 1500).ToArray()[0][0] as int[];
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/AggregateBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class AggregateBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int AggregateLinq()
10 | {
11 | return Data.Aggregate((l, r) => l ^ r);
12 | }
13 |
14 | [Benchmark]
15 | public int AggregateFaster()
16 | {
17 | return Data.AggregateF((l, r) => l ^ r);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/AllBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class AllBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public bool AllLinq()
10 | {
11 | return Data.All(v => v > -1);
12 | }
13 |
14 | [Benchmark]
15 | public bool AllFaster()
16 | {
17 | return Data.AllF(v => v > -1);
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/AnyBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class AnyBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public bool AnyLinq()
10 | {
11 | return Data.Any(v => v > -1);
12 | }
13 |
14 | [Benchmark]
15 | public bool AnyFaster()
16 | {
17 | return Data.AnyF(v => v > -1);
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/AppendBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class AppendBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] AppendLinq()
10 | {
11 | return Data.Append(5).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] AppendFaster()
16 | {
17 | return Data.AppendF(5).ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/AverageBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class AverageBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public double AverageLinq()
10 | {
11 | return Data.Average();
12 | }
13 |
14 | [Benchmark]
15 | public double AverageFaster()
16 | {
17 | return Data.AverageF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/ConcatBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class ConcatBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] ConcatLinq()
10 | {
11 | return Data.Concat(DataSecondary).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] ConcatFaster()
16 | {
17 | return Data.ConcatF(DataSecondary).ToArrayF();
18 | }
19 | }
20 |
21 | public class ConcatMultipleBenchmark : Benchmarkable
22 | {
23 | [Benchmark(Baseline = true)]
24 | public int[] ConcatMultipleFaster()
25 | {
26 | return EnumerableF.ConcatMultipleF(Data, DataSecondary, Data, DataSecondary).ToArrayF();
27 | }
28 | }
29 |
30 | public class ConcatMultipleStrBenchmark : Benchmarkable
31 | {
32 | [Benchmark(Baseline = true)]
33 | public string ConcatMultipleStrFaster()
34 | {
35 | return EnumerableF.ConcatMultipleF(Data.SelectF(i => i.ToString()).ToArrayF());
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/ContainsBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using BenchmarkDotNet.Attributes;
4 |
5 | namespace LinqFasterer.Benchmarks.Benchmarks
6 | {
7 | public class ContainsBenchmark : Benchmarkable
8 | {
9 | [Benchmark(Baseline = true)]
10 | public bool ContainsLinq()
11 | {
12 | return Data.Contains(-5);
13 | }
14 |
15 | [Benchmark]
16 | public bool ContainsFaster()
17 | {
18 | return Data.ContainsF(-5);
19 | }
20 | }
21 |
22 | public class ContainsComparerBenchmark : Benchmarkable
23 | {
24 | [Benchmark(Baseline = true)]
25 | public bool ContainsComparerLinq()
26 | {
27 | return Data.Contains(-5, EqualityComparer.Default);
28 | }
29 |
30 | [Benchmark]
31 | public bool ContainsComparerFaster()
32 | {
33 | return Data.ContainsF(-5, EqualityComparer.Default);
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/CountBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class CountBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int CountLinq()
10 | {
11 | return Data.Count();
12 | }
13 |
14 | [Benchmark]
15 | public int CountFaster()
16 | {
17 | return Data.CountF();
18 | }
19 | }
20 |
21 | public class CountPredicateBenchmark : Benchmarkable
22 | {
23 | [Benchmark(Baseline = true)]
24 | public int CountPredicateLinq()
25 | {
26 | return Data.Count(v => v % 2 == 0);
27 | }
28 |
29 | [Benchmark]
30 | public int CountPredicateFaster()
31 | {
32 | return Data.CountF(v => v % 2 == 0);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/DefaultIfEmptyBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class DefaultIfEmptyBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] DefaultIfEmptyLinq()
10 | {
11 | return Data.DefaultIfEmpty().ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] DefaultIfEmptyFaster()
16 | {
17 | return Data.DefaultIfEmptyF().ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/DistinctBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class DistinctBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] DistinctLinq()
10 | {
11 | return Data.Distinct().ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] DistinctFaster()
16 | {
17 | return Data.DistinctF().ToArrayF();
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/ElementAtBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class ElementAtBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int ElementAtLinq()
10 | {
11 | return Data.ElementAt(5);
12 | }
13 |
14 | [Benchmark]
15 | public int ElementAtFaster()
16 | {
17 | return Data.ElementAtF(5);
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/EmptyBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class EmptyBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] EmptyLinq()
10 | {
11 | return Enumerable.Empty().ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] EmptyFaster()
16 | {
17 | return EnumerableF.EmptyF().ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/ExceptBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class ExceptBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] ExceptLinq()
10 | {
11 | return Data.Except(DataSecondary).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] ExceptFaster()
16 | {
17 | return Data.ExceptF(DataSecondary).ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/FirstBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class FirstBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int FirstLinq()
10 | {
11 | return Data.First();
12 | }
13 |
14 | [Benchmark]
15 | public int FirstFaster()
16 | {
17 | return Data.FirstF();
18 | }
19 | }
20 |
21 | public class FirstPredicateBenchmark : Benchmarkable
22 | {
23 | [Benchmark(Baseline = true)]
24 | public int FirstPredicateLinq()
25 | {
26 | return Data.First(v => v == Data[Data.Length / 2]);
27 | }
28 |
29 | [Benchmark]
30 | public int FirstPredicateFaster()
31 | {
32 | return Data.FirstF(v => v == Data[Data.Length / 2]);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/IntersectBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class IntersectBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] IntersectLinq()
10 | {
11 | return Data.Intersect(DataSecondary).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] IntersectFaster()
16 | {
17 | return Data.IntersectF(DataSecondary).ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/LastBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class LastBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int LastLinq()
10 | {
11 | return Data.Last();
12 | }
13 |
14 | [Benchmark]
15 | public int LastFaster()
16 | {
17 | return Data.LastF();
18 | }
19 | }
20 |
21 | public class LastPredicateBenchmark : Benchmarkable
22 | {
23 | [Benchmark(Baseline = true)]
24 | public int LastPredicateLinq()
25 | {
26 | return Data.Last(v => v == Data[Data.Length / 2]);
27 | }
28 |
29 | [Benchmark]
30 | public int LastPredicateFaster()
31 | {
32 | return Data.LastF(v => v == Data[Data.Length / 2]);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/MaxBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class MaxBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int MaxLinq()
10 | {
11 | return Data.Max();
12 | }
13 |
14 | [Benchmark]
15 | public int MaxFaster()
16 | {
17 | return Data.MaxF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/MinBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class MinBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int MinLinq()
10 | {
11 | return Data.Min();
12 | }
13 |
14 | [Benchmark]
15 | public int MinFaster()
16 | {
17 | return Data.MinF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/OrderByBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class OrderByBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] OrderByLinq()
10 | {
11 | return Data.OrderBy(v => v).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] OrderByFaster()
16 | {
17 | return Data.OrderByF(v => v).ToArrayF();
18 | }
19 |
20 | [Benchmark]
21 | public int[] SortFaster()
22 | {
23 | return Data.SortF().ToArrayF();
24 | }
25 | }
26 |
27 | public class OrderByDescendingBenchmark : Benchmarkable
28 | {
29 | [Benchmark(Baseline = true)]
30 | public int[] OrderByDescendingLinq()
31 | {
32 | return Data.OrderByDescending(v => v).ToArray();
33 | }
34 |
35 | [Benchmark]
36 | public int[] OrderByDescendingFaster()
37 | {
38 | return Data.OrderByDescendingF(v => v).ToArrayF();
39 | }
40 |
41 | [Benchmark]
42 | public int[] SortDescendingFaster()
43 | {
44 | return Data.SortDescendingF().ToArrayF();
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/PrependBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class PrependBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] PrependLinq()
10 | {
11 | return Data.Prepend(5).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] PrependFaster()
16 | {
17 | return Data.PrependF(5).ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/RangeBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class RangeBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] RangeLinq()
10 | {
11 | return Enumerable.Range(0, 100).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] RangeFaster()
16 | {
17 | return EnumerableF.RangeF(0, 100).ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/RepeatBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class RepeatBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] RepeatLinq()
10 | {
11 | return Enumerable.Repeat(5, N).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] RepeatFaster()
16 | {
17 | return EnumerableF.RepeatF(5, N).ToArrayF();
18 | }
19 | }
20 |
21 | public class RepeatSequenceBenchmark : Benchmarkable
22 | {
23 | [Benchmark(Baseline = true)]
24 | public int[] RepeatSequenceFaster()
25 | {
26 | return EnumerableF.RepeatSequenceF(new[] {1, 2, 3, 4, 5}, N).ToArrayF();
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/ReverseBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class ReverseBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] ReverseLinq()
10 | {
11 | return Data.Reverse().ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] ReverseFaster()
16 | {
17 | return Data.ReverseF().ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/SelectBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class SelectBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] SelectLinq()
10 | {
11 | return Data.Select(i => -i).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] SelectFaster()
16 | {
17 | return Data.SelectF(i => -i).ToArrayF();
18 | }
19 |
20 | [Benchmark]
21 | public int[] SelectInPlaceFaster()
22 | {
23 | return Data.SelectInPlaceF(i => -i).ToArrayF();
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/SelectManyBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class SelectManyBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] SelectManyLinq()
10 | {
11 | return Data.SelectMany(i => new [] {i, i, i}).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] SelectManyFaster()
16 | {
17 | return Data.SelectManyF(i => new [] {i, i, i}).ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/SequenceEqualBenchmark.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Attributes;
2 | using System.Linq;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class SequenceEqualBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public bool SequenceEqualLinq()
10 | {
11 | return Data.SequenceEqual(DataSecondary);
12 | }
13 |
14 | [Benchmark]
15 | public bool SequenceEqualFaster()
16 | {
17 | return Data.SequenceEqualF(DataSecondary);
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/SingleBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class SingleBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int SingleLinq()
10 | {
11 | Data[Data.Length / 2] = -1;
12 | return Data.Single(i => i == -1);
13 | }
14 |
15 | [Benchmark]
16 | public int SingleFaster()
17 | {
18 | Data[Data.Length / 2] = -1;
19 | return Data.SingleF(i => i == -1);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/SkipBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class SkipBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] SkipLinq()
10 | {
11 | return Data.Skip(5).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] SkipFaster()
16 | {
17 | return Data.SkipF(5).ToArrayF();
18 | }
19 | }
20 |
21 | public class SkipLastBenchmark : Benchmarkable
22 | {
23 | [Benchmark(Baseline = true)]
24 | public int[] SkipLastLinq()
25 | {
26 | return Data.SkipLast(5).ToArray();
27 | }
28 |
29 | [Benchmark]
30 | public int[] SkipLastFaster()
31 | {
32 | return Data.SkipLastF(5).ToArrayF();
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/SumBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class SumBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int SumLinq()
10 | {
11 | return Data.Sum();
12 | }
13 |
14 | [Benchmark]
15 | public int SumFaster1()
16 | {
17 | return Data.SumF1();
18 | }
19 |
20 | [Benchmark]
21 | public int SumFaster4()
22 | {
23 | return Data.SumF4();
24 | }
25 |
26 | [Benchmark]
27 | public int SumFaster16()
28 | {
29 | return Data.SumF16();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/TakeBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class TakeBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] TakeLinq()
10 | {
11 | return Data.Take(5).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] TakeFaster()
16 | {
17 | return Data.TakeF(5).ToArrayF();
18 | }
19 | }
20 |
21 | public class TakeLastBenchmark : Benchmarkable
22 | {
23 | [Benchmark(Baseline = true)]
24 | public int[] TakeLastLinq()
25 | {
26 | return Data.TakeLast(5).ToArray();
27 | }
28 |
29 | [Benchmark]
30 | public int[] TakeLastFaster()
31 | {
32 | return Data.TakeLastF(5).ToArrayF();
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/ToCastBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using BenchmarkDotNet.Attributes;
4 |
5 | namespace LinqFasterer.Benchmarks.Benchmarks
6 | {
7 | public class ToArrayBenchmark : Benchmarkable
8 | {
9 | [Benchmark(Baseline = true)]
10 | public int[] ToArrayLinq()
11 | {
12 | return Data.ToArray();
13 | }
14 |
15 | [Benchmark]
16 | public int[] ToArrayFaster()
17 | {
18 | return Data.ToArrayF();
19 | }
20 | }
21 |
22 | public class ToArrayFromListBenchmark : Benchmarkable
23 | {
24 | [Benchmark(Baseline = true)]
25 | public int[] ToArrayFromListLinq()
26 | {
27 | // ReSharper disable once RemoveToList.1
28 | return Data.ToList().ToArray();
29 | }
30 |
31 | [Benchmark]
32 | public int[] ToArrayFromListFaster()
33 | {
34 | return Data.ToList().ToArrayF();
35 | }
36 | }
37 |
38 | public class ToListBenchmark : Benchmarkable
39 | {
40 | [Benchmark(Baseline = true)]
41 | public List ToListLinq()
42 | {
43 | return Data.ToList();
44 | }
45 |
46 | [Benchmark]
47 | public List ToListFaster()
48 | {
49 | return Data.ToListF();
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/UnionBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class UnionBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] UnionLinq()
10 | {
11 | return Data.Union(DataSecondary).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] UnionFaster()
16 | {
17 | return Data.UnionF(DataSecondary).ToArrayF();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/WhereBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class WhereBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public int[] WhereLinq()
10 | {
11 | return Data.Where(v => v > 10).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public int[] WhereFaster()
16 | {
17 | return Data.WhereF(v => v > 10).ToArrayF();
18 | }
19 | }
20 |
21 | public class WhereIndexedBenchmark : Benchmarkable
22 | {
23 | [Benchmark(Baseline = true)]
24 | public int[] WhereIndexedLinq()
25 | {
26 | return Data.Where((v, _) => v > 10).ToArray();
27 | }
28 |
29 | [Benchmark]
30 | public int[] WhereIndexedFaster()
31 | {
32 | return Data.WhereF((v, _) => v > 10).ToArrayF();
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/Benchmarks/ZipBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using BenchmarkDotNet.Attributes;
3 |
4 | namespace LinqFasterer.Benchmarks.Benchmarks
5 | {
6 | public class ZipBenchmark : Benchmarkable
7 | {
8 | [Benchmark(Baseline = true)]
9 | public (int, int)[] ZipLinq()
10 | {
11 | return Data.Zip(DataSecondary).ToArray();
12 | }
13 |
14 | [Benchmark]
15 | public (int, int)[] ZipFaster()
16 | {
17 | return Data.ZipF(DataSecondary).ToArrayF();
18 | }
19 | }
20 |
21 | public class ZipSelectorBenchmark : Benchmarkable
22 | {
23 | [Benchmark(Baseline = true)]
24 | public int[] ZipSelectorLinq()
25 | {
26 | return Data.ToList().Zip(DataSecondary, (l, r) => l + r).ToArray();
27 | }
28 |
29 | [Benchmark]
30 | public int[] ZipSelectorFaster()
31 | {
32 | return Data.ToList().ZipF(DataSecondary, (l, r) => l + r).ToArrayF();
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/LinqFasterer.Benchmark/LinqFasterer.Benchmarks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net5.0
6 | false
7 |
8 |
9 |
10 | x64
11 |
12 |
13 |
14 | x64
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/LinqFasterer.Shared/LinqFasterer.Shared.projitems:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 | true
6 | B7074944-6E6D-4AB0-8BBA-562132B5B9A3
7 |
8 |
9 | LinqFasterer.Shared
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/LinqFasterer.Shared/LinqFasterer.Shared.shproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {8CF29127-1239-4553-A8A1-BDCF290CA64F}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/LinqFasterer.Tests/AggregateTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using LinqFasterer.Shared;
5 | using Xunit;
6 |
7 | namespace LinqFasterer.Tests
8 | {
9 | public partial class Test
10 | {
11 | [Theory]
12 | [Trait(nameof(EnumerableF.AggregateF), null)]
13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))]
14 | public void AggregateTest_Int(IList source)
15 | {
16 | var expected = source.Aggregate((l, r) => l + r);
17 | var actual = source.AggregateF((l, r) => l + r);
18 |
19 | Assert.Equal(expected, actual);
20 | }
21 |
22 | [Theory]
23 | [Trait(nameof(EnumerableF.AggregateF), null)]
24 | [MemberData(nameof(Utilities.TestArray), typeof(int), 0, 0, 0, MemberType = typeof(Utilities))]
25 | public void AggregateTest_IntFail(IList source)
26 | {
27 | Assert.Throws(() => source.AggregateF((l, r) => l + r));
28 | }
29 |
30 | [Theory]
31 | [Trait(nameof(EnumerableF.AggregateF), null)]
32 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))]
33 | public void AggregateTest_IntSeed(IList source)
34 | {
35 | var expected = source.Aggregate("S33D", (l, r) => string.Concat(l, r));
36 | var actual = source.AggregateF("S33D", (l, r) => string.Concat(l, r));
37 |
38 | Assert.Equal(expected, actual);
39 | }
40 |
41 | [Theory]
42 | [Trait(nameof(EnumerableF.AggregateF), null)]
43 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))]
44 | public void AggregateTest_IntSeedSelector(IList source)
45 | {
46 | var expected = source.Aggregate("S33D", (l, r) => string.Concat(l, r), result => result + result);
47 | var actual = source.AggregateF("S33D", (l, r) => string.Concat(l, r), result => result + result);
48 |
49 | Assert.Equal(expected, actual);
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/LinqFasterer.Tests/AllNullTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using LinqFasterer.Shared;
3 | using Xunit;
4 |
5 | namespace LinqFasterer.Tests
6 | {
7 | public partial class Test
8 | {
9 | [Theory]
10 | [Trait(nameof(EnumerableF.AllNullF), null)]
11 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))]
12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))]
13 | public void AllNullTest_IntFalse(IList source)
14 | {
15 | Assert.False(source.AllNullF());
16 | }
17 |
18 | [Theory]
19 | [Trait(nameof(EnumerableF.AllNullF), null)]
20 | [InlineData(new object[] {new object[] {null,null,null,null,5}})]
21 | public void AllNullTest_ObjectFalse(IList