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