Skip to content

Commit 7dd8b6b

Browse files
committed
[All] add All extensions.
1 parent 0dfa000 commit 7dd8b6b

File tree

7 files changed

+353
-0
lines changed

7 files changed

+353
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## AllOnArray
2+
3+
### Source
4+
[AllOnArray.cs](../../src/StructLinq.Benchmark/AllOnArray.cs)
5+
6+
### Results:
7+
``` ini
8+
9+
BenchmarkDotNet=v0.12.0, OS=Windows 10.0.19041
10+
Intel Core i7-7700 CPU 3.60GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
11+
.NET Core SDK=3.1.402
12+
[Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT
13+
DefaultJob : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT
14+
15+
16+
```
17+
| Method | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
18+
|----------------------------- |-----------:|---------:|---------:|-----------:|------:|--------:|-------:|------:|------:|----------:|
19+
| For | 332.5 ns | 7.10 ns | 13.68 ns | 329.9 ns | 0.10 | 0.01 | - | - | - | - |
20+
| Linq | 3,471.3 ns | 67.19 ns | 84.97 ns | 3,467.4 ns | 1.00 | 0.00 | 0.0076 | - | - | 32 B |
21+
| StructLinq | 1,080.9 ns | 21.54 ns | 48.61 ns | 1,063.1 ns | 0.32 | 0.02 | 0.0076 | - | - | 32 B |
22+
| StructLinqZeroAlloc | 1,036.4 ns | 12.66 ns | 11.22 ns | 1,035.6 ns | 0.30 | 0.01 | - | - | - | - |
23+
| StructLinqIFunctionZeroAlloc | 237.6 ns | 6.60 ns | 5.85 ns | 235.9 ns | 0.07 | 0.00 | - | - | - | - |

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ Following aggregators are available:
171171
- `Sum`
172172
- `Min`
173173
- `Max`
174+
- `All`
174175
### Generators
175176
Following generators are available:
176177
- `Range`
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System.Linq;
2+
using System.Runtime.CompilerServices;
3+
using BenchmarkDotNet.Attributes;
4+
5+
namespace StructLinq.Benchmark
6+
{
7+
[MemoryDiagnoser]
8+
public class AllOnArray
9+
{
10+
private const int Count = 1000;
11+
private readonly int[] array;
12+
public AllOnArray()
13+
{
14+
array = Enumerable.ToArray(Enumerable.Range(0, Count));
15+
}
16+
17+
[Benchmark]
18+
public bool For()
19+
{
20+
for (int i = 0; i < Count; i++)
21+
{
22+
if (array[i] >= Count / 2)
23+
return false;
24+
}
25+
26+
return true;
27+
}
28+
29+
[Benchmark(Baseline = true)]
30+
public bool Linq() => array.All(x=> x < Count / 2);
31+
32+
[Benchmark]
33+
public bool StructLinq() => array.ToStructEnumerable().All(x => x < Count /2);
34+
35+
[Benchmark]
36+
public bool StructLinqZeroAlloc() => array.ToStructEnumerable().All(x => x < Count /2, x=>x );
37+
38+
[Benchmark]
39+
public bool StructLinqIFunctionZeroAlloc()
40+
{
41+
var func = new AllFunction();
42+
return array.ToStructEnumerable().All(ref func, x => x);
43+
}
44+
45+
private struct AllFunction : IFunction<int, bool>
46+
{
47+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
48+
public bool Eval(int element)
49+
{
50+
return element < Count / 2;
51+
}
52+
}
53+
}
54+
}

