示例#1
0
        public static void FindLastAxis <T>(T value, DataAndLayout <int> trgt, DataAndLayout <T> src)
        {
            var nd = src.FastAccess.NumDiensions;
            var sp = ScalarPrimitivesRegistry.For <T, T>();

            int op(int[] srcIndex, int pos, T val)
            {
                if (pos != SpecialIdx.NotFound)
                {
                    return(pos);
                }
                else
                {
                    if (sp.Equal(val, value))
                    {
                        return(srcIndex[nd - 1]);
                    }
                    else
                    {
                        return(SpecialIdx.NotFound);
                    }
                }
            }

            var initial = new InitialOption <int>(true, SpecialIdx.NotFound);

            ApplyAxisFold(op, v => v, trgt, src, initial, true, true);
        }
示例#2
0
        public static void CountTrueLastAxis(DataAndLayout <int> trgt, DataAndLayout <bool> src)
        {
            int foldOp(int[] pos, int res, bool v) => v ? res + 1 : res;

            var initial = new InitialOption <int>(true, 0);

            ApplyAxisFold(foldOp, v => v, trgt, src, initial, false, true);
        }
示例#3
0
        public static void AnyLastAxis(DataAndLayout <bool> trgt, DataAndLayout <bool> src)
        {
            bool foldOp(int[] pos, bool res, bool v) => res || v;

            var initial = new InitialOption <bool>(true, false);

            ApplyAxisFold(foldOp, v => v, trgt, src, initial, false, true);
        }
示例#4
0
        public static void ProductLastAxis <T>(DataAndLayout <T> trgt, DataAndLayout <T> src)
        {
            var p = ScalarPrimitivesRegistry.For <T, T>();

            T foldOp(int[] pos, T res, T v) => p.Multiply(res, v);

            var initial = new InitialOption <T>(true, Primitives.One <T>());

            ApplyAxisFold(foldOp, v => v, trgt, src, initial, false, true);
        }
示例#5
0
        public static void MinLastAxis <T>(DataAndLayout <T> trgt, DataAndLayout <T> src)
        {
            var p = ScalarPrimitivesRegistry.For <T, T>();

            T foldOp(int[] pos, T res, T v) => p.Less(res, v) ? res : v;

            var initial = new InitialOption <T>(true, Primitives.MaxValue <T>());

            ApplyAxisFold(foldOp, v => v, trgt, src, initial, false, true);
        }
示例#6
0
        public static void ApplyAxisFold <TS, T, T1>(
            Func <int[], TS, T1, TS> foldOp,
            Func <TS, T> extractOp,
            DataAndLayout <T> trgt,
            DataAndLayout <T1> src,
            InitialOption <TS> initial,
            bool isIndexed,
            bool useThreads)
        {
            var nd    = src.FastAccess.NumDiensions;
            var shape = src.FastAccess.Shape;

            void loops(bool dim0Fixed, int dim0Pos)
            {
                var fromDim  = dim0Fixed ? 1 : 0;
                var startPos = new int[nd];

                if (dim0Fixed)
                {
                    startPos[0] = dim0Pos;
                }

                var targetPosItr = new PosIter(trgt.FastAccess, startPos, fromDim: fromDim, toDim: nd - 2);

                PosIter initialPosItr;

                if (!initial.UseValue)
                {
                    var intialDataAndLayout = initial.DataAndLayout;
                    initialPosItr = new PosIter(intialDataAndLayout.FastAccess, startPos, fromDim: fromDim, toDim: nd - 2);
                }
                else
                {
                    // it won't be used. Only for compiler. I need a better solution.
                    initialPosItr = new PosIter(src.FastAccess, startPos, fromDim: fromDim, toDim: nd - 2);
                }

                var srcPosItr = new PosIter(src.FastAccess, startPos, fromDim: fromDim, toDim: nd - 2);
                var pos       = new int[targetPosItr.Pos.Length];

                while (targetPosItr.Active)
                {
                    var srcAddr = srcPosItr.Addr;
                    TS  state;
                    if (initial.UseValue)
                    {
                        state = initial.Value;
                    }
                    else
                    {
                        state = initial.DataAndLayout.Data[initialPosItr.Addr];
                    }

                    if (nd == 0)
                    {
                        trgt.Data[targetPosItr.Addr] = extractOp(foldOp(null, state, src.Data[srcAddr]));
                    }
                    else if (isIndexed)
                    {
                        for (var d = 0; d < nd - 1; d++)
                        {
                            pos[d] = targetPosItr.Pos[d];
                        }

                        pos[nd - 1] = 0;

                        for (var i = 0; i < shape[nd - 1]; i++)
                        {
                            state       = foldOp(pos, state, src.Data[srcAddr]);
                            srcAddr    += src.FastAccess.Stride[nd - 1];
                            pos[nd - 1] = pos[nd - 1] + 1;
                        }

                        trgt.Data[targetPosItr.Addr] = extractOp(state);
                    }
                    else
                    {
                        for (var i = 0; i < shape[nd - 1]; i++)
                        {
                            state    = foldOp(null, state, src.Data[srcAddr]);
                            srcAddr += src.FastAccess.Stride[nd - 1];
                        }

                        trgt.Data[targetPosItr.Addr] = extractOp(state);
                    }

                    targetPosItr.MoveNext();
                    if (!initial.UseValue)
                    {
                        initialPosItr.MoveNext();
                    }
                }
            }

            if (useThreads && nd > 1)
            {
                Parallel.For(0, shape[0], index => loops(true, index));
            }
            else
            {
                loops(false, 0);
            }
        }