public static unsafe TResult SumRange <TResult, TVectorSelector, TSelector>(int start, int count, TVectorSelector vectorSelector, TSelector selector) where TVectorSelector : struct, IFunction <Vector <int>, Vector <TResult> > where TSelector : struct, IFunction <int, TResult> where TResult : struct { var sum = default(TResult); var index = 0; if (Vector.IsHardwareAccelerated && count > Vector <TResult> .Count * 4) // use SIMD { var seed = stackalloc int[Vector <TResult> .Count]; if (start is 0) { for (index = 0; index < Vector <TResult> .Count; index++) { seed[index] = index; } } else { for (index = 0; index < Vector <TResult> .Count; index++) { seed[index] = index + start; } } var vector = Unsafe.AsRef <Vector <int> >(seed); var vectorIncrement = new Vector <int>(Vector <TResult> .Count); var vectorSum = Vector <TResult> .Zero; for (index = 0; index <= count - Vector <TResult> .Count; index += Vector <TResult> .Count) { vectorSum += vectorSelector.Invoke(vector); vector += vectorIncrement; } for (index = 0; index < Vector <TResult> .Count; index++) { sum = GenericsOperator.Add(vectorSum[index], sum); } } if (start is 0) { for (; index < count; index++) { sum = GenericsOperator.Add(selector.Invoke(index), sum); } } else { for (; index < count; index++) { sum = GenericsOperator.Add(selector.Invoke(index + start), sum); } } return(sum); }
static TResult Sum <TSource, TResult, TVectorSelector, TSelector>(this ReadOnlySpan <TSource> source, TVectorSelector vectorSelector, TSelector selector) where TVectorSelector : struct, IFunction <Vector <TSource>, Vector <TResult> > where TSelector : struct, IFunction <TSource, TResult> where TSource : struct where TResult : struct { var sum = default(TResult); if (Vector.IsHardwareAccelerated && source.Length > Vector <TResult> .Count * 2) // use SIMD { var vectors = MemoryMarshal.Cast <TSource, Vector <TSource> >(source); var vectorSum = Vector <TResult> .Zero; foreach (var vector in vectors) { vectorSum += vectorSelector.Invoke(vector); } for (var index = 0; index < Vector <TResult> .Count; index++) { sum = GenericsOperator.Add(vectorSum[index], sum); } for (var index = source.Length - (source.Length % Vector <TSource> .Count); index < source.Length; index++) { var item = source[index]; sum = GenericsOperator.Add(selector.Invoke(item), sum); } } else { foreach (var item in source) { sum = GenericsOperator.Add(selector.Invoke(item), sum); } } return(sum); }
/////////////////////////////////////////////////////////// static TSource Sum <TSource>(this ReadOnlySpan <TSource> source) where TSource : struct { var sum = default(TSource); if (Vector.IsHardwareAccelerated && source.Length > Vector <TSource> .Count * 2) // use SIMD { var vectors = MemoryMarshal.Cast <TSource, Vector <TSource> >(source); var vectorSum = Vector <TSource> .Zero; foreach (var vector in vectors) { vectorSum += vector; } for (var index = 0; index < Vector <TSource> .Count; index++) { sum = GenericsOperator.Add(vectorSum[index], sum); } for (var index = source.Length - (source.Length % Vector <TSource> .Count); index < source.Length; index++) { var item = source[index]; sum = GenericsOperator.Add(item, sum); } } else { foreach (var item in source) { sum = GenericsOperator.Add(item, sum); } } return(sum); }