1
1
using System . Numerics ;
2
2
using System . Runtime . CompilerServices ;
3
3
using System . Runtime . InteropServices ;
4
+ #if ! NET48
4
5
using System . Runtime . Intrinsics ;
6
+ #endif
7
+ using Microsoft . CodeAnalysis . CSharp . Syntax ;
5
8
6
9
namespace SimdIteration ;
7
10
@@ -10,8 +13,22 @@ public static class LinqExtensions
10
13
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
11
14
public static IEnumerable < TSource [ ] > OptimizedChunk < TSource > ( this IEnumerable < TSource > source , int size )
12
15
{
16
+ #if NET48
17
+ if ( source == null )
18
+ {
19
+ throw new ArgumentNullException ( nameof ( source ) ) ;
20
+ }
21
+ #else
13
22
ArgumentNullException . ThrowIfNull ( source ) ;
23
+ #endif
24
+ #if NET8_0
14
25
ArgumentOutOfRangeException . ThrowIfLessThan ( size , 1 ) ;
26
+ #else
27
+ if ( size < 1 )
28
+ {
29
+ throw new ArgumentOutOfRangeException ( nameof ( source ) ) ;
30
+ }
31
+ #endif
15
32
return SafeOptimizedChunker ( source , size ) ;
16
33
}
17
34
@@ -71,35 +88,65 @@ private static IEnumerable<TSource[]> SafeOptimizedChunker<TSource>(IEnumerable<
71
88
}
72
89
}
73
90
}
91
+ #if ! NET48
92
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
93
+ public static int SumSimd ( this int [ ] source ) => SimdCore < int > . Sum ( new ReadOnlySpan < int > ( source ) ) ;
74
94
75
95
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
76
- public static int Sum ( this int [ ] source ) => SimdCore < int > . Sum ( new ReadOnlySpan < int > ( source ) ) ;
96
+ public static ( int Min , int Max ) MinMaxSimd ( this int [ ] source ) => SimdCore < int > . MinMax ( new ReadOnlySpan < int > ( source ) ) ;
97
+ #endif
77
98
78
99
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
79
- public static ( int Min , int Max ) MinMax ( this int [ ] source ) => SimdCore < int > . MinMax ( new ReadOnlySpan < int > ( source ) ) ;
100
+ public static ( int Min , int Max ) MinMaxLinq ( this int [ ] source )
101
+ {
102
+ return ( source . Min ( ) , source . Max ( ) ) ;
103
+ }
80
104
81
105
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
82
- public static decimal Average ( this int [ ] source ) => SimdCore < int > . Sum ( new ReadOnlySpan < int > ( source ) ) / ( source . Length * 1M ) ;
106
+ public static ( int Min , int Max ) MinMaxForEach ( this int [ ] source )
107
+ {
108
+ int min = source [ 0 ] ;
109
+ int max = min ;
110
+
111
+ foreach ( int value in source )
112
+ {
113
+ if ( value < min )
114
+ {
115
+ min = value ;
116
+ }
117
+ if ( value > max )
118
+ {
119
+ max = value ;
120
+ }
121
+ }
122
+
123
+ return ( min , max ) ;
124
+ }
83
125
}
84
126
127
+ #if ! NET48
85
128
file static class SimdCore < T > where T : struct , INumber < T >
86
129
{
87
130
#region fields
88
131
private static readonly int _vectorLength ;
132
+ #if NET8_0
89
133
private static readonly bool _is512 ;
134
+ #endif
90
135
private static readonly bool _is256 ;
91
136
private static readonly bool _is128 ;
92
137
#endregion
93
138
94
139
#region ctor
95
140
static SimdCore ( )
96
141
{
97
- if ( Vector256 . IsHardwareAccelerated )
142
+ #if NET8_0
143
+ if ( Vector512 . IsHardwareAccelerated )
98
144
{
99
145
_is512 = true ;
100
146
_vectorLength = Vector512 < T > . Count ;
101
147
return ;
102
148
}
149
+ #endif
103
150
if ( Vector256 . IsHardwareAccelerated )
104
151
{
105
152
_is256 = true ;
@@ -121,10 +168,12 @@ internal static T Sum(ReadOnlySpan<T> source)
121
168
{
122
169
if ( source . Length > _vectorLength )
123
170
{
171
+ #if NET8_0
124
172
if ( _is512 )
125
173
{
126
174
return Sum512 ( source ) ;
127
175
}
176
+ #endif
128
177
if ( _is256 )
129
178
{
130
179
return Sum256 ( source ) ;
@@ -136,7 +185,7 @@ internal static T Sum(ReadOnlySpan<T> source)
136
185
}
137
186
return SumFallback ( source ) ;
138
187
}
139
-
188
+ #if NET8_0
140
189
private static T Sum512 ( ReadOnlySpan < T > source )
141
190
{
142
191
T sum = T . Zero ;
@@ -163,7 +212,7 @@ private static T Sum512(ReadOnlySpan<T> source)
163
212
164
213
return sum + Vector512 . Sum ( vectorSum512 ) ;
165
214
}
166
-
215
+ #endif
167
216
private static T Sum256 ( ReadOnlySpan < T > source )
168
217
{
169
218
T sum = T . Zero ;
@@ -236,10 +285,12 @@ internal static (T Min, T Max) MinMax(ReadOnlySpan<T> source)
236
285
{
237
286
if ( source . Length > _vectorLength )
238
287
{
288
+ #if NET8_0
239
289
if ( _is512 )
240
290
{
241
291
return MinMax512 ( source ) ;
242
292
}
293
+ #endif
243
294
if ( _is256 )
244
295
{
245
296
return MinMax256 ( source ) ;
@@ -252,6 +303,7 @@ internal static (T Min, T Max) MinMax(ReadOnlySpan<T> source)
252
303
return MinMaxFallback ( source ) ;
253
304
}
254
305
306
+ #if NET8_0
255
307
private static ( T Min , T Max ) MinMax512 ( ReadOnlySpan < T > source )
256
308
{
257
309
ref T current = ref MemoryMarshal . GetReference ( source ) ;
@@ -302,7 +354,7 @@ private static (T Min, T Max) MinMax512(ReadOnlySpan<T> source)
302
354
303
355
return ( min , max ) ;
304
356
}
305
-
357
+ #endif
306
358
private static ( T Min , T Max ) MinMax256 ( ReadOnlySpan < T > source )
307
359
{
308
360
ref T current = ref MemoryMarshal . GetReference ( source ) ;
@@ -426,4 +478,5 @@ private static (T Min, T Max) MinMaxFallback(ReadOnlySpan<T> source)
426
478
return ( min , max ) ;
427
479
}
428
480
#endregion
429
- }
481
+ }
482
+ #endif
0 commit comments