aboutsummaryrefslogtreecommitdiff
path: root/src/backends/reference/workloads/Stack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/backends/reference/workloads/Stack.cpp')
-rw-r--r--src/backends/reference/workloads/Stack.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/backends/reference/workloads/Stack.cpp b/src/backends/reference/workloads/Stack.cpp
new file mode 100644
index 0000000000..386c8992eb
--- /dev/null
+++ b/src/backends/reference/workloads/Stack.cpp
@@ -0,0 +1,115 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "Stack.hpp"
+#include "RefWorkloadUtils.hpp"
+
+namespace armnn
+{
+
+void Stack(const StackQueueDescriptor& data,
+ std::vector<std::unique_ptr<Decoder<float>>>& inputs,
+ Encoder<float>& output)
+{
+ const TensorInfo& outputInfo = GetTensorInfo(data.m_Outputs[0]);
+ const TensorInfo& inputInfo = GetTensorInfo(data.m_Inputs[0]);
+
+ unsigned int outputNumDims = outputInfo.GetNumDimensions();
+ unsigned int inputNumDims = inputInfo.GetNumDimensions();
+
+ const armnn::TensorShape& outputDims = outputInfo.GetShape();
+ const armnn::TensorShape& inputDims = inputInfo.GetShape();
+
+ unsigned int axis = data.m_Parameters.m_Axis;
+
+ // Initialise output data
+ unsigned int numOutputElements = 1;
+ for (unsigned int i=0; i<outputNumDims; ++i)
+ {
+ numOutputElements *= outputDims[i];
+ }
+
+ const unsigned int iNumTensors = static_cast<unsigned int>(data.m_Inputs.size());
+ const unsigned int iBatchSize = inputDims[0];
+ const unsigned int iChannels = (inputNumDims > 1) ? inputDims[1] : 1;
+ const unsigned int iHeight = (inputNumDims > 2) ? inputDims[2] : 1;
+ const unsigned int iWidth = (inputNumDims > 3) ? inputDims[3] : 1;
+
+ const unsigned int oBatchSize = outputDims[1];
+ const unsigned int oChannels = (outputNumDims > 2) ? outputDims[2] : 1;
+ const unsigned int oHeight = (outputNumDims > 3) ? outputDims[3] : 1;
+ const unsigned int oWidth = (outputNumDims > 4) ? outputDims[4] : 1;
+
+ // Array to store the input coordinates
+ // iCoordinates[0] = i, iCoordinates[1] = bi, iCoordinates[2] = ci
+ // iCoordinates[3] = hi, iCoordinates[4] = wi, iCoordinates[5] = 0
+ // iCoordinates[5] will be always zero and used for not incrementing
+ // the output when the input has less than 4 dimensions
+ std::array<unsigned int, 6> iCoordinates{ 0 };
+
+ // Array of pointers used to map the output coordinates to the input ones, in accordance with the axis
+ // This array is initialized with &iCoordinates[5] since this will be always zero
+ std::array<unsigned int *, 5> oCoordinates = { &iCoordinates[5],
+ &iCoordinates[5],
+ &iCoordinates[5],
+ &iCoordinates[5],
+ &iCoordinates[5] };
+
+ // Set the axis coordinate
+ oCoordinates[axis] = &iCoordinates[0];
+
+ // Map the output coordinates, accounting for the axis
+ unsigned int dim_shift = 0;
+ for(unsigned int dim = 0; dim < inputNumDims; ++dim)
+ {
+ if(dim == axis)
+ {
+ dim_shift++;
+ }
+ oCoordinates[dim + dim_shift] = &iCoordinates[dim + 1];
+ }
+
+ // Alias for the input coordinates
+ unsigned int &i = iCoordinates[0];
+ unsigned int &bi = iCoordinates[1];
+ unsigned int &ci = iCoordinates[2];
+ unsigned int &hi = iCoordinates[3];
+ unsigned int &wi = iCoordinates[4];
+
+ // Alias for the output coordinates
+ unsigned int &o = *(oCoordinates[0]);
+ unsigned int &bo = *(oCoordinates[1]);
+ unsigned int &co = *(oCoordinates[2]);
+ unsigned int &ho = *(oCoordinates[3]);
+ unsigned int &wo = *(oCoordinates[4]);
+
+ // Stack tensors
+ for(; i < iNumTensors; ++(i))
+ {
+ for(bi = 0; bi < iBatchSize; ++(bi))
+ {
+ for(ci = 0; ci < iChannels; ++(ci))
+ {
+ for(hi = 0; hi < iHeight; ++(hi))
+ {
+ for(wi = 0; wi < iWidth; ++(wi))
+ {
+ output[o * oWidth * oHeight * oChannels * oBatchSize +
+ bo * oWidth * oHeight * oChannels +
+ co * oWidth * oHeight +
+ ho * oWidth +
+ wo];
+
+ output.Set(inputs[i]->Get());
+
+ ++(*(inputs[i]));
+ }
+ }
+ }
+ }
+ }
+}
+
+} // namespace armnn