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