├── .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 source) 22 | { 23 | Assert.False(source.AllNullF()); 24 | } 25 | 26 | [Theory] 27 | [Trait(nameof(EnumerableF.AllNullF), null)] 28 | [InlineData(new object[] {new object[] {null,null,null,null,null}})] 29 | public void AllNullTest_ObjectTrue(IList source) 30 | { 31 | Assert.True(source.AllNullF()); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/AllTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.AllF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 0, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 1, MemberType = typeof(Utilities))] 15 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, -1, 0, MemberType = typeof(Utilities))] 16 | public void AllTest_Int(IList source) 17 | { 18 | var expected = source.All(v => v == -1); 19 | var actual = source.AllF(v => v == -1); 20 | 21 | Assert.Equal(expected, actual); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/AnyTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.AnyF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 0, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 14 | public void AnyTest_Int(IList source) 15 | { 16 | var expected = source.Any(); 17 | var actual = source.AnyF(); 18 | 19 | Assert.Equal(expected, actual); 20 | } 21 | 22 | [Theory] 23 | [Trait(nameof(EnumerableF.AnyF), null)] 24 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 25 | public void AnyTest_IntPredicate(IList source) 26 | { 27 | var expected = source.Any(v => v == -1); 28 | var actual = source.AnyF(v => v == -1); 29 | 30 | Assert.Equal(expected, actual); 31 | } 32 | 33 | [Theory] 34 | [Trait(nameof(EnumerableF.AnyF), null)] 35 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 36 | public void AnyTest_IntPredicateMatch(IList source) 37 | { 38 | var expected = source.Any(v => v == source[0]); 39 | var actual = source.AnyF(v => v == source[0]); 40 | 41 | Assert.Equal(expected, actual); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/AppendTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.AppendF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | public void AppendTest_Int(IList source) 14 | { 15 | var (first, second) = Utilities.SplitArray(source, source.Count - 1); 16 | 17 | var expected = first.Append(second[0]).ToArray(); 18 | var actual = first.AppendF(second[0]).ToArrayF(); 19 | 20 | Assert.Equal(expected, actual); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LinqFasterer.Tests/BinarySearchTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Xunit; 3 | 4 | namespace LinqFasterer.Tests 5 | { 6 | public partial class Test 7 | { 8 | [Theory] 9 | [Trait(nameof(EnumerableF.BinarySearchF), null)] 10 | [InlineData(1, new [] {5,6,7,8,9}, 6)] 11 | [InlineData(2, new [] {5,6,7,8,9}, 7)] 12 | [InlineData(~0, new [] {5,6,7,8,9}, 0)] 13 | [InlineData(~0, new [] {5,6,7,8,9}, 4)] 14 | [InlineData(~5, new [] {5,6,7,8,9}, 10)] 15 | [InlineData(~2, new [] {5,6,8,9}, 7)] 16 | public void BinarySearchTest_Int(int expected, int[] source, int value) 17 | { 18 | var actual = source.BinarySearchF(value); 19 | var actual2 = source.BinarySearchF(value, Comparer.Default); 20 | 21 | Assert.Equal(expected, actual); 22 | Assert.Equal(expected, actual2); 23 | } 24 | 25 | [Theory] 26 | [Trait(nameof(EnumerableF.BinarySearchF), null)] 27 | [InlineData(1, new [] {5,6,7,8,9}, 0, 2, 6)] 28 | [InlineData(1, new [] {5,6,7,8,9}, 1, 1, 6)] 29 | [InlineData(~1, new [] {5,6,7,8,9}, 1, 0, 6)] 30 | [InlineData(~2, new [] {5,6,7,8,9}, 0, 2, 7)] 31 | public void BinarySearchTest_IntIndexed(int expected, int[] source, int index, int length, int value) 32 | { 33 | var actual = source.BinarySearchF(index, length, value); 34 | var actual2 = source.BinarySearchF(index, length, value, Comparer.Default); 35 | 36 | Assert.Equal(expected, actual); 37 | Assert.Equal(expected, actual2); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/ClearTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace LinqFasterer.Tests 4 | { 5 | public partial class Test 6 | { 7 | [Theory] 8 | [Trait(nameof(EnumerableF.ClearF), null)] 9 | [InlineData(new [] {0,0,0,0,0}, new [] {1,1,1,1,1})] 10 | public void ClearTest_Int(int[] expected, int[] source) 11 | { 12 | var actual = source.ClearF(); 13 | 14 | Assert.Equal(expected, actual); 15 | } 16 | 17 | [Theory] 18 | [Trait(nameof(EnumerableF.ClearF), null)] 19 | [InlineData(new [] {1,1,1,1,1}, new [] {1,1,1,1,1}, 1, 0)] 20 | [InlineData(new [] {1,0,0,0,1}, new [] {1,1,1,1,1}, 1, 3)] 21 | [InlineData(new [] {0,1,1,1,1}, new [] {1,1,1,1,1}, 0, 1)] 22 | [InlineData(new [] {0,1,1,1,1}, new [] {1,1,1,1,1}, -1, 2)] 23 | [InlineData(new [] {1,1,1,1,1}, new [] {1,1,1,1,1}, -2, 2)] 24 | [InlineData(new [] {1,1,1,1,0}, new [] {1,1,1,1,1}, 4, 2)] 25 | [InlineData(new [] {1,1,1,1,1}, new [] {1,1,1,1,1}, 5, 2)] 26 | [InlineData(new [] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, new [] {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 0, 40)] 27 | public void ClearTest_IntIndexed(int[] expected, int[] source, int index, int length) 28 | { 29 | var actual = source.ClearF(index, length); 30 | 31 | Assert.Equal(expected, actual); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/CloneTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace LinqFasterer.Tests 4 | { 5 | public partial class Test 6 | { 7 | [Theory] 8 | [Trait(nameof(EnumerableF.CloneF), null)] 9 | [InlineData(new [] {0,1,2,3,0}, new [] {0,1,2,3,0})] 10 | public void CloneTest_Int(int[] expected, int[] source) 11 | { 12 | var actual = source.CloneF(); 13 | 14 | Assert.Equal(expected, actual); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /LinqFasterer.Tests/ContainsNullTests.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.ContainsNullF), 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 ContainsNullTest_IntFalse(IList source) 14 | { 15 | Assert.False(source.ContainsNullF()); 16 | } 17 | 18 | [Theory] 19 | [Trait(nameof(EnumerableF.ContainsNullF), null)] 20 | [InlineData(new object[] {new object[] {1,2,3,4,5}})] 21 | public void ContainsNullTest_ObjectFalse(IList source) 22 | { 23 | Assert.False(source.ContainsNullF()); 24 | } 25 | 26 | [Theory] 27 | [Trait(nameof(EnumerableF.ContainsNullF), null)] 28 | [InlineData(new object[] {new object[] {1,2,3,null,5}})] 29 | public void ContainsNullTest_ObjectTrue(IList source) 30 | { 31 | Assert.True(source.ContainsNullF()); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/ContainsTests.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.ContainsF), 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 ContainsTest_Int(IList source) 14 | { 15 | var (first, second) = Utilities.SplitArray(source, source.Count - 1); 16 | 17 | var expected = first.Contains(second[0]); 18 | var actual = first.ContainsF(second[0]); 19 | 20 | Assert.Equal(expected, actual); 21 | } 22 | 23 | [Theory] 24 | [Trait(nameof(EnumerableF.ContainsF), null)] 25 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 26 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 27 | public void ContainsComparerTest_Int(IList source) 28 | { 29 | var (first, second) = Utilities.SplitArray(source, source.Count - 1); 30 | 31 | var expected = first.Contains(second[0]); 32 | var actual = first.ContainsF(second[0], EqualityComparer.Default); 33 | 34 | Assert.Equal(expected, actual); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/CountTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.CountF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 2, MemberType = typeof(Utilities))] 14 | public void CountTest_Int(IList source) 15 | { 16 | var (first, second) = Utilities.SplitArray(source, source.Count - 1); 17 | 18 | var expected = first.Count(); 19 | var actual = first.CountF(); 20 | 21 | Assert.Equal(expected, actual); 22 | } 23 | 24 | [Theory] 25 | [Trait(nameof(EnumerableF.CountF), null)] 26 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 27 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 2, MemberType = typeof(Utilities))] 28 | public void CountPredicateTest_Int(IList source) 29 | { 30 | var (first, second) = Utilities.SplitArray(source, source.Count - 1); 31 | 32 | var expected = first.Count(v => v == second[0]); 33 | var actual = first.CountF(v => v == second[0]); 34 | 35 | Assert.Equal(expected, actual); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/DefaultIfEmptyTests.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.DefaultIfEmptyF), null)] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 14 | public void DefaultIfEmptyTest_Int(IList source) 15 | { 16 | var expected = source.DefaultIfEmpty().ToArray(); 17 | var actual = source.DefaultIfEmptyF().ToArrayF(); 18 | 19 | Assert.Equal(expected, actual); 20 | } 21 | 22 | [Fact] 23 | [Trait(nameof(EnumerableF.DefaultIfEmptyF), null)] 24 | public void DefaultIfEmptyTest_IntEmpty() 25 | { 26 | var source = Array.Empty(); 27 | 28 | var expected = source.DefaultIfEmpty().ToArray(); 29 | var actual = source.DefaultIfEmptyF().ToArrayF(); 30 | 31 | Assert.Equal(expected, actual); 32 | } 33 | 34 | [Fact] 35 | [Trait(nameof(EnumerableF.DefaultIfEmptyF), null)] 36 | public void DefaultIfEmptyTest_IntEmptyDefault() 37 | { 38 | var source = Array.Empty(); 39 | 40 | var expected = source.DefaultIfEmpty(int.MaxValue).ToArray(); 41 | var actual = source.DefaultIfEmptyF(int.MaxValue).ToArrayF(); 42 | 43 | Assert.Equal(expected, actual); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/DistinctTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.DistinctF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 15 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5000, 0, 100, MemberType = typeof(Utilities))] 16 | public void DistinctTest_Int(IList source) 17 | { 18 | var expected = source.Distinct().ToArray(); 19 | var actual = source.DistinctF().ToArrayF(); 20 | 21 | Assert.Equal(expected, actual); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/ElementAtTests.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.ElementAtF), null)] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 14 | public void ElementAtTest_Int(IList source) 15 | { 16 | var expected = source.ElementAt(source.Count / 2); 17 | var actual = source.ElementAtF(source.Count / 2); 18 | 19 | Assert.Equal(expected, actual); 20 | } 21 | 22 | [Theory] 23 | [Trait(nameof(EnumerableF.ElementAtF), null)] 24 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 25 | public void ElementAtTest_Except(IList source) 26 | { 27 | Assert.Throws(() => source.ElementAtF(-1)); 28 | Assert.Throws(() => source.ElementAtF(source.Count)); 29 | } 30 | 31 | [Theory] 32 | [Trait(nameof(EnumerableF.ElementAtOrDefaultF), null)] 33 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 34 | public void ElementAtOrDefaultTest_Int(IList source) 35 | { 36 | var expected = source.ElementAtOrDefault(source.Count / 2); 37 | var actual = source.ElementAtOrDefaultF(source.Count / 2); 38 | 39 | Assert.Equal(expected, actual); 40 | } 41 | 42 | [Theory] 43 | [Trait(nameof(EnumerableF.ElementAtOrDefaultF), null)] 44 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 45 | public void ElementAtOrDefaultTest_Default(IList source) 46 | { 47 | Assert.Equal(0, source.ElementAtOrDefaultF(-1)); 48 | Assert.Equal(0, source.ElementAtOrDefaultF(source.Count)); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/EmptyTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Xunit; 3 | 4 | namespace LinqFasterer.Tests 5 | { 6 | public partial class Test 7 | { 8 | [Fact] 9 | [Trait(nameof(EnumerableF.EmptyF), null)] 10 | public void EmptyTest_Int() 11 | { 12 | var expected = Enumerable.Empty().ToArray(); 13 | var actual = EnumerableF.EmptyF().ToArrayF(); 14 | 15 | Assert.Equal(expected, actual); 16 | } 17 | 18 | [Fact] 19 | [Trait(nameof(EnumerableF.EmptyF), null)] 20 | public void EmptyTest_IntExtension() 21 | { 22 | var expected = Enumerable.Empty().ToArray(); 23 | var actual = new int[4].EmptyF().ToArrayF(); 24 | 25 | Assert.Equal(expected, actual); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/ExceptTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.ExceptF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 15 | public void ExceptTest_Int(IList source) 16 | { 17 | var (first, second) = Utilities.SplitArray(source, source.Count / 2); 18 | 19 | var expected = first.Except(second).ToArray(); 20 | var actual = first.ExceptF(second).ToArrayF(); 21 | 22 | Assert.Equal(expected, actual); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/FillTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace LinqFasterer.Tests 4 | { 5 | public partial class Test 6 | { 7 | [Theory] 8 | [Trait(nameof(EnumerableF.FillF), null)] 9 | [InlineData(new [] {0,0,0,0,0}, new [] {1,1,1,1,1}, 0)] 10 | public void FillTest_Int(int[] expected, int[] source, int value) 11 | { 12 | var actual = source.FillF(value); 13 | 14 | Assert.Equal(expected, actual); 15 | } 16 | 17 | [Theory] 18 | [Trait(nameof(EnumerableF.FillF), null)] 19 | [InlineData(new [] {1,1,1,1,1}, new [] {1,1,1,1,1}, 0, 1, 0)] 20 | [InlineData(new [] {1,0,0,0,1}, new [] {1,1,1,1,1}, 0, 1, 3)] 21 | [InlineData(new [] {0,1,1,1,1}, new [] {1,1,1,1,1}, 0, 0, 1)] 22 | [InlineData(new [] {0,1,1,1,1}, new [] {1,1,1,1,1}, 0, -1, 2)] 23 | [InlineData(new [] {1,1,1,1,1}, new [] {1,1,1,1,1}, 0, -2, 2)] 24 | [InlineData(new [] {1,1,1,1,0}, new [] {1,1,1,1,1}, 0, 4, 2)] 25 | [InlineData(new [] {1,1,1,1,1}, new [] {1,1,1,1,1}, 0, 5, 2)] 26 | [InlineData(new [] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, new [] {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 0, 0, 40)] 27 | public void FillTest_IntIndexed(int[] expected, int[] source, int value, int index, int length) 28 | { 29 | var actual = source.FillF(value, index, length); 30 | 31 | Assert.Equal(expected, actual); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/FirstTests.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.FirstF), null)] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 14 | public void FirstTest_Int(IList source) 15 | { 16 | var expected = source.First(); 17 | var actual = source.FirstF(); 18 | 19 | Assert.Equal(expected, actual); 20 | } 21 | 22 | [Theory] 23 | [Trait(nameof(EnumerableF.FirstF), null)] 24 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 10, MemberType = typeof(Utilities))] 25 | public void FirstTest_IntPredicate(IList source) 26 | { 27 | var expected = source.First(v => v == source[0]); 28 | var actual = source.FirstF(v => v == source[0]); 29 | 30 | Assert.Equal(expected, actual); 31 | } 32 | 33 | [Theory] 34 | [Trait(nameof(EnumerableF.FirstF), null)] 35 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 10, MemberType = typeof(Utilities))] 36 | public void FirstTest_IntPredicateFail(IList source) 37 | { 38 | Assert.Throws(() => source.FirstF(v => v == -1)); 39 | } 40 | 41 | [Theory] 42 | [Trait(nameof(EnumerableF.FirstOrDefaultF), null)] 43 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 44 | public void FirstOrDefaultTest_Int(IList source) 45 | { 46 | var expected = source.FirstOrDefault(); 47 | var actual = source.FirstOrDefaultF(); 48 | 49 | Assert.Equal(expected, actual); 50 | } 51 | 52 | [Theory] 53 | [Trait(nameof(EnumerableF.FirstOrDefaultF), null)] 54 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 10, MemberType = typeof(Utilities))] 55 | public void FirstOrDefaultTest_IntPredicate(IList source) 56 | { 57 | var expected = source.FirstOrDefault(v => v == source[0]); 58 | var actual = source.FirstOrDefaultF(v => v == source[0]); 59 | 60 | Assert.Equal(expected, actual); 61 | } 62 | 63 | [Theory] 64 | [Trait(nameof(EnumerableF.FirstOrDefaultF), null)] 65 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 10, MemberType = typeof(Utilities))] 66 | public void FirstOrDefaultTest_IntPredicateDefault(IList source) 67 | { 68 | var expected = source.FirstOrDefault(v => v == -1); 69 | var actual = source.FirstOrDefaultF(v => v == -1); 70 | 71 | Assert.Equal(expected, actual); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/ForEachTests.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.ForEachF), null)] 11 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 12 | public void ForEachTest_Int(IList source) 13 | { 14 | var expected = source.ToArrayF(); 15 | var actual = new List(); 16 | 17 | source.ForEachF(i => actual.Add(i)); 18 | 19 | Assert.Equal(expected, actual.ToArray()); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/IntersectTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.IntersectF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 15 | public void IntersectTest_Int(IList source) 16 | { 17 | var (first, second) = Utilities.SplitArray(source, source.Count / 2); 18 | 19 | var expected = first.Intersect(second).ToArray(); 20 | var actual = first.IntersectF(second).ToArrayF(); 21 | 22 | Assert.Equal(expected, actual); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/IsOrderedByTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | {[Theory] 10 | [Trait(nameof(EnumerableF.IsOrderedByF), 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 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 14 | public void IsOrderedByTest_Int(IList source) 15 | { 16 | Assert.True(source.OrderBy(v => v).ToArray().IsOrderedByF(v => v)); 17 | Assert.True(source.OrderBy(v => v).ToArray().IsOrderedByF(v => v, Comparer.Default)); 18 | Assert.False(source.OrderBy(v => v).ToArray().IsOrderedByF(v => -v)); 19 | Assert.False(source.OrderBy(v => v).ToArray().IsOrderedByF(v => -v, Comparer.Default)); 20 | } 21 | 22 | [Theory] 23 | [Trait(nameof(EnumerableF.IsOrderedByF), null)] 24 | [MemberData(nameof(Utilities.TestArray), typeof(int), 0, 0, 100, MemberType = typeof(Utilities))] 25 | [MemberData(nameof(Utilities.TestArray), typeof(int), 1, 0, 100, MemberType = typeof(Utilities))] 26 | public void IsOrderedByTest_IntSmall(IList source) 27 | { 28 | Assert.True(source.OrderBy(v => v).ToArray().IsOrderedByF(v => v)); 29 | Assert.True(source.OrderBy(v => v).ToArray().IsOrderedByF(v => v, Comparer.Default)); 30 | } 31 | 32 | [Theory] 33 | [Trait(nameof(EnumerableF.IsOrderedByDescendingF), null)] 34 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 35 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 36 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 37 | public void IsOrderedByDescendingTest_Int(IList source) 38 | { 39 | Assert.True(source.OrderByDescending(v => v).ToArray().IsOrderedByDescendingF(v => v)); 40 | Assert.True(source.OrderByDescending(v => v).ToArray().IsOrderedByDescendingF(v => v, Comparer.Default)); 41 | Assert.False(source.OrderByDescending(v => v).ToArray().IsOrderedByDescendingF(v => -v)); 42 | Assert.False(source.OrderByDescending(v => v).ToArray().IsOrderedByDescendingF(v => -v, Comparer.Default)); 43 | } 44 | 45 | [Theory] 46 | [Trait(nameof(EnumerableF.IsOrderedByDescendingF), null)] 47 | [MemberData(nameof(Utilities.TestArray), typeof(int), 0, 0, 100, MemberType = typeof(Utilities))] 48 | [MemberData(nameof(Utilities.TestArray), typeof(int), 1, 0, 100, MemberType = typeof(Utilities))] 49 | public void IsOrderedByDescendingTest_IntSmall(IList source) 50 | { 51 | Assert.True(source.OrderByDescending(v => v).ToArray().IsOrderedByDescendingF(v => v)); 52 | Assert.True(source.OrderByDescending(v => v).ToArray().IsOrderedByDescendingF(v => v, Comparer.Default)); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/IsSortedTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.IsSortedF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 15 | public void IsSortedTest_Int(IList source) 16 | { 17 | Assert.True(source.OrderBy(v => v).ToArray().IsSortedF()); 18 | Assert.True(source.OrderBy(v => v).ToArray().IsSortedF(Comparer.Default)); 19 | Assert.False(source.OrderBy(v => v).ToArray().IsSortedDescendingF()); 20 | Assert.False(source.OrderBy(v => v).ToArray().IsSortedDescendingF(Comparer.Default)); 21 | } 22 | 23 | [Theory] 24 | [Trait(nameof(EnumerableF.IsSortedF), null)] 25 | [MemberData(nameof(Utilities.TestArray), typeof(int), 0, 0, 100, MemberType = typeof(Utilities))] 26 | [MemberData(nameof(Utilities.TestArray), typeof(int), 1, 0, 100, MemberType = typeof(Utilities))] 27 | public void IsSortedTest_IntSmall(IList source) 28 | { 29 | Assert.True(source.OrderBy(v => v).ToArray().IsSortedF()); 30 | Assert.True(source.OrderBy(v => v).ToArray().IsSortedF(Comparer.Default)); 31 | } 32 | 33 | [Theory] 34 | [Trait(nameof(EnumerableF.IsSortedDescendingF), null)] 35 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 36 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 37 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 38 | public void IsSortedDescendingTest_Int(IList source) 39 | { 40 | Assert.True(source.OrderByDescending(v => v).ToArray().IsSortedDescendingF()); 41 | Assert.True(source.OrderByDescending(v => v).ToArray().IsSortedDescendingF(Comparer.Default)); 42 | Assert.False(source.OrderByDescending(v => v).ToArray().IsSortedF()); 43 | Assert.False(source.OrderByDescending(v => v).ToArray().IsSortedF(Comparer.Default)); 44 | } 45 | 46 | [Theory] 47 | [Trait(nameof(EnumerableF.IsSortedDescendingF), null)] 48 | [MemberData(nameof(Utilities.TestArray), typeof(int), 0, 0, 100, MemberType = typeof(Utilities))] 49 | [MemberData(nameof(Utilities.TestArray), typeof(int), 1, 0, 100, MemberType = typeof(Utilities))] 50 | public void IsSortedDescendingTest_IntSmall(IList source) 51 | { 52 | Assert.True(source.OrderByDescending(v => v).ToArray().IsSortedDescendingF()); 53 | Assert.True(source.OrderByDescending(v => v).ToArray().IsSortedDescendingF(Comparer.Default)); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/LastTests.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.LastF), null)] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 14 | public void LastTest_Int(IList source) 15 | { 16 | var expected = source.Last(); 17 | var actual = source.LastF(); 18 | 19 | Assert.Equal(expected, actual); 20 | } 21 | 22 | [Theory] 23 | [Trait(nameof(EnumerableF.LastF), null)] 24 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 10, MemberType = typeof(Utilities))] 25 | public void LastTest_IntPredicate(IList source) 26 | { 27 | var expected = source.Last(v => v == source[0]); 28 | var actual = source.LastF(v => v == source[0]); 29 | 30 | Assert.Equal(expected, actual); 31 | } 32 | 33 | [Theory] 34 | [Trait(nameof(EnumerableF.LastF), null)] 35 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 10, MemberType = typeof(Utilities))] 36 | public void LastTest_IntPredicateFail(IList source) 37 | { 38 | Assert.Throws(() => source.LastF(v => v == -1)); 39 | } 40 | 41 | [Theory] 42 | [Trait(nameof(EnumerableF.LastOrDefaultF), null)] 43 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 44 | public void LastOrDefaultTest_Int(IList source) 45 | { 46 | var expected = source.LastOrDefault(); 47 | var actual = source.LastOrDefaultF(); 48 | 49 | Assert.Equal(expected, actual); 50 | } 51 | 52 | [Theory] 53 | [Trait(nameof(EnumerableF.LastOrDefaultF), null)] 54 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 10, MemberType = typeof(Utilities))] 55 | public void LastOrDefaultTest_IntPredicate(IList source) 56 | { 57 | var expected = source.LastOrDefault(v => v == source[0]); 58 | var actual = source.LastOrDefaultF(v => v == source[0]); 59 | 60 | Assert.Equal(expected, actual); 61 | } 62 | 63 | [Theory] 64 | [Trait(nameof(EnumerableF.LastOrDefaultF), null)] 65 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 10, MemberType = typeof(Utilities))] 66 | public void LastOrDefaultTest_IntPredicateDefault(IList source) 67 | { 68 | var expected = source.LastOrDefault(v => v == -1); 69 | var actual = source.LastOrDefaultF(v => v == -1); 70 | 71 | Assert.Equal(expected, actual); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/LinqFasterer.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | 6 | false 7 | 8 | LinqFasterer.Tests 9 | 10 | LinqFasterer.Tests 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | 20 | 21 | 22 | 23 | all 24 | runtime; build; native; contentfiles; analyzers; buildtransitive 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /LinqFasterer.Tests/OrderByTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.OrderByF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 15 | public void OrderByTest_Int(IList source) 16 | { 17 | var expected = source.OrderBy(v => v).ToArray(); 18 | var actual = source.OrderByF(v => v).ToArrayF(); 19 | 20 | Assert.Equal(expected, actual); 21 | } 22 | 23 | [Theory] 24 | [Trait(nameof(EnumerableF.OrderByDescendingF), null)] 25 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 26 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 27 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 28 | public void OrderByDescendingTest_Int(IList source) 29 | { 30 | var expected = source.OrderByDescending(v => v).ToArray(); 31 | var actual = source.OrderByDescendingF(v => v).ToArrayF(); 32 | 33 | Assert.Equal(expected, actual); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/PrependTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.PrependF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | public void PrependTest_Int(IList source) 14 | { 15 | var (first, second) = Utilities.SplitArray(source, source.Count - 1); 16 | 17 | var expected = first.Prepend(second[0]).ToArray(); 18 | var actual = first.PrependF(second[0]).ToArrayF(); 19 | 20 | Assert.Equal(expected, actual); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LinqFasterer.Tests/RangeTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Xunit; 3 | 4 | namespace LinqFasterer.Tests 5 | { 6 | public partial class Test 7 | { 8 | [Fact] 9 | [Trait(nameof(EnumerableF.RangeF), null)] 10 | public void RangeTest_Int() 11 | { 12 | var expected = Enumerable.Range(5, 100).ToArray(); 13 | var actual = EnumerableF.RangeF(5, 100).ToArrayF(); 14 | 15 | Assert.Equal(expected, actual); 16 | } 17 | 18 | [Theory] 19 | [Trait(nameof(EnumerableF.RangeF), null)] 20 | [InlineData(new[] {1, 0, -1, -2, -3}, 1, 5, -1)] 21 | [InlineData(new[] {1, 1, 1, 1, 1}, 1, 5, 0)] 22 | [InlineData(new[] {1, 3, 5, 7, 9}, 1, 5, 2)] 23 | public void RangeTest_IntChange(int[] expected, int start, int count, int change) 24 | { 25 | Assert.Equal(expected, EnumerableF.RangeF(start, count, change)); 26 | } 27 | 28 | [Theory] 29 | [Trait(nameof(EnumerableF.RangeF), null)] 30 | [InlineData(new long[] {1, 0, -1, -2, -3}, 1, 5, -1)] 31 | [InlineData(new long[] {1, 1, 1, 1, 1}, 1, 5, 0)] 32 | [InlineData(new long[] {1, 3, 5, 7, 9}, 1, 5, 2)] 33 | public void RangeTest_LongChange(long[] expected, long start, int count, long change) 34 | { 35 | Assert.Equal(expected, EnumerableF.RangeF(start, count, change)); 36 | } 37 | 38 | [Theory] 39 | [Trait(nameof(EnumerableF.RangeF), null)] 40 | [InlineData(new float[] {1, 0, -1, -2, -3}, 1, 5, -1)] 41 | [InlineData(new float[] {1, 1, 1, 1, 1}, 1, 5, 0)] 42 | [InlineData(new float[] {1, 2.5f, 4, 5.5f, 7}, 1, 5, 1.5)] 43 | public void RangeTest_FloatChange(float[] expected, float start, int count, float change) 44 | { 45 | Assert.Equal(expected, EnumerableF.RangeF(start, count, change)); 46 | } 47 | 48 | [Theory] 49 | [Trait(nameof(EnumerableF.RangeF), null)] 50 | [InlineData(new double[] {1, 0, -1, -2, -3}, 1, 5, -1)] 51 | [InlineData(new double[] {1, 1, 1, 1, 1}, 1, 5, 0)] 52 | [InlineData(new double[] {1, 2.5, 4, 5.5, 7}, 1, 5, 1.5)] 53 | public void RangeTest_DoubleChange(double[] expected, double start, int count, double change) 54 | { 55 | Assert.Equal(expected, EnumerableF.RangeF(start, count, change)); 56 | } 57 | 58 | [Theory] 59 | [Trait(nameof(EnumerableF.RangeF), null)] 60 | [InlineData(new double[] {1, 0, -1, -2, -3}, 1, 5, -1)] 61 | [InlineData(new double[] {1, 1, 1, 1, 1}, 1, 5, 0)] 62 | [InlineData(new double[] {1, 2.5, 4, 5.5, 7}, 1, 5, 1.5)] 63 | public void RangeTest_DecimalChange(double[] expected, decimal start, int count, decimal change) 64 | { 65 | Assert.Equal(expected, EnumerableF.RangeF(start, count, change).SelectF(v => (double) v)); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/RepeatTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.RepeatF), null)] 12 | [InlineData(new int[0])] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 15 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 16 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5000, 0, 100, MemberType = typeof(Utilities))] 17 | public void RepeatTest_Int(IList source) 18 | { 19 | var expected = Enumerable.Repeat(source.FirstOrDefault(), source.Count).ToArray(); 20 | var actual = EnumerableF.RepeatF(source.FirstOrDefault(), source.Count).ToArrayF(); 21 | 22 | Assert.Equal(expected, actual); 23 | } 24 | 25 | [Theory] 26 | [Trait(nameof(EnumerableF.RepeatSequenceF), null)] 27 | [InlineData(new[] {1, 2, 3, 1, 2, 3}, new [] {1, 2, 3}, 2)] 28 | [InlineData(new[] {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3}, new [] {1, 2, 3}, 4)] 29 | [InlineData(new[] {1, 1, 1, 1, 1}, new [] {1}, 5)] 30 | [InlineData(new int[0], new [] {1}, 0)] 31 | [InlineData(new int[0], new int[0], 5)] 32 | [InlineData(new[] {1}, new [] {1}, 1)] 33 | public void RepeatSequenceTest_Int(int[] expected, int[] source, int count) 34 | { 35 | var actual = EnumerableF.RepeatSequenceF(source, count).ToArrayF(); 36 | var actual2 = source.RepeatF(count).ToArrayF(); 37 | 38 | Assert.Equal(expected, actual); 39 | Assert.Equal(expected, actual2); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/ReverseTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.ReverseF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | public void ReverseTest_Int(IList source) 14 | { 15 | var expected = source.Reverse().ToArray(); 16 | var actual = source.ReverseF().ToArrayF(); 17 | 18 | Assert.Equal(expected, actual); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/SelectManyTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.SelectManyF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | public void SelectManyTest_Int(IList source) 14 | { 15 | var expected = source.SelectMany(v => new [] {v, v, v}).ToArray(); 16 | var actual = source.SelectManyF(v => new[] {v, v, v}).ToArrayF(); 17 | var actualIndexed = source.SelectManyF((v, i) => new[] {v, v, v}).ToArrayF(); 18 | 19 | Assert.Equal(expected, actual); 20 | Assert.Equal(expected, actualIndexed); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/SelectTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.SelectF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 0, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 14 | public void SelectTest_Int(IList source) 15 | { 16 | var expected = source.Select(v => -v).ToArray(); 17 | var actual = source.SelectF(v => -v).ToArrayF(); 18 | var actualIndexed = source.SelectF((v, i) => -v).ToArrayF(); 19 | 20 | Assert.Equal(expected, actual); 21 | Assert.Equal(expected, actualIndexed); 22 | } 23 | 24 | [Theory] 25 | [Trait(nameof(EnumerableF.SelectInPlaceF), null)] 26 | [MemberData(nameof(Utilities.TestArray), typeof(int), 0, 0, 100, MemberType = typeof(Utilities))] 27 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 28 | public void SelectInPlaceTest_Int(IList source) 29 | { 30 | var expected = source.Select(v => -v).ToArray(); 31 | var actual = source.ToArrayF(true).SelectInPlaceF(v => -v).ToArrayF(); 32 | var actualIndexed = source.ToArrayF(true).SelectInPlaceF((v, i) => -v).ToArrayF(); 33 | 34 | Assert.Equal(expected, actual); 35 | Assert.Equal(expected, actualIndexed); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/SelfTests.cs: -------------------------------------------------------------------------------- 1 | using LinqFasterer.Shared; 2 | using Xunit; 3 | 4 | namespace LinqFasterer.Tests 5 | { 6 | public partial class Test 7 | { 8 | [Theory] 9 | [Trait(nameof(Utilities.SplitArray), "Internal")] 10 | [InlineData(new [] {1,2,3,4,5}, -1, new int[0], new [] {1,2,3,4,5})] 11 | [InlineData(new [] {1,2,3,4,5}, 0, new int[0], new [] {1,2,3,4,5})] 12 | [InlineData(new [] {1,2,3,4,5}, 2, new [] {1,2}, new [] {3,4,5})] 13 | [InlineData(new [] {1,2,3,4,5}, 3, new [] {1,2,3}, new [] {4,5})] 14 | [InlineData(new [] {1,2,3,4,5}, 99, new []{ 1,2,3,4,5}, new int[0])] 15 | public void SplitArrayTest(int[] source, int splitSize, int[] firstExpected, int[] secondExpected) 16 | { 17 | var (first, second) = Utilities.SplitArray(source, splitSize); 18 | 19 | Assert.Equal(first, firstExpected); 20 | Assert.Equal(second, secondExpected); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/SkipTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.SkipF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 5, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 100, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, -5, -1, MemberType = typeof(Utilities))] 15 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 50, 100, MemberType = typeof(Utilities))] 16 | public void SkipTest_Int(IList source) 17 | { 18 | foreach (var i in source) 19 | { 20 | var expected = source.Skip(i).ToArray(); 21 | var actual = source.SkipF(i, true).ToArrayF(); 22 | 23 | Assert.Equal(expected, actual); 24 | } 25 | } 26 | 27 | [Theory] 28 | [Trait(nameof(EnumerableF.SkipLastF), null)] 29 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 5, MemberType = typeof(Utilities))] 30 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 100, MemberType = typeof(Utilities))] 31 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, -5, -1, MemberType = typeof(Utilities))] 32 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 50, 100, MemberType = typeof(Utilities))] 33 | public void SkipLastTest_Int(IList source) 34 | { 35 | foreach (var i in source) 36 | { 37 | var expected = source.SkipLast(i).ToArray(); 38 | var actual = source.SkipLastF(i, true).ToArrayF(); 39 | 40 | Assert.Equal(expected, actual); 41 | } 42 | } 43 | 44 | [Theory] 45 | [Trait(nameof(EnumerableF.SkipWhileF), null)] 46 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 5, MemberType = typeof(Utilities))] 47 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 100, MemberType = typeof(Utilities))] 48 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, -5, -1, MemberType = typeof(Utilities))] 49 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 50, 100, MemberType = typeof(Utilities))] 50 | public void SkipWhileTest_Int(IList source) 51 | { 52 | var expected = source.SkipWhile(v => v > 2).ToArray(); 53 | var actual = source.SkipWhileF(v => v > 2, true).ToArrayF(); 54 | var actualIndexed = source.SkipWhileF((v, i) => v > 2, true).ToArrayF(); 55 | 56 | Assert.Equal(expected, actual); 57 | Assert.Equal(expected, actualIndexed); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/SortTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.SortF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 15 | public void SortTest_Int(IList source) 16 | { 17 | var expected = source.OrderBy(v => v).ToArray(); 18 | var actual = source.SortF().ToArrayF(); 19 | 20 | Assert.Equal(expected, actual); 21 | } 22 | 23 | [Theory] 24 | [Trait(nameof(EnumerableF.SortDescendingF), null)] 25 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 26 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 27 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 28 | public void SortDescendingTest_Int(IList source) 29 | { 30 | var expected = source.OrderByDescending(v => v).ToArray(); 31 | var actual = source.SortDescendingF().ToArrayF(); 32 | 33 | Assert.Equal(expected, actual); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/Sum16Tests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.SumF16), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 100, MemberType = typeof(Utilities))] 13 | public void Sum16Test_Int(IList source) 14 | { 15 | var expected = source.Sum(); 16 | var actual = source.SumF16(); 17 | var actualSelector = source.SumF16(v => v); 18 | 19 | Assert.InRange(expected - actual, -1e-3, 1e-3); 20 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 21 | } 22 | 23 | [Theory] 24 | [Trait(nameof(EnumerableF.SumF16), null)] 25 | [MemberData(nameof(Utilities.TestArray), typeof(long), 50, 0, 100, MemberType = typeof(Utilities))] 26 | public void Sum16Test_Long(IList source) 27 | { 28 | var expected = source.Sum(); 29 | var actual = source.SumF16(); 30 | var actualSelector = source.SumF16(v => v); 31 | 32 | Assert.InRange(expected - actual, -1e-3, 1e-3); 33 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 34 | } 35 | 36 | [Theory] 37 | [Trait(nameof(EnumerableF.SumF16), null)] 38 | [MemberData(nameof(Utilities.TestArray), typeof(float), 50, 0, 100, MemberType = typeof(Utilities))] 39 | public void Sum16Test_Float(IList source) 40 | { 41 | var expected = source.Sum(); 42 | var actual = source.SumF16(); 43 | var actualSelector = source.SumF16(v => v); 44 | 45 | Assert.InRange(expected - actual, -1e-3, 1e-3); 46 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 47 | } 48 | 49 | [Theory] 50 | [Trait(nameof(EnumerableF.SumF16), null)] 51 | [MemberData(nameof(Utilities.TestArray), typeof(double), 50, 0, 100, MemberType = typeof(Utilities))] 52 | public void Sum16Test_Double(IList source) 53 | { 54 | var expected = source.Sum(); 55 | var actual = source.SumF16(); 56 | var actualSelector = source.SumF16(v => v); 57 | 58 | Assert.InRange(expected - actual, -1e-3, 1e-3); 59 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 60 | } 61 | 62 | [Theory] 63 | [Trait(nameof(EnumerableF.SumF16), null)] 64 | [MemberData(nameof(Utilities.TestArray), typeof(decimal), 50, 0, 100, MemberType = typeof(Utilities))] 65 | public void Sum16Test_Decimal(IList source) 66 | { 67 | var expected = source.Sum(); 68 | var actual = source.SumF16(); 69 | var actualSelector = source.SumF16(v => v); 70 | 71 | Assert.InRange(expected - actual, -1e-3M, 1e-3M); 72 | Assert.InRange(expected - actualSelector, -1e-3M, 1e-3M); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /LinqFasterer.Tests/Sum1Tests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.SumF1), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | public void Sum1Test_Int(IList source) 14 | { 15 | var expected = source.Sum(); 16 | var actual = source.SumF1(); 17 | var actualSelector = source.SumF1(v => v); 18 | 19 | Assert.InRange(expected - actual, -1e-3, 1e-3); 20 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 21 | } 22 | 23 | [Theory] 24 | [Trait(nameof(EnumerableF.SumF1), null)] 25 | [MemberData(nameof(Utilities.TestArray), typeof(long), 5, 0, 100, MemberType = typeof(Utilities))] 26 | public void Sum1Test_Long(IList source) 27 | { 28 | var expected = source.Sum(); 29 | var actual = source.SumF1(); 30 | var actualSelector = source.SumF1(v => v); 31 | 32 | Assert.InRange(expected - actual, -1e-3, 1e-3); 33 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 34 | } 35 | 36 | [Theory] 37 | [Trait(nameof(EnumerableF.SumF1), null)] 38 | [MemberData(nameof(Utilities.TestArray), typeof(float), 5, 0, 100, MemberType = typeof(Utilities))] 39 | public void Sum1Test_Float(IList source) 40 | { 41 | var expected = source.Sum(); 42 | var actual = source.SumF1(); 43 | var actualSelector = source.SumF1(v => v); 44 | 45 | Assert.InRange(expected - actual, -1e-3, 1e-3); 46 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 47 | } 48 | 49 | [Theory] 50 | [Trait(nameof(EnumerableF.SumF1), null)] 51 | [MemberData(nameof(Utilities.TestArray), typeof(double), 5, 0, 100, MemberType = typeof(Utilities))] 52 | public void Sum1Test_Double(IList source) 53 | { 54 | var expected = source.Sum(); 55 | var actual = source.SumF1(); 56 | var actualSelector = source.SumF1(v => v); 57 | 58 | Assert.InRange(expected - actual, -1e-3, 1e-3); 59 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 60 | } 61 | 62 | [Theory] 63 | [Trait(nameof(EnumerableF.SumF1), null)] 64 | [MemberData(nameof(Utilities.TestArray), typeof(decimal), 5, 0, 100, MemberType = typeof(Utilities))] 65 | public void Sum1Test_Decimal(IList source) 66 | { 67 | var expected = source.Sum(); 68 | var actual = source.SumF1(); 69 | var actualSelector = source.SumF1(v => v); 70 | 71 | Assert.InRange(expected - actual, -1e-3M, 1e-3M); 72 | Assert.InRange(expected - actualSelector, -1e-3M, 1e-3M); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /LinqFasterer.Tests/Sum4Tests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.SumF4), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | public void Sum4Test_Int(IList source) 14 | { 15 | var expected = source.Sum(); 16 | var actual = source.SumF4(); 17 | var actualSelector = source.SumF4(v => v); 18 | 19 | Assert.InRange(expected - actual, -1e-3, 1e-3); 20 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 21 | } 22 | 23 | [Theory] 24 | [Trait(nameof(EnumerableF.SumF4), null)] 25 | [MemberData(nameof(Utilities.TestArray), typeof(long), 5, 0, 100, MemberType = typeof(Utilities))] 26 | public void Sum4Test_Long(IList source) 27 | { 28 | var expected = source.Sum(); 29 | var actual = source.SumF4(); 30 | var actualSelector = source.SumF4(v => v); 31 | 32 | Assert.InRange(expected - actual, -1e-3, 1e-3); 33 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 34 | } 35 | 36 | [Theory] 37 | [Trait(nameof(EnumerableF.SumF4), null)] 38 | [MemberData(nameof(Utilities.TestArray), typeof(float), 5, 0, 100, MemberType = typeof(Utilities))] 39 | public void Sum4Test_Float(IList source) 40 | { 41 | var expected = source.Sum(); 42 | var actual = source.SumF4(); 43 | var actualSelector = source.SumF4(v => v); 44 | 45 | Assert.InRange(expected - actual, -1e-3, 1e-3); 46 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 47 | } 48 | 49 | [Theory] 50 | [Trait(nameof(EnumerableF.SumF4), null)] 51 | [MemberData(nameof(Utilities.TestArray), typeof(double), 5, 0, 100, MemberType = typeof(Utilities))] 52 | public void Sum4Test_Double(IList source) 53 | { 54 | var expected = source.Sum(); 55 | var actual = source.SumF4(); 56 | var actualSelector = source.SumF4(v => v); 57 | 58 | Assert.InRange(expected - actual, -1e-3, 1e-3); 59 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 60 | } 61 | 62 | [Theory] 63 | [Trait(nameof(EnumerableF.SumF4), null)] 64 | [MemberData(nameof(Utilities.TestArray), typeof(decimal), 5, 0, 100, MemberType = typeof(Utilities))] 65 | public void Sum4Test_Decimal(IList source) 66 | { 67 | var expected = source.Sum(); 68 | var actual = source.SumF4(); 69 | var actualSelector = source.SumF4(v => v); 70 | 71 | Assert.InRange(expected - actual, -1e-3M, 1e-3M); 72 | Assert.InRange(expected - actualSelector, -1e-3M, 1e-3M); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /LinqFasterer.Tests/SumTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.SumF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | public void SumTest_Int(IList source) 14 | { 15 | var expected = source.Sum(); 16 | var actual = source.SumF(); 17 | var actualSelector = source.SumF(v => v); 18 | 19 | Assert.InRange(expected - actual, -1e-3, 1e-3); 20 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 21 | } 22 | 23 | [Theory] 24 | [Trait(nameof(EnumerableF.SumF), null)] 25 | [MemberData(nameof(Utilities.TestArray), typeof(long), 5, 0, 100, MemberType = typeof(Utilities))] 26 | public void SumTest_Long(IList source) 27 | { 28 | var expected = source.Sum(); 29 | var actual = source.SumF(); 30 | var actualSelector = source.SumF(v => v); 31 | 32 | Assert.InRange(expected - actual, -1e-3, 1e-3); 33 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 34 | } 35 | 36 | [Theory] 37 | [Trait(nameof(EnumerableF.SumF), null)] 38 | [MemberData(nameof(Utilities.TestArray), typeof(float), 5, 0, 100, MemberType = typeof(Utilities))] 39 | public void SumTest_Float(IList source) 40 | { 41 | var expected = source.Sum(); 42 | var actual = source.SumF(); 43 | var actualSelector = source.SumF(v => v); 44 | 45 | Assert.InRange(expected - actual, -1e-3, 1e-3); 46 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 47 | } 48 | 49 | [Theory] 50 | [Trait(nameof(EnumerableF.SumF), null)] 51 | [MemberData(nameof(Utilities.TestArray), typeof(double), 5, 0, 100, MemberType = typeof(Utilities))] 52 | public void SumTest_Double(IList source) 53 | { 54 | var expected = source.Sum(); 55 | var actual = source.SumF(); 56 | var actualSelector = source.SumF(v => v); 57 | 58 | Assert.InRange(expected - actual, -1e-3, 1e-3); 59 | Assert.InRange(expected - actualSelector, -1e-3, 1e-3); 60 | } 61 | 62 | [Theory] 63 | [Trait(nameof(EnumerableF.SumF), null)] 64 | [MemberData(nameof(Utilities.TestArray), typeof(decimal), 5, 0, 100, MemberType = typeof(Utilities))] 65 | public void SumTest_Decimal(IList source) 66 | { 67 | var expected = source.Sum(); 68 | var actual = source.SumF(); 69 | var actualSelector = source.SumF(v => v); 70 | 71 | Assert.InRange(expected - actual, -1e-3M, 1e-3M); 72 | Assert.InRange(expected - actualSelector, -1e-3M, 1e-3M); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /LinqFasterer.Tests/TakeTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.TakeF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 5, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 100, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, -5, -1, MemberType = typeof(Utilities))] 15 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 50, 100, MemberType = typeof(Utilities))] 16 | public void TakeTest_Int(IList source) 17 | { 18 | foreach (var i in source) 19 | { 20 | var expected = source.Take(i).ToArray(); 21 | var actual = source.TakeF(i, true).ToArrayF(); 22 | 23 | Assert.Equal(expected, actual); 24 | } 25 | } 26 | 27 | [Theory] 28 | [Trait(nameof(EnumerableF.TakeLastF), null)] 29 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 5, MemberType = typeof(Utilities))] 30 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 100, MemberType = typeof(Utilities))] 31 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, -5, -1, MemberType = typeof(Utilities))] 32 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 50, 100, MemberType = typeof(Utilities))] 33 | public void TakeLastTest_Int(IList source) 34 | { 35 | foreach (var i in source) 36 | { 37 | var expected = source.TakeLast(i).ToArray(); 38 | var actual = source.TakeLastF(i, true).ToArrayF(); 39 | 40 | Assert.Equal(expected, actual); 41 | } 42 | } 43 | 44 | [Theory] 45 | [Trait(nameof(EnumerableF.TakeWhileF), null)] 46 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 5, MemberType = typeof(Utilities))] 47 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 0, 100, MemberType = typeof(Utilities))] 48 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, -5, -1, MemberType = typeof(Utilities))] 49 | [MemberData(nameof(Utilities.TestArray), typeof(int), 15, 50, 100, MemberType = typeof(Utilities))] 50 | public void TakeWhileTest_Int(IList source) 51 | { 52 | var expected = source.TakeWhile(v => v > 2).ToArray(); 53 | var actual = source.TakeWhileF(v => v > 2, true).ToArrayF(); 54 | var actualIndexed = source.TakeWhileF((v, i) => v > 2, true).ToArrayF(); 55 | 56 | Assert.Equal(expected, actual); 57 | Assert.Equal(expected, actualIndexed); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/ToCastTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.ToArrayF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | public void ToArrayTest_Int(IList source) 14 | { 15 | var expected = source.ToArray(); 16 | var actual = source.ToArrayF(); 17 | 18 | Assert.Equal(expected, actual); 19 | } 20 | 21 | [Theory] 22 | [Trait(nameof(EnumerableF.ToArrayF), null)] 23 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 24 | public void ToArrayTest_IntForceClone(IList source) 25 | { 26 | var expected = source.ToArray(); 27 | var actual = source.ToArrayF(true); 28 | 29 | Assert.Equal(expected, actual); 30 | } 31 | 32 | [Theory] 33 | [Trait(nameof(EnumerableF.ToListF), null)] 34 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 35 | public void ToListTest_Int(IList source) 36 | { 37 | var expected = source.ToList(); 38 | var actual = source.ToListF(); 39 | 40 | Assert.Equal(expected, actual); 41 | } 42 | 43 | [Theory] 44 | [Trait(nameof(EnumerableF.ToListF), null)] 45 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 46 | public void ToListTest_IntInPlace(IList source) 47 | { 48 | var expected = source.ToList(); 49 | var actual = source.ToList().ToListF(); 50 | 51 | Assert.Equal(expected, actual); 52 | } 53 | 54 | [Theory] 55 | [Trait(nameof(EnumerableF.ToListF), null)] 56 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 57 | public void ToListTest_IntInPlaceForceClone(IList source) 58 | { 59 | var expected = source.ToList(); 60 | var actual = source.ToList().ToListF(true); 61 | 62 | Assert.Equal(expected, actual); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/UnionTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.UnionF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 15 | [MemberData(nameof(Utilities.TestArray), typeof(int), 3000, 0, 100, MemberType = typeof(Utilities))] 16 | public void UnionTest_Int(IList source) 17 | { 18 | var (first, second) = Utilities.SplitArray(source, source.Count / 2); 19 | 20 | var expected = first.Union(second).ToArray(); 21 | var actual = first.UnionF(second).ToArrayF(); 22 | 23 | Assert.Equal(expected, actual); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/WhereTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.WhereF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 15 | public void WhereTest_Int(IList source) 16 | { 17 | var expected = source.Where(v => v % 2 == 0).ToArray(); 18 | var actual = source.WhereF(v => v % 2 == 0, true).ToArrayF(); 19 | var actualIndexed = source.WhereF((v, i) => v % 2 == 0, true).ToArrayF(); 20 | 21 | Assert.Equal(expected, actual); 22 | Assert.Equal(expected, actualIndexed); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /LinqFasterer.Tests/ZipTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqFasterer.Shared; 4 | using Xunit; 5 | 6 | namespace LinqFasterer.Tests 7 | { 8 | public partial class Test 9 | { 10 | [Theory] 11 | [Trait(nameof(EnumerableF.ZipF), null)] 12 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 13 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 14 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 15 | public void ZipTest_Int(IList source) 16 | { 17 | var (first, second) = Utilities.SplitArray(source, source.Count / 2); 18 | 19 | var expected = first.Zip(second).ToArray(); 20 | var actual = first.ZipF(second).ToArrayF(); 21 | 22 | Assert.Equal(expected, actual); 23 | } 24 | 25 | [Theory] 26 | [Trait(nameof(EnumerableF.ZipF), null)] 27 | [MemberData(nameof(Utilities.TestArray), typeof(int), 5, 0, 100, MemberType = typeof(Utilities))] 28 | [MemberData(nameof(Utilities.TestArray), typeof(int), 10, 0, 2, MemberType = typeof(Utilities))] 29 | [MemberData(nameof(Utilities.TestArray), typeof(int), 50, 0, 5, MemberType = typeof(Utilities))] 30 | public void ZipTest_IntSelector(IList source) 31 | { 32 | var (first, second) = Utilities.SplitArray(source, source.Count / 2); 33 | 34 | var expected = first.Zip(second, (l, r) => l * r).ToArray(); 35 | var actual = first.ZipF(second, (l, r) => l * r).ToArrayF(); 36 | 37 | Assert.Equal(expected, actual); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /LinqFasterer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30225.117 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{646310DD-2F62-4E11-BA72-84B233E6BDB1}" 7 | ProjectSection(SolutionItems) = preProject 8 | Benchmarks.md = Benchmarks.md 9 | README.md = README.md 10 | EndProjectSection 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LinqFasterer", "LinqFasterer\LinqFasterer.csproj", "{5B2F0F9F-6DDA-4F06-A999-26E43AE04F86}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LinqFasterer.Tests", "LinqFasterer.Tests\LinqFasterer.Tests.csproj", "{74C04BC1-3686-43C0-BCCF-3EB47179065A}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LinqFasterer.Benchmarks", "LinqFasterer.Benchmark\LinqFasterer.Benchmarks.csproj", "{E5CFAF89-6293-4A7B-97CF-C3588A52EE86}" 17 | EndProject 18 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "LinqFasterer.Shared", "LinqFasterer.Shared\LinqFasterer.Shared.shproj", "{8CF29127-1239-4553-A8A1-BDCF290CA64F}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {5B2F0F9F-6DDA-4F06-A999-26E43AE04F86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {5B2F0F9F-6DDA-4F06-A999-26E43AE04F86}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {5B2F0F9F-6DDA-4F06-A999-26E43AE04F86}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {5B2F0F9F-6DDA-4F06-A999-26E43AE04F86}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {74C04BC1-3686-43C0-BCCF-3EB47179065A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {74C04BC1-3686-43C0-BCCF-3EB47179065A}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {74C04BC1-3686-43C0-BCCF-3EB47179065A}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {74C04BC1-3686-43C0-BCCF-3EB47179065A}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {E5CFAF89-6293-4A7B-97CF-C3588A52EE86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {E5CFAF89-6293-4A7B-97CF-C3588A52EE86}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {E5CFAF89-6293-4A7B-97CF-C3588A52EE86}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {E5CFAF89-6293-4A7B-97CF-C3588A52EE86}.Release|Any CPU.Build.0 = Release|Any CPU 38 | EndGlobalSection 39 | GlobalSection(SolutionProperties) = preSolution 40 | HideSolutionNode = FALSE 41 | EndGlobalSection 42 | GlobalSection(ExtensibilityGlobals) = postSolution 43 | SolutionGuid = {2A9F064E-AB4C-4ACD-9BE0-A7073320E714} 44 | EndGlobalSection 45 | EndGlobal 46 | -------------------------------------------------------------------------------- /LinqFasterer.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /LinqFasterer/All.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Determines whether all elements of a sequence satisfy a condition. 10 | /// 11 | /// An that contains the elements to apply the predicate to. 12 | /// A predicate function to test each element for a condition. 13 | /// The type of the elements of . 14 | /// if every element of passes the test in the specified , or if is empty; otherwise, . 15 | public static bool AllF(this IList source, Predicate predicate) 16 | { 17 | var sourceArray = source.ToArrayF(); 18 | var sourceLength = sourceArray.Length; 19 | 20 | for (var i = 0; i < sourceLength; i++) 21 | if (!predicate(sourceArray[i])) 22 | return false; 23 | 24 | return true; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /LinqFasterer/AllNullF.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public partial class EnumerableF 7 | { 8 | /// 9 | /// Determines whether all elements of a sequence are null. 10 | /// 11 | /// An in which to check whether every element is . 12 | /// The type of the elements of . 13 | /// if every element of is , or if is empty; otherwise, . 14 | public static bool AllNullF(this IList source) 15 | { 16 | if (default(TSource) != null) 17 | return false; 18 | 19 | var sourceArray = source.ToArrayF(); 20 | var sourceLength = sourceArray.Length; 21 | 22 | for (var i = 0; i < sourceLength; i++) 23 | if (sourceArray[i] != null) 24 | return false; 25 | 26 | return true; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /LinqFasterer/Any.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Determines whether any element of a sequence satisfies a condition. 10 | /// 11 | /// An whose elements to apply the predicate to. 12 | /// An optional predicate function to test each element for a condition; when set to , the function check whether is empty or not. 13 | /// The type of the elements of . 14 | /// if any element of passes the test in the specified ; otherwise, . 15 | public static bool AnyF(this IList source, Predicate? predicate = null) 16 | { 17 | if (predicate == null) 18 | return source.Count != 0; 19 | 20 | var sourceArray = source.ToArrayF(); 21 | var sourceLength = sourceArray.Length; 22 | 23 | for (var i = 0; i < sourceLength; i++) 24 | if (predicate(sourceArray[i])) 25 | return true; 26 | 27 | return false; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /LinqFasterer/Append.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LinqFasterer 4 | { 5 | public static partial class EnumerableF 6 | { 7 | /// 8 | /// Appends a value to the end of the sequence. 9 | /// 10 | /// An of values. 11 | /// A value to append. 12 | /// The type of the elements of . 13 | /// An that starts with and ends with . 14 | public static IList AppendF(this IList source, TSource element) 15 | { 16 | var sourceLength = source.Count; 17 | 18 | // TODO: benchmark with Array.Resize() 19 | var result = new TSource[sourceLength + 1]; 20 | 21 | source.CopyTo(result, 0); 22 | result[sourceLength] = element; 23 | 24 | return result; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /LinqFasterer/Clear.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Sets elements in a sequence to the default value of each element type. 10 | /// 11 | /// An whose elements need to be cleared. 12 | /// Force clone of (disable in-place optimization). 13 | /// The type of the elements of . 14 | /// An with elements set to . 15 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 16 | public static IList ClearF(this IList source, bool forceClone = false) 17 | { 18 | return source.ClearF(0, int.MaxValue, forceClone); 19 | } 20 | 21 | /// 22 | /// Sets elements in a sequence to the default value of each element type. 23 | /// 24 | /// An whose elements need to be cleared. 25 | /// The starting index of the range to clear. 26 | /// The length of the range to clear. 27 | /// Force clone of (disable in-place optimization). 28 | /// The type of the elements of . 29 | /// An with elements set to . 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | public static IList ClearF(this IList source, int index, int length, bool forceClone = false) 32 | { 33 | #pragma warning disable 8620 34 | #pragma warning disable 8619 35 | return source.FillF(default!, index, length, forceClone); 36 | #pragma warning restore 8619 37 | #pragma warning restore 8620 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LinqFasterer/Clone.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Creates a copy of the input sequence. 10 | /// 11 | /// An to be cloned. 12 | /// The type of the elements of . 13 | /// An which is a copy of the input sequence. 14 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 15 | public static IList CloneF(this IList source) 16 | { 17 | return source.ToArrayF(true); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /LinqFasterer/Contains.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Determines whether a sequence contains a specified element by using a specified equality comparer. 10 | /// 11 | /// An in which to locate a value. 12 | /// A value to locate. 13 | /// An optional used to compare values; falls back to when set to . 14 | /// The type of the elements of . 15 | /// if contains an element that has the specified ; otherwise, . 16 | public static bool ContainsF(this IList source, TSource value, IEqualityComparer? comparer = null) 17 | { 18 | var sourceArray = source.ToArrayF(); 19 | 20 | if (comparer == null) 21 | return Array.IndexOf(sourceArray, value) > -1; 22 | 23 | var sourceLength = sourceArray.Length; 24 | 25 | for (var i = 0; i < sourceLength; i++) 26 | if (comparer.Equals(sourceArray[i], value)) 27 | return true; 28 | 29 | return false; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LinqFasterer/ContainsNull.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public partial class EnumerableF 7 | { 8 | /// 9 | /// Determines whether a sequence contains a null element. 10 | /// 11 | /// An in which to check for a . 12 | /// The type of the elements of . 13 | /// if contains a element; otherwise, . 14 | public static bool ContainsNullF(this IList source) 15 | { 16 | if (default(TSource) != null) 17 | return false; 18 | 19 | var sourceArray = source.ToArrayF(); 20 | var sourceLength = sourceArray.Length; 21 | 22 | for (var i = 0; i < sourceLength; i++) 23 | if (sourceArray[i] == null) 24 | return true; 25 | 26 | return false; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /LinqFasterer/Count.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Returns a number that represents how many elements in the specified sequence satisfy a condition. 10 | /// 11 | /// An that contains elements to be tested and counted. 12 | /// An optional predicate function to test each element for a condition; when set to , the function returns the current size of . 13 | /// The type of the elements of . 14 | /// A number that represents how many elements in satisfy the condition specified by . 15 | public static int CountF(this IList source, Func? predicate = null) 16 | { 17 | var sourceLength = source.Count; 18 | 19 | if (predicate == null) 20 | return sourceLength; 21 | 22 | var sourceArray = source.ToArrayF(); 23 | var count = 0; 24 | 25 | for (var i = 0; i < sourceLength; i++) 26 | if (predicate(sourceArray[i])) 27 | count++; 28 | 29 | return count; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LinqFasterer/DefaultIfEmpty.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Returns the elements of the specified sequence or the specified value in a singleton collection if the sequence is empty. 10 | /// 11 | /// An to return the specified value for if it is empty. 12 | /// The value to return if is empty. 13 | /// The type of the elements of . 14 | /// An that contains if is empty; otherwise, . 15 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 16 | public static IList DefaultIfEmptyF(this IList source, TSource? defaultValue = default) 17 | { 18 | return source.Count == 0 ? new [] {defaultValue}! : source; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /LinqFasterer/Distinct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Returns distinct elements from a sequence by using a specified equality comparer to compare values. 10 | /// 11 | /// An to remove duplicate elements from. 12 | /// An optional used to compare values; falls back to when set to . 13 | /// Force clone of (disable in-place optimization). 14 | /// The type of the elements of . 15 | /// An that contains distinct elements from . 16 | public static IList DistinctF(this IList source, IEqualityComparer? comparer = null, bool forceClone = false) 17 | { 18 | var sourceArray = source.ToArrayF(); 19 | var sourceLength = sourceArray.Length; 20 | 21 | comparer ??= EqualityComparer.Default; 22 | 23 | TSource[] result; 24 | 25 | // The following code runs faster on smaller workloads 26 | // The magic number is a result of multiple benchmark tests 27 | if (sourceLength < 2500) 28 | { 29 | var resultHashSet = new HashSet(sourceArray, comparer); 30 | var resultSize = resultHashSet.Count; 31 | 32 | result = new TSource[resultSize]; 33 | resultHashSet.CopyTo(result, 0, resultSize); 34 | } 35 | else 36 | { 37 | var resultHashSet = new HashSet(comparer); 38 | var resultSize = 0; 39 | 40 | result = forceClone ? new TSource[sourceLength] : sourceArray; 41 | 42 | for (var i = 0; i < sourceLength; i++) 43 | { 44 | var value = sourceArray[i]; 45 | 46 | if (!resultHashSet.Contains(value)) 47 | { 48 | resultHashSet.Add(value); 49 | result[resultSize++] = value; 50 | } 51 | } 52 | 53 | Array.Resize(ref result, resultSize); 54 | } 55 | 56 | return result; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /LinqFasterer/ElementAt.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Returns the element at a specified index in a sequence. 10 | /// 11 | /// An to return an element from. 12 | /// The zero-based index of the element to retrieve. 13 | /// The type of the elements of . 14 | /// The element at in . 15 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 16 | public static TSource ElementAtF(this IList source, int index) 17 | { 18 | return source[index]; 19 | } 20 | 21 | /// 22 | /// Returns the element at a specified index in a sequence or a default value if the index is out of range. 23 | /// 24 | /// An to return an element from. 25 | /// The zero-based index of the element to retrieve. 26 | /// The type of the elements of . 27 | /// if the index is outside the bounds of ; otherwise, the element at in . 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | public static TSource? ElementAtOrDefaultF(this IList source, int index) 30 | { 31 | if (index < 0 || index >= source.Count) 32 | return default; 33 | 34 | return source[index]; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /LinqFasterer/Empty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace LinqFasterer 6 | { 7 | public static partial class EnumerableF 8 | { 9 | /// 10 | /// Returns an empty sequence that has the specified type argument. 11 | /// 12 | /// An empty sequence. 13 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 14 | public static IList EmptyF() 15 | { 16 | return Array.Empty(); 17 | } 18 | 19 | /// 20 | /// Returns an empty sequence that has the specified type argument. 21 | /// 22 | /// An empty sequence. 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public static IList EmptyF(this IList _) 25 | { 26 | return Array.Empty(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /LinqFasterer/Enumerable.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LinqFasterer 4 | { 5 | /// 6 | /// Provides a set of methods for querying objects that implement . 7 | /// 8 | public static partial class EnumerableF 9 | { } 10 | } -------------------------------------------------------------------------------- /LinqFasterer/Except.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | // TODO: benchmark 9 | 10 | /// 11 | /// Produces the set difference of two sequences by using the specified equality comparer to compare values. 12 | /// 13 | /// An whose elements that are not also in will be returned. 14 | /// An whose elements that also occur in will cause those elements to be removed from the returned sequence. 15 | /// An optional used to compare values; falls back to when set to . 16 | /// Force clone of (disable in-place optimization). 17 | /// The type of the elements of and . 18 | /// An that contains the set difference of the elements of the two input sequences. 19 | public static IList ExceptF(this IList first, IEnumerable second, IEqualityComparer? comparer = null, bool forceClone = false) 20 | { 21 | var firstArray = first.ToArrayF(forceClone); 22 | var firstLength = firstArray.Length; 23 | 24 | comparer ??= EqualityComparer.Default; 25 | 26 | var secondHashSet = new HashSet(second, comparer); 27 | var resultSize = 0; 28 | 29 | for (var i = 0; i < firstLength; i++) 30 | { 31 | var value = firstArray[i]; 32 | 33 | if (!secondHashSet.Contains(value)) 34 | firstArray[resultSize++] = value; 35 | } 36 | 37 | Array.Resize(ref firstArray, resultSize); 38 | 39 | return firstArray; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /LinqFasterer/Fill.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace LinqFasterer 6 | { 7 | public static partial class EnumerableF 8 | { 9 | /// 10 | /// Sets elements in a sequence to the chosen value. 11 | /// 12 | /// An whose elements need to be filled. 13 | /// A value to set elements to. 14 | /// Force clone of (disable in-place optimization). 15 | /// The type of the elements of . 16 | /// An with elements set to the chosen value. 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | public static IList FillF(this IList source, TSource value, bool forceClone = false) 19 | { 20 | return source.FillF(value, 0, int.MaxValue, forceClone); 21 | } 22 | 23 | /// 24 | /// Sets elements in a sequence to the chosen value. 25 | /// 26 | /// An whose elements need to be filled. 27 | /// A value to set elements to. 28 | /// The starting index of the range to fill. 29 | /// The length of the range to fill. 30 | /// Force clone of (disable in-place optimization). 31 | /// The type of the elements of . 32 | /// An with elements set to the chosen value. 33 | public static IList FillF(this IList source, TSource value, int index, int length, bool forceClone = false) 34 | { 35 | var sourceArray = source.ToArrayF(forceClone); 36 | var sourceLength = sourceArray.Length; 37 | 38 | if (index < 0) 39 | { 40 | length += index; 41 | index = 0; 42 | } 43 | 44 | length = Math.Min(length, sourceLength - index); 45 | 46 | if (index >= sourceLength || length < 1) 47 | return sourceArray; 48 | 49 | var filled = Math.Min(length, 16); 50 | 51 | // It's more efficient to fill some initial data by index instead of calling Array.Copy straightaway 52 | // The magic number is a result of multiple benchmark tests 53 | var iMax = index + filled; 54 | for (var i = index; i < iMax; i++) 55 | sourceArray[i] = value; 56 | 57 | // ReSharper disable once InvertIf 58 | if (filled < length) 59 | { 60 | for (; filled * 2 < length; filled *= 2) 61 | Array.Copy(sourceArray, index, sourceArray, index + filled, filled); 62 | 63 | Array.Copy(sourceArray, index, sourceArray, index + filled, length - filled); 64 | } 65 | 66 | return sourceArray; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /LinqFasterer/First.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using LinqFasterer.Utils; 4 | 5 | namespace LinqFasterer 6 | { 7 | public static partial class EnumerableF 8 | { 9 | /// 10 | /// Returns the first element in a sequence that satisfies a specified condition. 11 | /// 12 | /// An to return an element from. 13 | /// An optional predicate function to test each element for a condition; when set to the function returns the first element in . 14 | /// The type of the elements of . 15 | /// The first element in that passes the test specified by . 16 | public static TSource FirstF(this IList source, Func? predicate = null) 17 | { 18 | if (predicate == null) 19 | return source[0]; 20 | 21 | var sourceArray = source.ToArrayF(); 22 | var sourceLength = sourceArray.Length; 23 | 24 | for (var i = 0; i < sourceLength; i++) 25 | { 26 | var value = sourceArray[i]; 27 | 28 | if (predicate(value)) 29 | return value; 30 | } 31 | 32 | throw Error.NoMatch(); 33 | } 34 | 35 | /// 36 | /// Returns the first element of a sequence, or a default value if the sequence contains no elements. 37 | /// 38 | /// An to return an element from. 39 | /// An optional predicate function to test each element for a condition; when set to the function returns the first element in or when is empty. 40 | /// The type of the elements of . 41 | /// if is empty or if no element passes the test specified by ; otherwise, the first element in that passes the test specified by . 42 | public static TSource? FirstOrDefaultF(this IList source, Func? predicate = null) 43 | { 44 | if (predicate == null) 45 | return source.Count == 0 ? default : source[0]; 46 | 47 | var sourceArray = source.ToArrayF(); 48 | var sourceLength = sourceArray.Length; 49 | 50 | for (var i = 0; i < sourceLength; i++) 51 | { 52 | var value = sourceArray[i]; 53 | 54 | if (predicate(value)) 55 | return value; 56 | } 57 | 58 | return default; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /LinqFasterer/ForEach.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Performs the specified action on each element of the specified sequence. 10 | /// 11 | /// An on whose elements the action is to be performed. 12 | /// An to perform on each element of . 13 | /// The type of the elements of . 14 | /// The input sequence. 15 | public static IList ForEachF(this IList source, Action action) 16 | { 17 | var sourceArray = source.ToArrayF(); 18 | var sourceLength = sourceArray.Length; 19 | 20 | for (var i = 0; i < sourceLength; i++) 21 | action(sourceArray[i]); 22 | 23 | return sourceArray; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LinqFasterer/Intersect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Produces the set intersection of two sequences. 10 | /// 11 | /// An whose distinct elements that also appear in will be returned. 12 | /// An whose distinct elements that also appear in will be returned. 13 | /// An optional used to compare values; falls back to when set to . 14 | /// Force clone of (disable in-place optimization). 15 | /// The type of the elements of and . 16 | /// An that contains the elements that form the set intersection of the two input sequences. 17 | public static IList IntersectF(this IList first, IEnumerable second, IEqualityComparer? comparer = null, bool forceClone = false) 18 | { 19 | comparer ??= EqualityComparer.Default; 20 | 21 | var secondHashSet = new HashSet(second, comparer); 22 | var resultHashSet = new HashSet(comparer); 23 | var resultSize = 0; 24 | 25 | var firstArray = first.ToArrayF(forceClone); 26 | var firstLength = firstArray.Length; 27 | 28 | for (var i = 0; i < firstLength; i++) 29 | { 30 | var value = firstArray[i]; 31 | 32 | if (secondHashSet.Contains(value) && !resultHashSet.Contains(value)) 33 | { 34 | firstArray[resultSize++] = value; 35 | resultHashSet.Add(value); 36 | } 37 | } 38 | 39 | Array.Resize(ref firstArray, resultSize); 40 | 41 | return firstArray; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /LinqFasterer/Last.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using LinqFasterer.Utils; 4 | 5 | namespace LinqFasterer 6 | { 7 | public static partial class EnumerableF 8 | { 9 | /// 10 | /// Returns the last element in a sequence that satisfies a specified condition. 11 | /// 12 | /// An to return an element from. 13 | /// An optional predicate function to test each element for a condition; when set to the function returns the last element in . 14 | /// The type of the elements of . 15 | /// The last element in that passes the test specified by . 16 | public static TSource LastF(this IList source, Func? predicate = null) 17 | { 18 | if (predicate == null) 19 | // ReSharper disable once UseIndexFromEndExpression 20 | return source[source.Count - 1]; 21 | 22 | var sourceArray = source.ToArrayF(); 23 | var sourceLength = sourceArray.Length; 24 | 25 | for (var i = sourceLength - 1; i >= 0; i--) 26 | { 27 | var value = sourceArray[i]; 28 | 29 | if (predicate(value)) 30 | return value; 31 | } 32 | 33 | throw Error.NoMatch(); 34 | } 35 | 36 | /// 37 | /// Returns the last element of a sequence, or a default value if the sequence contains no elements. 38 | /// 39 | /// An to return an element from. 40 | /// An optional predicate function to test each element for a condition; when set to the function returns the last element in or when is empty. 41 | /// The type of the elements of . 42 | /// if is empty or if no element passes the test specified by ; otherwise, the last element in that passes the test specified by . 43 | public static TSource? LastOrDefaultF(this IList source, Func? predicate = null) 44 | { 45 | if (predicate == null) 46 | // ReSharper disable once UseIndexFromEndExpression 47 | return source.Count == 0 ? default : source[source.Count - 1]; 48 | 49 | var sourceArray = source.ToArrayF(); 50 | var sourceLength = sourceArray.Length; 51 | 52 | for (var i = sourceLength - 1; i >= 0; i--) 53 | { 54 | var value = sourceArray[i]; 55 | 56 | if (predicate(value)) 57 | return value; 58 | } 59 | 60 | return default; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /LinqFasterer/LinqFasterer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 9 6 | net5.0;netstandard2.0 7 | enable 8 | 9 | 10 | 2.1.0 11 | 2.1.0 12 | 13 | 14 | Zaczero; jackmott 15 | LinqFasterer Developers 16 | LinqFasterer 17 | LinqFasterer 18 | 19 | 20 | A set of fast LINQ-like extension methods for arrays and lists. Fine-tune your code for the maximum performance. 21 | Copyright © 2021 Kamil Monicz. All rights reserved. 22 | 23 | 24 | github 25 | https://github.com/Zaczero/LinqFasterer 26 | 27 | 28 | linqfaster; linq; fast; faster; performance; fine-tuning; arrays; lists; optimization; optimize 29 | icon.png 30 | https://raw.githubusercontent.com/Zaczero/LinqFasterer/master/resources/icon.png 31 | https://github.com/Zaczero/LinqFasterer 32 | MIT 33 | 34 | 35 | true 36 | true 37 | true 38 | snupkg 39 | 40 | 41 | true 42 | en 43 | 44 | 45 | 46 | false 47 | ..\docs\linqfaster.xml 48 | 49 | 50 | 51 | full 52 | 53 | 54 | 55 | true 56 | 57 | 58 | 59 | 60 | all 61 | runtime; build; native; contentfiles; analyzers; buildtransitive 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | icon.png 70 | true 71 | \ 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /LinqFasterer/OrderBy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace LinqFasterer 6 | { 7 | public static partial class EnumerableF 8 | { 9 | /// 10 | /// Sorts the elements of a sequence in ascending order by using a specified comparer. 11 | /// 12 | /// An of values to order. 13 | /// A selector function to extract a key from an element. 14 | /// An optional used to compare keys; falls back to when set to . 15 | /// Force clone of (disable in-place optimization). 16 | /// The type of the elements of . 17 | /// The type of the key returned by . 18 | /// An whose elements are sorted in ascending order according to a key. 19 | public static IList OrderByF(this IList source, Func keySelector, IComparer? comparer = null, bool forceClone = false) 20 | { 21 | comparer ??= Comparer.Default; 22 | 23 | var sourceArray = source.ToArrayF(forceClone); 24 | var sourceLength = sourceArray.Length; 25 | 26 | var keys = new TKey[sourceLength]; 27 | 28 | for (var i = 0; i < sourceLength; i++) 29 | keys[i] = keySelector(sourceArray[i]); 30 | 31 | Array.Sort(keys, sourceArray, comparer); 32 | 33 | return sourceArray; 34 | } 35 | 36 | /// 37 | /// Sorts the elements of a sequence in descending order by using a specified comparer. 38 | /// 39 | /// An of values to order. 40 | /// A selector function to extract a key from an element. 41 | /// An optional used to compare keys; falls back to when set to . 42 | /// Force clone of (disable in-place optimization). 43 | /// The type of the elements of . 44 | /// The type of the key returned by . 45 | /// An whose elements are sorted in descending order according to a key. 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | public static IList OrderByDescendingF(this IList source, Func keySelector, IComparer? comparer = null, bool forceClone = false) 48 | { 49 | return source.OrderByF(keySelector, comparer, forceClone).ReverseF(); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /LinqFasterer/Prepend.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LinqFasterer 4 | { 5 | public static partial class EnumerableF 6 | { 7 | /// 8 | /// Prepends a value to the beginning of the sequence. 9 | /// 10 | /// An of values. 11 | /// A value to prepend. 12 | /// The type of the elements of . 13 | /// An that starts with and ends with . 14 | public static IList PrependF(this IList source, TSource element) 15 | { 16 | var result = new TSource[source.Count + 1]; 17 | 18 | result[0] = element; 19 | source.CopyTo(result, 1); 20 | 21 | return result; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /LinqFasterer/Repeat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace LinqFasterer 6 | { 7 | public static partial class EnumerableF 8 | { 9 | /// 10 | /// Generates a sequence that contains one repeated value. 11 | /// 12 | /// The value to be repeated. 13 | /// The number of times to repeat the value in the generated sequence. 14 | /// The type of the value to be repeated in the result sequence. 15 | /// An that contains a repeated . 16 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 17 | public static IList RepeatF(TResult element, int count) 18 | { 19 | return count < 1 ? Array.Empty() : new TResult[count].FillF(element, 0, count); 20 | } 21 | 22 | /// 23 | /// Generates a sequence that contains one repeated sequence. 24 | /// 25 | /// An to be repeated. 26 | /// The number of times to repeat the in the generated sequence. 27 | /// The type of the elements of . 28 | /// An that contains a repeated . 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | public static IList RepeatF(this IList source, int count) 31 | { 32 | return RepeatSequenceF(source, count); 33 | } 34 | 35 | /// 36 | /// Generates a sequence that contains one repeated sequence. 37 | /// 38 | /// An to be repeated. 39 | /// The number of times to repeat the in the generated sequence. 40 | /// The type of the elements of . 41 | /// An that contains a repeated . 42 | public static IList RepeatSequenceF(IList source, int count) 43 | { 44 | if (count < 1) 45 | return Array.Empty(); 46 | 47 | var sourceArray = source.ToArrayF(); 48 | var sourceLength = sourceArray.Length; 49 | 50 | switch (sourceLength) 51 | { 52 | case 0: 53 | return Array.Empty(); 54 | case 1: 55 | return RepeatF(sourceArray[0], count); 56 | } 57 | 58 | var resultLength = sourceLength * count; 59 | var result = new TResult[resultLength]; 60 | 61 | Array.Copy(sourceArray, 0, result, 0, sourceLength); 62 | var filled = sourceLength; 63 | 64 | for (; filled * 2 < resultLength; filled *= 2) 65 | Array.Copy(result, 0, result, filled, filled); 66 | 67 | Array.Copy(result, 0, result, filled, resultLength - filled); 68 | 69 | return result; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /LinqFasterer/Reverse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Inverts the order of the elements in a sequence. 10 | /// 11 | /// An of values to reverse. 12 | /// Force clone of (disable in-place optimization). 13 | /// The type of the elements of . 14 | /// An whose elements correspond to those of in reverse order. 15 | public static IList ReverseF(this IList source, bool forceClone = false) 16 | { 17 | var sourceArray = source.ToArrayF(forceClone); 18 | 19 | Array.Reverse(sourceArray); 20 | 21 | return sourceArray; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /LinqFasterer/SelectMany.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Projects each element of sequence to a sequence and flattens the resulting sequences into one sequence. 10 | /// 11 | /// An of values to project. 12 | /// A transform function to apply to each element. 13 | /// The type of the elements of . 14 | /// The type of the value returned by . 15 | /// An whose elements are the result of invoking the one-to-many on each element of . 16 | public static IList SelectManyF(this IList source, Func> selector) 17 | { 18 | var sourceArray = source.ToArrayF(); 19 | var sourceLength = sourceArray.Length; 20 | 21 | var result = new List(); 22 | 23 | for (var i = 0; i < sourceLength; i++) 24 | { 25 | var valueArray = selector(source[i]).ToArrayF(); 26 | var valueLength = valueArray.Length; 27 | 28 | for (var j = 0; j < valueLength; j++) 29 | result.Add(valueArray[j]); 30 | } 31 | 32 | return result; 33 | } 34 | 35 | /// 36 | /// Projects each element of sequence to a sequence and flattens the resulting sequences into one sequence. 37 | /// 38 | /// An of values to project. 39 | /// A transform function to apply to each element; the second parameter of the function represents the index of element. 40 | /// The type of the elements of . 41 | /// The type of the value returned by . 42 | /// An whose elements are the result of invoking the one-to-many on each element of . 43 | public static IList SelectManyF(this IList source, Func> selector) 44 | { 45 | var sourceArray = source.ToArrayF(); 46 | var sourceLength = sourceArray.Length; 47 | 48 | var result = new List(); 49 | 50 | for (var i = 0; i < sourceLength; i++) 51 | { 52 | var valueArray = selector(source[i], i).ToArrayF(); 53 | var valueLength = valueArray.Length; 54 | 55 | for (var j = 0; j < valueLength; j++) 56 | result.Add(valueArray[j]); 57 | } 58 | 59 | return result; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /LinqFasterer/Sort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace LinqFasterer 6 | { 7 | public static partial class EnumerableF 8 | { 9 | /// 10 | /// Sorts the elements of a sequence in ascending order by using a specified comparer. 11 | /// 12 | /// An of values to order. 13 | /// An optional used to compare elements; falls back to when set to . 14 | /// Force clone of (disable in-place optimization). 15 | /// The type of the elements of . 16 | /// An whose elements are sorted in ascending order. 17 | public static IList SortF(this IList source, IComparer? comparer = null, bool forceClone = false) 18 | { 19 | comparer ??= Comparer.Default; 20 | 21 | var sourceArray = source.ToArrayF(forceClone); 22 | 23 | Array.Sort(sourceArray, comparer); 24 | 25 | return sourceArray; 26 | } 27 | 28 | /// 29 | /// Sorts the elements of a sequence in descending order by using a specified comparer. 30 | /// 31 | /// An of values to order. 32 | /// An optional used to compare elements; falls back to when set to . 33 | /// Force clone of (disable in-place optimization). 34 | /// The type of the elements of . 35 | /// An whose elements are sorted in descending order. 36 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 37 | public static IList SortDescendingF(this IList source, IComparer? comparer = null, bool forceClone = false) 38 | { 39 | return source.SortF(comparer, forceClone).ReverseF(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /LinqFasterer/ToCast.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LinqFasterer 4 | { 5 | public static partial class EnumerableF 6 | { 7 | /// 8 | /// Creates a from an . 9 | /// 10 | /// An to create a from. 11 | /// Force clone of (disable in-place optimization). 12 | /// The type of the elements of . 13 | /// A that contains the elements from . 14 | public static TSource[] ToArrayF(this IList source, bool forceClone = false) 15 | { 16 | if (!forceClone && source is TSource[] sourceArray) 17 | return sourceArray; 18 | 19 | var result = new TSource[source.Count]; 20 | 21 | source.CopyTo(result, 0); 22 | 23 | return result; 24 | } 25 | 26 | /// 27 | /// Creates a from an . 28 | /// 29 | /// An to create a from. 30 | /// Force clone of (disable in-place optimization). 31 | /// The type of the elements of . 32 | /// A that contains elements from . 33 | public static List ToListF(this IList source, bool forceClone = false) 34 | { 35 | if (!forceClone && source is List sourceList) 36 | return sourceList; 37 | 38 | var result = new List(source.Count); 39 | 40 | result.AddRange(source); 41 | 42 | return result; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /LinqFasterer/Union.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Produces the set union of two sequences. 10 | /// 11 | /// An whose distinct elements form the first set for the union. 12 | /// An whose distinct elements form the second set for the union. 13 | /// An optional used to compare values; falls back to when set to . 14 | /// The type of the elements of and . 15 | /// An that contains the elements from both input sequences, excluding duplicates. 16 | public static IList UnionF(this IList first, IList second, IEqualityComparer? comparer = null) 17 | { 18 | comparer ??= EqualityComparer.Default; 19 | 20 | var firstLength = first.Count; 21 | var secondLength = second.Count; 22 | 23 | var resultLength = firstLength + secondLength; 24 | var result = new TSource[resultLength]; 25 | int resultSize; 26 | 27 | first.CopyTo(result, 0); 28 | second.CopyTo(result, firstLength); 29 | 30 | // The following code runs faster on smaller workloads. 31 | // The magic number is a result of multiple benchmark tests. 32 | if (resultLength < 2500) 33 | { 34 | var resultHashSet = new HashSet(result, comparer); 35 | resultSize = resultHashSet.Count; 36 | 37 | resultHashSet.CopyTo(result, 0, resultSize); 38 | } 39 | else 40 | { 41 | var resultHashSet = new HashSet(comparer); 42 | resultSize = 0; 43 | 44 | for (var i = 0; i < resultLength; i++) 45 | { 46 | var value = result[i]; 47 | 48 | if (!resultHashSet.Contains(value)) 49 | { 50 | result[resultSize++] = value; 51 | resultHashSet.Add(value); 52 | } 53 | } 54 | } 55 | 56 | Array.Resize(ref result, resultSize); 57 | 58 | return result; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /LinqFasterer/Utils/ComparerMagic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace LinqFasterer.Utils { 6 | 7 | //Takes a comparer, and creates a reverse comparer, for Descending sorts 8 | internal sealed class ComparerReverser : IComparer { 9 | private readonly IComparer wrappedComparer; 10 | 11 | public ComparerReverser(IComparer wrappedComparer) { 12 | this.wrappedComparer = wrappedComparer; 13 | } 14 | #if !(UNITY_4 || UNITY_5) 15 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 16 | #endif 17 | public int Compare(T x, T y) { 18 | return wrappedComparer.Compare(y, x); 19 | } 20 | } 21 | 22 | 23 | internal static class ComparerExtensions { 24 | 25 | // Lets us reverse a comparere with comparer.Reverse(); 26 | public static IComparer Reverse(this IComparer comparer) { 27 | return new ComparerReverser(comparer); 28 | } 29 | } 30 | 31 | internal sealed class LambdaComparer : IComparer { 32 | IComparer comparer; 33 | Func selector; 34 | 35 | public LambdaComparer(Func selector, IComparer comparer) { 36 | this.comparer = comparer; 37 | this.selector = selector; 38 | } 39 | #if !(UNITY_4 || UNITY_5) 40 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 41 | #endif 42 | public int Compare(T x, T y) { 43 | return comparer.Compare(selector(x), selector(y)); 44 | } 45 | } 46 | 47 | internal sealed class ReverseLambdaComparer : IComparer { 48 | IComparer comparer; 49 | Func selector; 50 | 51 | public ReverseLambdaComparer(Func selector, IComparer comparer) { 52 | this.comparer = comparer; 53 | this.selector = selector; 54 | } 55 | #if !(UNITY_4 || UNITY_5) 56 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 57 | #endif 58 | public int Compare(T x, T y) { 59 | return comparer.Compare(selector(y), selector(x)); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /LinqFasterer/Utils/CustomPartition.cs: -------------------------------------------------------------------------------- 1 | #if !(UNITY_4 || UNITY_5) 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | 6 | namespace LinqFasterer.Utils 7 | { 8 | public class EmptyOrderablePartitioner : OrderablePartitioner 9 | { 10 | // Constructor just grabs the collection to wrap 11 | public EmptyOrderablePartitioner() 12 | : base(true, true, true) 13 | { 14 | } 15 | 16 | public override IList>> GetOrderablePartitions(int partitionCount) 17 | { 18 | return new List>>(); 19 | } 20 | 21 | 22 | public override IEnumerable> GetOrderableDynamicPartitions() 23 | { 24 | return new List>(); 25 | } 26 | 27 | // Must be set to true if GetDynamicPartitions() is supported. 28 | public override bool SupportsDynamicPartitions { 29 | get { return true; } 30 | } 31 | } 32 | 33 | internal static class CustomPartition 34 | { 35 | public static OrderablePartitioner> MakePartition(int len, int? batchSize) 36 | { 37 | if (len == 0) return new EmptyOrderablePartitioner>(); 38 | 39 | if (batchSize == null) 40 | { 41 | return Partitioner.Create(0, len); 42 | } 43 | else 44 | { 45 | return Partitioner.Create(0, len, batchSize.Value); 46 | } 47 | } 48 | 49 | public static OrderablePartitioner> MakeSIMDPartition(int len, int chunkSize, int? batchSize) 50 | { 51 | if (len == 0) return new EmptyOrderablePartitioner>(); 52 | 53 | var chunkLen = len - len % chunkSize; 54 | var numChunks = chunkLen / chunkSize; 55 | if (batchSize == null) 56 | { 57 | return Partitioner.Create(0, numChunks,numChunks/Environment.ProcessorCount); 58 | } 59 | else 60 | { 61 | return Partitioner.Create(0, numChunks, batchSize.Value); 62 | } 63 | } 64 | 65 | } 66 | } 67 | #endif -------------------------------------------------------------------------------- /LinqFasterer/Utils/Error.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace LinqFasterer.Utils 4 | { 5 | internal static class Error 6 | { 7 | //internal static Exception ArgumentNull(string s) { return new ArgumentNullException(s); } 8 | 9 | //internal static Exception ArgumentOutOfRange(string s) { return new ArgumentOutOfRangeException(s); } 10 | 11 | internal static Exception MoreThanOneElement() { return new InvalidOperationException("Sequence contains more than one element"); } 12 | 13 | //internal static Exception MoreThanOneMatch() { return new InvalidOperationException("Sequence contains more than one matching element"); } 14 | 15 | internal static Exception NoElements() { return new InvalidOperationException("Sequence contains no elements"); } 16 | 17 | internal static Exception NoMatch() { return new InvalidOperationException("Sequence contains no matching element"); } 18 | 19 | internal static Exception NotSupported() { return new NotSupportedException(); } 20 | } 21 | } -------------------------------------------------------------------------------- /LinqFasterer/Utils/SliceHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace LinqFasterer.Utils 4 | { 5 | public static class SliceHelper 6 | { 7 | public static Span Slice(this T[] array,int start, int len) { 8 | return array.AsSpan().Slice(start, len); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LinqFasterer/Where.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Filters a sequence of values based on a predicate. 10 | /// 11 | /// An to filter. 12 | /// A predicate function to test each element for a condition. 13 | /// Force clone of (disable in-place optimization). 14 | /// The type of the elements of . 15 | /// An that contains elements from that satisfy the condition. 16 | public static IList WhereF(this IList source, Func predicate, bool forceClone = false) 17 | { 18 | var sourceArray = source.ToArrayF(forceClone); 19 | var sourceLength = sourceArray.Length; 20 | var resultSize = 0; 21 | 22 | for (var i = 0; i < sourceLength; i++) 23 | { 24 | var value = sourceArray[i]; 25 | 26 | if (predicate(value)) 27 | sourceArray[resultSize++] = value; 28 | } 29 | 30 | Array.Resize(ref sourceArray, resultSize); 31 | 32 | return sourceArray; 33 | } 34 | 35 | /// 36 | /// Filters a sequence of values based on a predicate. 37 | /// 38 | /// An to filter. 39 | /// A predicate function to test each source element for a condition; the second parameter of the function represents the index of element. 40 | /// Force clone of (disable in-place optimization). 41 | /// The type of the elements of . 42 | /// An that contains elements from that satisfy the condition. 43 | public static IList WhereF(this IList source, Func predicate, bool forceClone = false) 44 | { 45 | var sourceArray = source.ToArrayF(forceClone); 46 | var sourceLength = sourceArray.Length; 47 | var resultSize = 0; 48 | 49 | for (var i = 0; i < sourceLength; i++) 50 | { 51 | var value = sourceArray[i]; 52 | 53 | if (predicate(value, i)) 54 | sourceArray[resultSize++] = value; 55 | } 56 | 57 | Array.Resize(ref sourceArray, resultSize); 58 | 59 | return sourceArray; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /LinqFasterer/Zip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LinqFasterer 5 | { 6 | public static partial class EnumerableF 7 | { 8 | /// 9 | /// Produces a sequence of tuples with elements from the two specified sequences. 10 | /// 11 | /// The first to merge. 12 | /// The second to merge. 13 | /// The type of the elements of . 14 | /// The type of the elements of . 15 | /// An of tuples with elements taken from and , in that order. 16 | public static IList> ZipF(this IList first, IList second) 17 | { 18 | var firstArray = first.ToArrayF(); 19 | var secondArray = second.ToArrayF(); 20 | 21 | var resultLength = Math.Min(firstArray.Length, secondArray.Length); 22 | var result = new ValueTuple[resultLength]; 23 | 24 | for (var i = 0; i < resultLength; i++) 25 | result[i] = new ValueTuple(firstArray[i], secondArray[i]); 26 | 27 | return result; 28 | } 29 | 30 | /// 31 | /// Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results. 32 | /// 33 | /// The first to merge. 34 | /// The second to merge. 35 | /// A selector function that specifies how to merge the elements from the two input sequences. 36 | /// The type of the elements of . 37 | /// The type of the elements of . 38 | /// The type returned by . 39 | /// An that contains merged elements of the two input sequences using . 40 | public static IList ZipF(this IList first, IList second, Func resultSelector) 41 | { 42 | var firstArray = first.ToArrayF(); 43 | var secondArray = second.ToArrayF(); 44 | 45 | var resultLength = Math.Min(firstArray.Length, secondArray.Length); 46 | var result = new TResult[resultLength]; 47 | 48 | for (var i = 0; i < resultLength; i++) 49 | result[i] = resultSelector(firstArray[i], secondArray[i]); 50 | 51 | return result; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /resources/icon-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zaczero/LinqFasterer/de8f41806e5ff6ce85fe2a29f8ad5f70ecdd7bff/resources/icon-24.png -------------------------------------------------------------------------------- /resources/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zaczero/LinqFasterer/de8f41806e5ff6ce85fe2a29f8ad5f70ecdd7bff/resources/icon-32.png -------------------------------------------------------------------------------- /resources/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zaczero/LinqFasterer/de8f41806e5ff6ce85fe2a29f8ad5f70ecdd7bff/resources/icon-48.png -------------------------------------------------------------------------------- /resources/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zaczero/LinqFasterer/de8f41806e5ff6ce85fe2a29f8ad5f70ecdd7bff/resources/icon-64.png -------------------------------------------------------------------------------- /resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zaczero/LinqFasterer/de8f41806e5ff6ce85fe2a29f8ad5f70ecdd7bff/resources/icon.png -------------------------------------------------------------------------------- /resources/icon.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zaczero/LinqFasterer/de8f41806e5ff6ce85fe2a29f8ad5f70ecdd7bff/resources/icon.xcf --------------------------------------------------------------------------------