-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSubjects.cs
More file actions
147 lines (105 loc) · 8.41 KB
/
Copy pathSubjects.cs
File metadata and controls
147 lines (105 loc) · 8.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System.Runtime.CompilerServices;
using LinqOrderProof.Counting;
namespace LinqOrderProof;
/// <summary>
/// Все измеряемые записи. Каждая возвращает число, и это число сверяется
/// с эталоном отчётом checks: записи одной группы обязаны дать один
/// и тот же ответ.
/// Компаратор передаётся аргументом, чтобы одна и та же запись годилась
/// и для замера времени, и для отчёта calls со счётчиком.
/// </summary>
public static class Subjects
{
/// <summary>
/// Псевдослучайные числа с постоянным начальным значением: набор
/// заведомо не отсортирован и один и тот же в каждом прогоне.
/// </summary>
public static int[] Create(int count)
{
int[] items = new int[count];
Random random = new(42);
for (int i = 0; i < count; i++)
{
items[i] = random.Next();
}
return items;
}
/// <summary>
/// Элемент, делящий набор пополам. Порог для условий: под каждое
/// из них подходит примерно половина набора.
/// </summary>
public static int Threshold(int[] items) => items.OrderBy(x => x).ElementAt(items.Length / 2);
// Способы получить результат из OrderBy. Селектор ключа и компаратор
// у всех одинаковые, различается только последний вызов.
[MethodImpl(MethodImplOptions.NoInlining)]
public static int First(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int FirstWhere(int[] items, Func<int, int> key, IComparer<int> comparer, int threshold) => items.OrderBy(key, comparer).First(x => x >= threshold);
[MethodImpl(MethodImplOptions.NoInlining)]
public static int FirstOrDefaultWhere(int[] items, Func<int, int> key, IComparer<int> comparer, int threshold) => items.OrderBy(key, comparer).FirstOrDefault(x => x >= threshold);
[MethodImpl(MethodImplOptions.NoInlining)]
public static int Last(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Last();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int LastWhere(int[] items, Func<int, int> key, IComparer<int> comparer, int threshold) => items.OrderBy(key, comparer).Last(x => x <= threshold);
[MethodImpl(MethodImplOptions.NoInlining)]
public static int Min(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Min();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int Max(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Max();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ElementAtFirst(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).ElementAt(0);
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ElementAtMiddle(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).ElementAt(items.Length / 2);
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ElementAtLast(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).ElementAt(items.Length - 1);
[MethodImpl(MethodImplOptions.NoInlining)]
public static int TakeTenLast(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Take(10).Last();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ToArrayFirst(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).ToArray()[0];
// Операторы между OrderBy и последним вызовом. Последний вызов везде
// First, а ответ у каждой записи свой и сверяется отдельно.
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ThenByFirst(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).ThenBy(x => x).First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int SelectFirst(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Select(x => x).First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int DistinctFirst(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Distinct().First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int TakeTenFirst(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Take(10).First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int SkipOneFirst(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Skip(1).First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ReverseFirst(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Reverse().First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int DescendingFirst(int[] items, Func<int, int> key, IComparer<int> comparer) => items.OrderByDescending(key, comparer).First();
// Тот же ответ, что у FirstWhere, но записанный иначе.
[MethodImpl(MethodImplOptions.NoInlining)]
public static int WhereThenOrderFirst(int[] items, Func<int, int> key, IComparer<int> comparer, int threshold) => items.Where(x => x >= threshold).OrderBy(key, comparer).First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int OrderThenWhereFirst(int[] items, Func<int, int> key, IComparer<int> comparer, int threshold) => items.OrderBy(key, comparer).Where(x => x >= threshold).First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int WhereThenMin(int[] items, int threshold) => items.Where(x => x >= threshold).Min();
// Условия, поменянные местами. Показывают, что разница между First
// и Last не от того, в какую сторону смотрит условие.
[MethodImpl(MethodImplOptions.NoInlining)]
public static int FirstWhereBelow(int[] items, Func<int, int> key, IComparer<int> comparer, int threshold) => items.OrderBy(key, comparer).First(x => x <= threshold);
[MethodImpl(MethodImplOptions.NoInlining)]
public static int LastWhereAbove(int[] items, Func<int, int> key, IComparer<int> comparer, int threshold) => items.OrderBy(key, comparer).Last(x => x >= threshold);
/// <summary>
/// Та же запись, но компаратор не передан вовсе. Этот случай замер
/// покрывает наравне с остальными.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
public static int FirstNoComparer(int[] items, Func<int, int> key) => items.OrderBy(key).First();
[MethodImpl(MethodImplOptions.NoInlining)]
public static int FirstWhereNoComparer(int[] items, Func<int, int> key, int threshold) => items.OrderBy(key).First(x => x >= threshold);
// Ссылочный элемент с ключом вместо числа.
public static Item[] CreateItems(int count) => [.. Create(count).Select(static x => new Item(x))];
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ItemFirst(Item[] items, Func<Item, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).First().Key;
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ItemFirstWhere(Item[] items, Func<Item, int> key, IComparer<int> comparer, int threshold) => items.OrderBy(key, comparer).First(i => i.Key >= threshold).Key;
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ItemLastWhere(Item[] items, Func<Item, int> key, IComparer<int> comparer, int threshold) => items.OrderBy(key, comparer).Last(i => i.Key <= threshold).Key;
[MethodImpl(MethodImplOptions.NoInlining)]
public static int ItemMin(Item[] items, Func<Item, int> key, IComparer<int> comparer) => items.OrderBy(key, comparer).Min(i => i.Key);
}