internal static Tensor Permute(Tensor inTensor, int[] permutations) // TODO: unify Permute() arguments { var padPermutationsToBarracudaRank = TensorShape.MaxRank - permutations.Length; if (padPermutationsToBarracudaRank > 0) { permutations = permutations.Concat(Enumerable.Range(permutations.Length, padPermutationsToBarracudaRank)).ToArray(); } Debug.Assert(permutations.Length == TensorShape.MaxRank); // See: https://stackoverflow.com/a/32034565 Profiler.BeginSample("ONNXTensor.Permute"); var outTensor = new Tensor(ONNXLayout.Permute(inTensor.shape.ToArray(), permutations)); Debug.Assert(outTensor.length == inTensor.length); // {0, 2, 3, 1} => {0, 3, 1, 2} // {2, 3, 1, 0} => {3, 2, 0, 1} // => {find_index(0), find_index(1), find_index(2), find_index(3)} var reversePermute = new int[permutations.Length]; for (var i = 0; i < permutations.Length; ++i) { reversePermute[i] = Array.IndexOf(permutations, i); } // outTensor strides var tempOutStrides = new int[TensorShape.MaxRank + 1]; tempOutStrides[8] = 1; for (int i = 7; i >= 0; --i) { tempOutStrides[i] = tempOutStrides[i + 1] * outTensor.shape[i]; } var outStride = new int[reversePermute.Length]; for (var i = 0; i < reversePermute.Length; ++i) { outStride[i] = tempOutStrides[reversePermute[i] + 1]; } // inTensor strides var inStrides = new int[TensorShape.MaxRank]; inStrides[7] = 1; for (int i = 6; i >= 0; --i) { inStrides[i] = inStrides[i + 1] * inTensor.shape[i + 1]; } for (var it = new TensorIterator(inTensor.shape); it.IsValid(); ++it) { outTensor[it.d0 * outStride[0] + it.d1 * outStride[1] + it.d2 * outStride[2] + it.d3 * outStride[3] + it.d4 * outStride[4] + it.d5 * outStride[5] + it.d6 * outStride[6] + it.d7 * outStride[7]] = inTensor[ it.d0 * inStrides[0] + it.d1 * inStrides[1] + it.d2 * inStrides[2] + it.d3 * inStrides[3] + it.d4 * inStrides[4] + it.d5 * inStrides[5] + it.d6 * inStrides[6] + it.d7 * inStrides[7]]; } Profiler.EndSample(); return(outTensor); }
public ONNXTensor NonZero() { //https://github.com/onnx/onnx/blob/master/docs/Operators.md#NonZero //https://numpy.org/doc/stable/reference/generated/numpy.nonzero.html //Return the indices of the elements that are non-zero. Iterating row major c style. // pad with 1s to visit all elements at least once in the loop. int[] paddedONNXShape = new int[] { 1, 1, 1, 1, 1, 1, 1, 1 }; for (int d = 0; d < rank; ++d) { paddedONNXShape[d] = shape[d]; } // collect all non zero item List <int[]> nonZeroIndices = new List <int[]>(); for (var it = new TensorIterator(m_Data.shape); it.IsValid(); it.Next()) { if (Math.Abs(m_Data[it.index]) > Single.Epsilon) { nonZeroIndices.Add(new int[] { it.d0, it.d1, it.d2, it.d3, it.d4, it.d5, it.d6, it.d7 }); } } // store indices in dest tensor Tensor result = new Tensor(new TensorShape(rank, nonZeroIndices.Count)); for (int i = 0; i < nonZeroIndices.Count; ++i) { for (int d = 0; d < rank; ++d) { result[d, i] = nonZeroIndices[i][d]; } } return(new ONNXTensor(result, new int[] { rank, nonZeroIndices.Count })); }