2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
7 #include "backendsCommon/WorkloadData.hpp"
9 #include <boost/numeric/conversion/cast.hpp>
18 bool NextIndex(const unsigned int numDims, const armnn::TensorShape& dims, std::vector<unsigned int>& current)
20 unsigned int carry = 1;
22 for (unsigned int idx = numDims; idx-- > 0; )
24 unsigned int current_val = current[idx] + carry;
25 if (dims[idx] == current_val)
31 current[idx] = current_val;
39 std::size_t ReducedOutputOffset(const unsigned int numDims, const armnn::TensorShape& dims,
40 std::vector<unsigned int>& index, const unsigned int numAxis,
41 const std::vector<unsigned int>& axis) {
42 std::size_t offset = 0;
43 for (unsigned int idx = 0; idx < numDims; ++idx)
48 for (unsigned int axisIdx = 0; axisIdx < numAxis; ++axisIdx)
50 if (idx == axis[axisIdx])
59 offset = offset * boost::numeric_cast<size_t>(dims[idx]) + boost::numeric_cast<size_t>(index[idx]);
68 void Mean(const armnn::TensorInfo& inputInfo,
69 const armnn::TensorInfo& outputInfo,
70 const std::vector<unsigned int>& axis,
71 const float* inputData,
74 unsigned int inputNumDims = inputInfo.GetNumDimensions();
75 unsigned int outputNumDims = outputInfo.GetNumDimensions();
77 armnn::TensorShape outputDims = outputInfo.GetShape();
78 armnn::TensorShape inputDims = inputInfo.GetShape();
80 // Initialise output data.
81 size_t numOutputs = 1;
82 for (unsigned int idx = 0; idx < outputNumDims; ++idx)
84 numOutputs *= boost::numeric_cast<size_t>(outputDims[idx]);
87 std::vector<float> tempSum(numOutputs);
88 for (size_t idx = 0; idx < numOutputs; ++idx)
90 outputData[idx] = 0.0f;
94 // Initialise temp index.
95 std::vector<unsigned int> tempIndex(inputNumDims);
96 for (unsigned int idx = 0; idx < inputNumDims; ++idx)
101 std::vector<unsigned int> resolvedAxis = axis;
102 if (resolvedAxis.empty())
104 for (unsigned int idx = 0; idx < inputNumDims; ++idx)
106 resolvedAxis.push_back(idx);
109 unsigned int numResolvedAxis = boost::numeric_cast<unsigned int>(resolvedAxis.size());
111 // Iterates through input_data and sum up the reduced axis.
112 for (bool hasNext = true; hasNext; hasNext = NextIndex(inputNumDims, inputDims, tempIndex))
114 size_t inputOffset = ReducedOutputOffset(inputNumDims, inputDims, tempIndex, 0, {});
115 size_t outputOffset = ReducedOutputOffset(inputNumDims, inputDims, tempIndex,
116 numResolvedAxis, resolvedAxis);
117 tempSum[outputOffset] += inputData[inputOffset];
120 // Takes average by num of elements added to get mean.
121 size_t numElementsInAxis = 1;
122 for (unsigned int idx = 0; idx < numResolvedAxis; ++idx)
124 size_t current = boost::numeric_cast<size_t>(inputDims[resolvedAxis[idx]]);
125 BOOST_ASSERT(boost::numeric_cast<float>(current) <
126 (std::numeric_limits<float>::max() / boost::numeric_cast<float>(numElementsInAxis)));
127 numElementsInAxis *= current;
129 if (numElementsInAxis > 0) {
130 for (size_t idx = 0; idx < numOutputs; ++idx)
132 outputData[idx] = tempSum[idx] / boost::numeric_cast<float>(numElementsInAxis);