2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
5 #include "armnn/Descriptors.hpp"
11 #include <boost/format.hpp>
12 #include <boost/log/trivial.hpp>
13 #include <boost/numeric/conversion/cast.hpp>
18 PermutationVector::PermutationVector(const ValueType *dimMappings, const SizeType numDimMappings)
22 if (numDimMappings > MaxNumOfTensorDimensions)
24 boost::format fmt("The number of mappings (%1%) cannot be greater "
25 "than the maximum number of dimensions supported (%2%)");
26 throw InvalidArgumentException(boost::str(fmt % numDimMappings % MaxNumOfTensorDimensions));
29 if ((dimMappings == nullptr) && (numDimMappings != 0))
31 throw InvalidArgumentException("Dimension mappings must not be NULL if the number of mappings is positive");
34 for (SizeType i = 0; i < numDimMappings; ++i)
36 const ValueType dstIndex = dimMappings[i];
37 if (dstIndex >= numDimMappings)
39 boost::format fmt("Dimension mapping at index %1% is invalid: %2% is outside of the valid range [0,%3%]");
40 throw InvalidArgumentException(boost::str(fmt % i % dstIndex % (numDimMappings - 1)));
44 // Validation: Detect duplicates
46 std::array<bool, MaxNumOfTensorDimensions> observedDims;
47 observedDims.fill(false);
49 for (SizeType i = 0; i < numDimMappings; ++i)
51 const ValueType dstIndex = dimMappings[i];
52 if (observedDims[dstIndex])
54 throw InvalidArgumentException("Invalid dimension mappings: Two or more source dimensions are mapped "
55 "to the same output dimension");
57 observedDims[dstIndex] = true;
62 for (SizeType i = 0; i < numDimMappings; ++i)
64 m_DimMappings[i] = dimMappings[i];
66 m_NumDimMappings = numDimMappings;
69 PermutationVector::PermutationVector(std::initializer_list<ValueType> dimMappings)
70 : PermutationVector(dimMappings.begin(), boost::numeric_cast<SizeType>(dimMappings.size()))
74 OriginsDescriptor::OriginsDescriptor()
78 , m_ViewOrigins(nullptr)
81 OriginsDescriptor::OriginsDescriptor(uint32_t numViews, uint32_t numDimensions /*= 4*/)
83 , m_NumViews(numViews)
84 , m_NumDimensions(numDimensions)
85 , m_ViewOrigins(numViews && numDimensions > 0 ? new uint32_t *[numViews]() : nullptr)
87 for (uint32_t i = 0; m_NumDimensions > 0 && i < m_NumViews; ++i)
89 m_ViewOrigins[i] = new uint32_t[m_NumDimensions]();
93 OriginsDescriptor::OriginsDescriptor(const OriginsDescriptor& other)
94 : m_ConcatAxis(other.m_ConcatAxis)
95 , m_NumViews(other.m_NumViews)
96 , m_NumDimensions(other.m_NumDimensions)
97 , m_ViewOrigins(other.m_NumViews && other.m_NumDimensions > 0 ? new uint32_t *[other.m_NumViews]() : nullptr)
99 for (uint32_t i = 0; m_NumDimensions > 0 && i < m_NumViews; ++i)
101 m_ViewOrigins[i] = new uint32_t[m_NumDimensions]();
102 memcpy(m_ViewOrigins[i], other.m_ViewOrigins[i], m_NumDimensions * sizeof(uint32_t));
106 OriginsDescriptor::OriginsDescriptor(OriginsDescriptor&& other)
107 : OriginsDescriptor()
112 OriginsDescriptor::~OriginsDescriptor()
114 for (uint32_t i = 0; m_NumDimensions > 0 && i < m_NumViews; ++i)
116 delete[] m_ViewOrigins[i];
118 delete[] m_ViewOrigins;
121 OriginsDescriptor& OriginsDescriptor::operator=(OriginsDescriptor rhs)
127 bool OriginsDescriptor::operator==(const OriginsDescriptor& rhs) const
129 if (GetNumViews() != rhs.GetNumViews() ||
130 GetNumDimensions() != rhs.GetNumDimensions() ||
131 GetConcatAxis() != rhs.GetConcatAxis())
136 for (unsigned int i = 0u; i < GetNumViews(); ++i)
138 for (unsigned int j = 0u; j < GetNumDimensions(); ++j)
140 if (GetViewOrigin(i)[j] != rhs.GetViewOrigin(i)[j])
150 void OriginsDescriptor::SetConcatAxis(unsigned int concatAxis)
152 m_ConcatAxis = concatAxis;
154 unsigned int OriginsDescriptor::GetConcatAxis() const
159 Status OriginsDescriptor::SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
161 if (view >= m_NumViews)
163 BOOST_LOG_TRIVIAL(error) << "OriginsDescriptor::SetViewOriginCoord: view argument:" << view <<
165 return Status::Failure;
167 if (coord >= m_NumDimensions)
169 BOOST_LOG_TRIVIAL(error) << "OriginsDescriptor::SetViewOriginCoord: coord argument:" << coord <<
171 return Status::Failure;
174 m_ViewOrigins[view][coord] = value;
175 return Status::Success;
179 uint32_t OriginsDescriptor::GetNumViews() const
184 uint32_t OriginsDescriptor::GetNumDimensions() const
186 return m_NumDimensions;
189 const uint32_t* OriginsDescriptor::GetViewOrigin(uint32_t idx) const
191 return m_ViewOrigins ? m_ViewOrigins[idx] : nullptr;
195 // Reorders the viewOrigins in accordance with the indices presented in newOrdering array.
196 void OriginsDescriptor::ReorderOrigins(unsigned int* newOrdering, unsigned int numNewOrdering)
198 BOOST_ASSERT_MSG(m_NumViews == numNewOrdering, "number of views must match number of "
199 "elements in the new ordering array");
200 std::vector<uint32_t*> viewOrigins(&m_ViewOrigins[0], &m_ViewOrigins[m_NumViews]);
202 for (unsigned int i = 0; i < numNewOrdering; ++i)
204 m_ViewOrigins[i] = viewOrigins[newOrdering[i]];
208 ViewsDescriptor::ViewsDescriptor()
210 , m_ViewSizes(nullptr)
213 ViewsDescriptor::ViewsDescriptor(uint32_t numViews, uint32_t numDimensions /*= 4*/)
214 : m_Origins(numViews, numDimensions)
215 , m_ViewSizes(numViews > 0 && numDimensions > 0 ?
216 new uint32_t *[numViews]() : nullptr)
220 for (uint32_t i = 0; GetNumDimensions() > 0 && i < GetNumViews(); ++i)
222 m_ViewSizes[i] = new uint32_t[GetNumDimensions()]();
227 ViewsDescriptor::ViewsDescriptor(const ViewsDescriptor& other)
228 : m_Origins(other.m_Origins)
229 , m_ViewSizes(other.GetNumViews() > 0 && other.GetNumDimensions() > 0 ?
230 new uint32_t *[other.GetNumViews()]() : nullptr)
234 for (uint32_t i = 0; GetNumDimensions() > 0 && i < GetNumViews(); ++i)
236 m_ViewSizes[i] = new uint32_t[GetNumDimensions()]();
237 memcpy(m_ViewSizes[i], other.m_ViewSizes[i], GetNumDimensions() * sizeof(uint32_t));
242 ViewsDescriptor::ViewsDescriptor(ViewsDescriptor&& other)
248 ViewsDescriptor::~ViewsDescriptor()
252 for (uint32_t i = 0; GetNumDimensions() > 0 && i < GetNumViews(); ++i)
254 delete[] m_ViewSizes[i];
256 delete[] m_ViewSizes;
260 ViewsDescriptor& ViewsDescriptor::operator=(ViewsDescriptor rhs)
266 bool ViewsDescriptor::operator==(const ViewsDescriptor& rhs) const
268 if (GetNumViews() != rhs.GetNumViews() || GetNumDimensions() != rhs.GetNumDimensions())
273 for (unsigned int i = 0u; i < GetNumViews(); ++i)
275 for (unsigned int j = 0u; j < GetNumDimensions(); ++j)
277 if (GetViewOrigin(i)[j] != rhs.GetViewOrigin(i)[j] || GetViewSizes(i)[j] != rhs.GetViewSizes(i)[j])
287 uint32_t ViewsDescriptor::GetNumViews() const
289 return m_Origins.GetNumViews();
292 uint32_t ViewsDescriptor::GetNumDimensions() const
294 return m_Origins.GetNumDimensions();
297 const uint32_t* ViewsDescriptor::GetViewOrigin(uint32_t idx) const
299 return m_Origins.GetViewOrigin(idx);
302 Status ViewsDescriptor::SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
304 return m_Origins.SetViewOriginCoord(view, coord, value);
307 Status ViewsDescriptor::SetViewSize(uint32_t view, uint32_t coord, uint32_t value)
311 BOOST_LOG_TRIVIAL(error) << "ViewsDescriptor::SetViewSize: invalid view sizes";
312 return Status::Failure;
315 if (view >= GetNumViews())
317 BOOST_LOG_TRIVIAL(error) << "ViewsDescriptor::SetViewSize: view argument:" << view <<
319 return Status::Failure;
321 if (coord >= GetNumDimensions())
323 BOOST_LOG_TRIVIAL(error) << "ViewsDescriptor::SetViewSize: coord argument:" << coord <<
325 return Status::Failure;
328 m_ViewSizes[view][coord] = value;
329 return Status::Success;
332 const uint32_t* ViewsDescriptor::GetViewSizes(uint32_t idx) const
334 return m_ViewSizes ? m_ViewSizes[idx] : nullptr;
337 const OriginsDescriptor& ViewsDescriptor::GetOrigins() const
342 void swap(OriginsDescriptor& first, OriginsDescriptor& second)
345 swap(first.m_NumViews, second.m_NumViews);
346 swap(first.m_NumDimensions, second.m_NumDimensions);
347 swap(first.m_ViewOrigins, second.m_ViewOrigins);
348 swap(first.m_ConcatAxis, second.m_ConcatAxis);
351 void swap(ViewsDescriptor& first, ViewsDescriptor& second)
354 swap(first.m_Origins, second.m_Origins);
355 swap(first.m_ViewSizes, second.m_ViewSizes);
358 int StridedSliceDescriptor::GetStartForAxis(const TensorShape& inputShape,
359 unsigned int axis) const
361 int start = m_Begin[axis];
363 if (m_BeginMask & (1 << axis))
365 if (m_Stride[axis] > 0)
367 start = std::numeric_limits<int>::min();
371 start = std::numeric_limits<int>::max();
375 const int axisSize = boost::numeric_cast<int>(inputShape[axis]);
381 return std::max(0, std::min(start, axisSize - 1));
385 int StridedSliceDescriptor::GetStopForAxis(const TensorShape& inputShape,
387 int startForAxis) const
390 if (m_ShrinkAxisMask & (1 << axis))
392 return startForAxis + 1;
395 int stop = m_End[axis];
397 if (m_EndMask & (1 << axis))
399 if (m_Stride[axis] > 0)
401 stop = std::numeric_limits<int>::max();
405 stop = std::numeric_limits<int>::min();
409 const int axisSize = boost::numeric_cast<int>(inputShape[axis]);
415 return m_Stride[axis] > 0 ? std::max(0, std::min(stop, axisSize)) :
416 std::max(-1, std::min(stop, axisSize - 1));