예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        ///////////////////////////////////////////////////////////

        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);
        }