ArmNN  NotReleased
Descriptors.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "armnn/Descriptors.hpp"
6 #include "armnn/Logging.hpp"
7 
8 #include <algorithm>
9 #include <array>
10 #include <vector>
11 
12 #include <boost/format.hpp>
13 #include <boost/numeric/conversion/cast.hpp>
14 
15 namespace armnn
16 {
17 
18 PermutationVector::PermutationVector(const ValueType *dimMappings, const SizeType numDimMappings)
19 {
20  // Validation
21 
22  if (numDimMappings > MaxNumOfTensorDimensions)
23  {
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));
27  }
28 
29  if ((dimMappings == nullptr) && (numDimMappings != 0))
30  {
31  throw InvalidArgumentException("Dimension mappings must not be NULL if the number of mappings is positive");
32  }
33 
34  for (SizeType i = 0; i < numDimMappings; ++i)
35  {
36  const ValueType dstIndex = dimMappings[i];
37  if (dstIndex >= numDimMappings)
38  {
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)));
41  }
42  }
43 
44  // Validation: Detect duplicates
45  {
46  std::array<bool, MaxNumOfTensorDimensions> observedDims;
47  observedDims.fill(false);
48 
49  for (SizeType i = 0; i < numDimMappings; ++i)
50  {
51  const ValueType dstIndex = dimMappings[i];
52  if (observedDims[dstIndex])
53  {
54  throw InvalidArgumentException("Invalid dimension mappings: Two or more source dimensions are mapped "
55  "to the same output dimension");
56  }
57  observedDims[dstIndex] = true;
58  }
59  }
60 
61  // Initialize
62  for (SizeType i = 0; i < numDimMappings; ++i)
63  {
64  m_DimMappings[i] = dimMappings[i];
65  }
66  m_NumDimMappings = numDimMappings;
67 }
68 
69 PermutationVector::PermutationVector(std::initializer_list<ValueType> dimMappings)
70  : PermutationVector(dimMappings.begin(), boost::numeric_cast<SizeType>(dimMappings.size()))
71 {
72 }
73 
75 : m_ConcatAxis(1)
76 , m_NumViews(0)
77 , m_NumDimensions(0)
78 , m_ViewOrigins(nullptr)
79 {}
80 
81 OriginsDescriptor::OriginsDescriptor(uint32_t numViews, uint32_t numDimensions /*= 4*/)
82 : m_ConcatAxis(1)
83 , m_NumViews(numViews)
84 , m_NumDimensions(numDimensions)
85 , m_ViewOrigins(numViews && numDimensions > 0 ? new uint32_t *[numViews]() : nullptr)
86 {
87  for (uint32_t i = 0; m_NumDimensions > 0 && i < m_NumViews; ++i)
88  {
89  m_ViewOrigins[i] = new uint32_t[m_NumDimensions]();
90  }
91 }
92 
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)
98 {
99  for (uint32_t i = 0; m_NumDimensions > 0 && i < m_NumViews; ++i)
100  {
101  m_ViewOrigins[i] = new uint32_t[m_NumDimensions]();
102  memcpy(m_ViewOrigins[i], other.m_ViewOrigins[i], m_NumDimensions * sizeof(uint32_t));
103  }
104 }
105 
108 {
109  swap(*this, other);
110 }
111 
113 {
114  for (uint32_t i = 0; m_NumDimensions > 0 && i < m_NumViews; ++i)
115  {
116  delete[] m_ViewOrigins[i];
117  }
118  delete[] m_ViewOrigins;
119 }
120 
122 {
123  swap(*this, rhs);
124  return *this;
125 }
126 
128 {
129  if (GetNumViews() != rhs.GetNumViews() ||
130  GetNumDimensions() != rhs.GetNumDimensions() ||
131  GetConcatAxis() != rhs.GetConcatAxis())
132  {
133  return false;
134  }
135 
136  for (unsigned int i = 0u; i < GetNumViews(); ++i)
137  {
138  for (unsigned int j = 0u; j < GetNumDimensions(); ++j)
139  {
140  if (GetViewOrigin(i)[j] != rhs.GetViewOrigin(i)[j])
141  {
142  return false;
143  }
144  }
145  }
146 
147  return true;
148 }
149 
150 void OriginsDescriptor::SetConcatAxis(unsigned int concatAxis)
151 {
152  m_ConcatAxis = concatAxis;
153 }
155 {
156  return m_ConcatAxis;
157 }
158 
159 Status OriginsDescriptor::SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
160 {
161  if (view >= m_NumViews)
162  {
163  ARMNN_LOG(error) << "OriginsDescriptor::SetViewOriginCoord: view argument:" << view <<
164  " is out of range";
165  return Status::Failure;
166  }
167  if (coord >= m_NumDimensions)
168  {
169  ARMNN_LOG(error) << "OriginsDescriptor::SetViewOriginCoord: coord argument:" << coord <<
170  " is out of range";
171  return Status::Failure;
172  }
173 
174  m_ViewOrigins[view][coord] = value;
175  return Status::Success;
176 }
177 
178 
180 {
181  return m_NumViews;
182 }
183 
185 {
186  return m_NumDimensions;
187 }
188 
189 const uint32_t* OriginsDescriptor::GetViewOrigin(uint32_t idx) const
190 {
191  return m_ViewOrigins ? m_ViewOrigins[idx] : nullptr;
192 }
193 
194 
195 // Reorders the viewOrigins in accordance with the indices presented in newOrdering array.
196 void OriginsDescriptor::ReorderOrigins(unsigned int* newOrdering, unsigned int numNewOrdering)
197 {
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]);
201 
202  for (unsigned int i = 0; i < numNewOrdering; ++i)
203  {
204  m_ViewOrigins[i] = viewOrigins[newOrdering[i]];
205  }
206 }
207 
209 : m_Origins()
210 , m_ViewSizes(nullptr)
211 {}
212 
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)
217 {
218  if (m_ViewSizes)
219  {
220  for (uint32_t i = 0; GetNumDimensions() > 0 && i < GetNumViews(); ++i)
221  {
222  m_ViewSizes[i] = new uint32_t[GetNumDimensions()]();
223  }
224  }
225 }
226 
228  : m_Origins(other.m_Origins)
229  , m_ViewSizes(other.GetNumViews() > 0 && other.GetNumDimensions() > 0 ?
230  new uint32_t *[other.GetNumViews()]() : nullptr)
231 {
232  if (m_ViewSizes)
233  {
234  for (uint32_t i = 0; GetNumDimensions() > 0 && i < GetNumViews(); ++i)
235  {
236  m_ViewSizes[i] = new uint32_t[GetNumDimensions()]();
237  memcpy(m_ViewSizes[i], other.m_ViewSizes[i], GetNumDimensions() * sizeof(uint32_t));
238  }
239  }
240 }
241 
243  : ViewsDescriptor()
244 {
245  swap(*this, other);
246 }
247 
249 {
250  if (m_ViewSizes)
251  {
252  for (uint32_t i = 0; GetNumDimensions() > 0 && i < GetNumViews(); ++i)
253  {
254  delete[] m_ViewSizes[i];
255  }
256  delete[] m_ViewSizes;
257  }
258 }
259 
261 {
262  swap(*this, rhs);
263  return *this;
264 }
265 
267 {
268  if (GetNumViews() != rhs.GetNumViews() || GetNumDimensions() != rhs.GetNumDimensions())
269  {
270  return false;
271  }
272 
273  for (unsigned int i = 0u; i < GetNumViews(); ++i)
274  {
275  for (unsigned int j = 0u; j < GetNumDimensions(); ++j)
276  {
277  if (GetViewOrigin(i)[j] != rhs.GetViewOrigin(i)[j] || GetViewSizes(i)[j] != rhs.GetViewSizes(i)[j])
278  {
279  return false;
280  }
281  }
282  }
283 
284  return true;
285 }
286 
288 {
289  return m_Origins.GetNumViews();
290 }
291 
293 {
294  return m_Origins.GetNumDimensions();
295 }
296 
297 const uint32_t* ViewsDescriptor::GetViewOrigin(uint32_t idx) const
298 {
299  return m_Origins.GetViewOrigin(idx);
300 }
301 
302 Status ViewsDescriptor::SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
303 {
304  return m_Origins.SetViewOriginCoord(view, coord, value);
305 }
306 
307 Status ViewsDescriptor::SetViewSize(uint32_t view, uint32_t coord, uint32_t value)
308 {
309  if (!m_ViewSizes)
310  {
311  ARMNN_LOG(error) << "ViewsDescriptor::SetViewSize: invalid view sizes";
312  return Status::Failure;
313  }
314 
315  if (view >= GetNumViews())
316  {
317  ARMNN_LOG(error) << "ViewsDescriptor::SetViewSize: view argument:" << view <<
318  " is out of range";
319  return Status::Failure;
320  }
321  if (coord >= GetNumDimensions())
322  {
323  ARMNN_LOG(error) << "ViewsDescriptor::SetViewSize: coord argument:" << coord <<
324  " is out of range";
325  return Status::Failure;
326  }
327 
328  m_ViewSizes[view][coord] = value;
329  return Status::Success;
330 }
331 
332 const uint32_t* ViewsDescriptor::GetViewSizes(uint32_t idx) const
333 {
334  return m_ViewSizes ? m_ViewSizes[idx] : nullptr;
335 }
336 
338 {
339  return m_Origins;
340 }
341 
343 {
344  using std::swap;
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);
349 }
350 
351 void swap(ViewsDescriptor& first, ViewsDescriptor& second)
352 {
353  using std::swap;
354  swap(first.m_Origins, second.m_Origins);
355  swap(first.m_ViewSizes, second.m_ViewSizes);
356 }
357 
359  unsigned int axis) const
360 {
361  int start = m_Begin[axis];
362 
363  if (m_BeginMask & (1 << axis))
364  {
365  if (m_Stride[axis] > 0)
366  {
367  start = std::numeric_limits<int>::min();
368  }
369  else
370  {
371  start = std::numeric_limits<int>::max();
372  }
373  }
374 
375  const int axisSize = boost::numeric_cast<int>(inputShape[axis]);
376  if (start < 0)
377  {
378  start += (axisSize);
379  }
380 
381  return std::max(0, std::min(start, axisSize - 1));
382 
383 }
384 
386  unsigned int axis,
387  int startForAxis) const
388 {
389 
390  if (m_ShrinkAxisMask & (1 << axis))
391  {
392  return startForAxis + 1;
393  }
394 
395  int stop = m_End[axis];
396 
397  if (m_EndMask & (1 << axis))
398  {
399  if (m_Stride[axis] > 0)
400  {
401  stop = std::numeric_limits<int>::max();
402  }
403  else
404  {
405  stop = std::numeric_limits<int>::min();
406  }
407  }
408 
409  const int axisSize = boost::numeric_cast<int>(inputShape[axis]);
410  if (stop < 0)
411  {
412  stop += axisSize;
413  }
414 
415  return m_Stride[axis] > 0 ? std::max(0, std::min(stop, axisSize)) :
416  std::max(-1, std::min(stop, axisSize - 1));
417 
418 }
419 
420 }
void SetConcatAxis(unsigned int concatAxis)
Set the concatenation axis value.
friend void swap(OriginsDescriptor &first, OriginsDescriptor &second)
Swap the ViewsDescriptor values first and second.
const OriginsDescriptor & GetOrigins() const
Get the View Origins.
int GetStopForAxis(const TensorShape &inputShape, unsigned int axis, int startForAxis) const
Status
Definition: Types.hpp:26
PermutationVector(const ValueType *dimMappings, SizeType numDimMappings)
Definition: Descriptors.cpp:18
ViewsDescriptor & operator=(ViewsDescriptor rhs)
ConstIterator begin() const
Definition: Types.hpp:201
unsigned int SizeType
Definition: Types.hpp:174
Status SetViewSize(uint32_t view, uint32_t coord, uint32_t value)
Set the size of the views. The arguments are: view, dimension, value. If the view is greater than or ...
Status SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
Status SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
bool operator==(const OriginsDescriptor &rhs) const
A ViewsDescriptor for the SplitterLayer. Descriptor to configure the splitting process. Number of Views must be equal to the number of outputs, and their order must match - e.g. first view corresponds to the first output, second view to the second output, etc.
#define ARMNN_LOG(severity)
Definition: Logging.hpp:163
uint32_t GetNumDimensions() const
Get the number of dimensions.
const uint32_t * GetViewOrigin(uint32_t idx) const
Return the view origin at the int value idx.
uint32_t GetNumViews() const
Get the number of views.
void swap(ViewsDescriptor &first, ViewsDescriptor &second)
uint32_t GetNumDimensions() const
Get the number of dimensions.
unsigned int GetConcatAxis() const
Get the concatenation axis value.
bool operator==(const ViewsDescriptor &rhs) const
const uint32_t * GetViewSizes(uint32_t idx) const
Get the view sizes at the int value idx.
void ReorderOrigins(unsigned int *newOrdering, unsigned int numNewOrdering)
Reorders the viewOrigins in accordance with the indices presented in newOrdering array. The number of views must match number of elements in the new ordering array.
constexpr unsigned int MaxNumOfTensorDimensions
Definition: Types.hpp:18
const uint32_t * GetViewOrigin(uint32_t idx) const
Get the view origin at the int value idx.
unsigned int ValueType
Definition: Types.hpp:173
int GetStartForAxis(const TensorShape &inputShape, unsigned int axis) const
uint32_t GetNumViews() const
Get the number of views.
An OriginsDescriptor for the ConcatLayer. Descriptor to configure the concatenation process...
friend void swap(ViewsDescriptor &first, ViewsDescriptor &second)
Swap the ViewsDescriptor value first and second.
OriginsDescriptor & operator=(OriginsDescriptor rhs)