src/StructLinq.Tests/AllTests.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using FluentAssertions;
2+
using Xunit;
3+
4+
namespace StructLinq.Tests
5+
{
6+
public class AllTests
7+
{
8+
[Fact]
9+
public void ShouldBeTrueWithFunc()
10+
{
11+
StructEnumerable.Range(0, 10).All(x => x < 11).Should().BeTrue();
12+
}
13+
14+
[Fact]
15+
public void ShouldBeFalseWithFunc()
16+
{
17+
StructEnumerable.Range(0, 10).All(x => x > 5).Should().BeFalse();
18+
}
19+
20+
[Fact]
21+
public void ShouldBeTrueWithFuncZeroAlloc()
22+
{
23+
StructEnumerable.Range(0, 10).All(x => x < 11, x=> x).Should().BeTrue();
24+
}
25+
26+
[Fact]
27+
public void ShouldBeFalseWithFuncZeroAlloc()
28+
{
29+
StructEnumerable.Range(0, 10).All(x => x > 5, x=> x).Should().BeFalse();
30+
}
31+
32+
[Fact]
33+
public void ShouldBeFalseWithIFunctionZeroAlloc()
34+
{
35+
var func = new AllFunction();
36+
StructEnumerable.Range(0, 10).All(ref func, x => x).Should().BeFalse();
37+
}
38+
39+
private struct AllFunction : IFunction<int, bool>
40+
{
41+
public bool Eval(int element)
42+
{
43+
return element > 5;
44+
}
45+
}
46+
47+
[Fact]
48+
public void ShouldBeFalseWithIFunction()
49+
{
50+
var func = new AllFunction();
51+
StructEnumerable.Range(0, 10).All(func).Should().BeFalse();
52+
}
53+
}
54+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using FluentAssertions;
2+
using Xunit;
3+
4+
namespace StructLinq.Tests
5+
{
6+
public class RefAllTests
7+
{
8+
[Fact]
9+
public void ShouldBeTrueWithFunc()
10+
{
11+
StructEnumerable.Range(0, 10).ToArray().ToRefStructEnumerable().All(x => x < 11).Should().BeTrue();
12+
}
13+
14+
[Fact]
15+
public void ShouldBeFalseWithFunc()
16+
{
17+
StructEnumerable.Range(0, 10).ToArray().ToRefStructEnumerable().All(x => x > 5).Should().BeFalse();
18+
}
19+
20+
[Fact]
21+
public void ShouldBeTrueWithFuncZeroAlloc()
22+
{
23+
StructEnumerable.Range(0, 10).ToArray().ToRefStructEnumerable().All(x => x < 11, x=> x).Should().BeTrue();
24+
}
25+
26+
[Fact]
27+
public void ShouldBeFalseWithFuncZeroAlloc()
28+
{
29+
StructEnumerable.Range(0, 10).ToArray().ToRefStructEnumerable().All(x => x > 5, x=> x).Should().BeFalse();
30+
}
31+
32+
[Fact]
33+
public void ShouldBeFalseWithIFunctionZeroAlloc()
34+
{
35+
var func = new AllFunction();
36+
StructEnumerable.Range(0, 10).ToArray().ToRefStructEnumerable().All(ref func, x => x).Should().BeFalse();
37+
}
38+
39+
private struct AllFunction : IInFunction<int, bool>
40+
{
41+
public bool Eval(in int element)
42+
{
43+
return element > 5;
44+
}
45+
}
46+
47+
[Fact]
48+
public void ShouldBeFalseWithIFunction()
49+
{
50+
var func = new AllFunction();
51+
StructEnumerable.Range(0, 10).ToArray().ToRefStructEnumerable().All(func).Should().BeFalse();
52+
}
53+
54+
}
55+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+

2+
3+
// ReSharper disable once CheckNamespace
4+
5+
using System;
6+
using System.Runtime.CompilerServices;
7+
8+
// ReSharper disable once CheckNamespace
9+
namespace StructLinq
10+
{
11+
public static partial class StructEnumerable
12+
{
13+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14+
private static bool RefInnerAll<T, TEnumerator>(ref TEnumerator enumerator, Func<T, bool> predicate)
15+
where TEnumerator : struct, IRefStructEnumerator<T>
16+
{
17+
while (enumerator.MoveNext())
18+
{
19+
ref var current = ref enumerator.Current;
20+
if (!predicate(current))
21+
{
22+
enumerator.Dispose();
23+
return false;
24+
}
25+
}
26+
enumerator.Dispose();
27+
return true;
28+
}
29+
30+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
31+
private static bool RefInnerAll<T, TEnumerator, TFunction>(ref TEnumerator enumerator, ref TFunction predicate)
32+
where TEnumerator : struct, IRefStructEnumerator<T>
33+
where TFunction : IInFunction<T, bool>
34+
{
35+
while (enumerator.MoveNext())
36+
{
37+
ref var current = ref enumerator.Current;
38+
if (!predicate.Eval(in current))
39+
{
40+
enumerator.Dispose();
41+
return false;
42+
}
43+
}
44+
enumerator.Dispose();
45+
return true;
46+
}
47+
48+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
49+
public static bool All<T, TEnumerable, TEnumerator>(this TEnumerable enumerable, Func<T, bool> predicate, Func<TEnumerable, IRefStructEnumerable<T, TEnumerator>> _)
50+
where TEnumerable : IRefStructEnumerable<T, TEnumerator>
51+
where TEnumerator : struct, IRefStructEnumerator<T>
52+
{
53+
var enumerator = enumerable.GetEnumerator();
54+
return RefInnerAll(ref enumerator, predicate);
55+
}
56+
57+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
58+
public static bool All<T, TEnumerator>(this IRefStructEnumerable<T, TEnumerator> enumerable, Func<T, bool> predicate)
59+
where TEnumerator : struct, IRefStructEnumerator<T>
60+
{
61+
var enumerator = enumerable.GetEnumerator();
62+
return RefInnerAll(ref enumerator, predicate);
63+
}
64+
65+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
66+
public static bool All<T, TEnumerable, TEnumerator, TFunction>(this TEnumerable enumerable, ref TFunction predicate, Func<TEnumerable, IRefStructEnumerable<T, TEnumerator>> _)
67+
where TEnumerable : IRefStructEnumerable<T, TEnumerator>
68+
where TEnumerator : struct, IRefStructEnumerator<T>
69+
where TFunction : IInFunction<T, bool>
70+
{
71+
var enumerator = enumerable.GetEnumerator();
72+
return RefInnerAll<T, TEnumerator, TFunction>(ref enumerator, ref predicate);
73+
}
74+
75+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
76+
public static bool All<T, TEnumerator>(this IRefStructEnumerable<T, TEnumerator> enumerable, IInFunction<T, bool> predicate)
77+
where TEnumerator : struct, IRefStructEnumerator<T>
78+
{
79+
var enumerator = enumerable.GetEnumerator();
80+
return RefInnerAll<T, TEnumerator, IInFunction<T, bool>>(ref enumerator, ref predicate);
81+
}
82+
}
83+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+

2+
3+
// ReSharper disable once CheckNamespace
4+
5+
using System;
6+
using System.Runtime.CompilerServices;
7+
8+
// ReSharper disable once CheckNamespace
9+
namespace StructLinq
10+
{
11+
public static partial class StructEnumerable
12+
{
13+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14+
private static bool InnerAll<T, TEnumerator>(ref TEnumerator enumerator, Func<T, bool> predicate)
15+
where TEnumerator : struct, IStructEnumerator<T>
16+
{
17+
while (enumerator.MoveNext())
18+
{
19+
var current = enumerator.Current;
20+
if (!predicate(current))
21+
{
22+
enumerator.Dispose();
23+
return false;
24+
}
25+
}
26+
enumerator.Dispose();
27+
return true;
28+
}
29+
30+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
31+
private static bool InnerAll<T, TEnumerator, TFunction>(ref TEnumerator enumerator, ref TFunction predicate)
32+
where TEnumerator : struct, IStructEnumerator<T>
33+
where TFunction : IFunction<T, bool>
34+
{
35+
while (enumerator.MoveNext())
36+
{
37+
var current = enumerator.Current;
38+
if (!predicate.Eval(current))
39+
{
40+
enumerator.Dispose();
41+
return false;
42+
}
43+
}
44+
enumerator.Dispose();
45+
return true;
46+
}
47+
48+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
49+
public static bool All<T, TEnumerable, TEnumerator>(this TEnumerable enumerable, Func<T, bool> predicate, Func<TEnumerable, IStructEnumerable<T, TEnumerator>> _)
50+
where TEnumerable : IStructEnumerable<T, TEnumerator>
51+
where TEnumerator : struct, IStructEnumerator<T>
52+
{
53+
var enumerator = enumerable.GetEnumerator();
54+
return InnerAll(ref enumerator, predicate);
55+
}
56+
57+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
58+
public static bool All<T, TEnumerator>(this IStructEnumerable<T, TEnumerator> enumerable, Func<T, bool> predicate)
59+
where TEnumerator : struct, IStructEnumerator<T>
60+
{
61+
var enumerator = enumerable.GetEnumerator();
62+
return InnerAll(ref enumerator, predicate);
63+
}
64+
65+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
66+
public static bool All<T, TEnumerable, TEnumerator, TFunction>(this TEnumerable enumerable, ref TFunction predicate, Func<TEnumerable, IStructEnumerable<T, TEnumerator>> _)
67+
where TEnumerable : IStructEnumerable<T, TEnumerator>
68+
where TEnumerator : struct, IStructEnumerator<T>
69+
where TFunction : IFunction<T, bool>
70+
{
71+
var enumerator = enumerable.GetEnumerator();
72+
return InnerAll<T, TEnumerator, TFunction>(ref enumerator, ref predicate);
73+
}
74+
75+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
76+
public static bool All<T, TEnumerator>(this IStructEnumerable<T, TEnumerator> enumerable, IFunction<T, bool> predicate)
77+
where TEnumerator : struct, IStructEnumerator<T>
78+
{
79+
var enumerator = enumerable.GetEnumerator();
80+
return InnerAll<T, TEnumerator, IFunction<T, bool>>(ref enumerator, ref predicate);
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)