public static void TrueIndices(DataAndLayout <int> trgt, DataAndLayout <bool> src)
        {
            var targetPosItr = new PosIter(trgt.FastAccess);
            var srcPosItr    = new PosIter(src.FastAccess);

            while (targetPosItr.Active)
            {
                if (src.Data[srcPosItr.Addr])
                {
                    for (var d = 0; d < src.FastAccess.NumDiensions; d++)
                    {
                        trgt.Data[targetPosItr.Addr] = srcPosItr.Pos[d];
                        targetPosItr.MoveNext();
                    }
                }

                srcPosItr.MoveNext();
            }
        }
        public static void ApplyNoaryOp <T>(Func <int[], T> op, DataAndLayout <T> trgt, bool isIndexed, bool useThreads)
        {
            var nd    = trgt.FastAccess.NumDiensions;
            var shape = trgt.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);
                var pos          = new int[targetPosItr.Pos.Length];

                while (targetPosItr.Active)
                {
                    var targetAddr = targetPosItr.Addr;
                    if (nd == 0)
                    {
                        trgt.Data[targetPosItr.Addr] = op(null);
                    }
                    else if (isIndexed)
                    {
                        for (var d = 0; d < nd; d++)
                        {
                            pos[d] = targetPosItr.Pos[d];
                        }

                        for (var i = 0; i < shape[nd - 1]; i++)
                        {
                            trgt.Data[targetAddr] = op(pos);
                            targetAddr            = targetAddr + trgt.FastAccess.Stride[nd - 1];
                            pos[nd - 1]           = pos[nd - 1] + 1;
                        }
                    }
                    else
                    {
                        for (var i = 0; i < shape[nd - 1]; i++)
                        {
                            trgt.Data[targetAddr] = op(null);
                            targetAddr            = targetAddr + trgt.FastAccess.Stride[nd - 1];
                        }
                    }

                    targetPosItr.MoveNext();
                }
            }

            if (useThreads && nd > 1)
            {
                Parallel.For(0, shape[0], index => loops(true, index));
            }
            else
            {
                loops(false, 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);
            }
        }