Release 18.08
[platform/upstream/armnn.git] / src / armnn / Descriptors.cpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // See LICENSE file in the project root for full license information.
4 //
5 #include "armnn/Descriptors.hpp"
6
7 #include <algorithm>
8 #include <array>
9 #include <vector>
10
11 #include <boost/format.hpp>
12 #include <boost/log/trivial.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
74 OriginsDescriptor::OriginsDescriptor()
75 : m_NumViews(0)
76 , m_NumDimensions(0)
77 , m_ViewOrigins(nullptr)
78 {}
79
80 OriginsDescriptor::OriginsDescriptor(uint32_t numViews, uint32_t numDimensions /*= 4*/)
81 : m_NumViews(numViews)
82 , m_NumDimensions(numDimensions)
83 , m_ViewOrigins(numViews && numDimensions > 0 ? new uint32_t *[numViews]() : nullptr)
84 {
85     for (uint32_t i = 0; m_NumDimensions > 0 && i < m_NumViews; ++i)
86     {
87         m_ViewOrigins[i] = new uint32_t[m_NumDimensions]();
88     }
89 }
90
91 OriginsDescriptor::OriginsDescriptor(const OriginsDescriptor& other)
92 : m_NumViews(other.m_NumViews)
93 , m_NumDimensions(other.m_NumDimensions)
94 , m_ViewOrigins(other.m_NumViews && other.m_NumDimensions > 0 ? new uint32_t *[other.m_NumViews]() : nullptr)
95 {
96     for (uint32_t i = 0; m_NumDimensions > 0 && i < m_NumViews; ++i)
97     {
98         m_ViewOrigins[i] = new uint32_t[m_NumDimensions]();
99         memcpy(m_ViewOrigins[i], other.m_ViewOrigins[i], m_NumDimensions * sizeof(uint32_t));
100     }
101 }
102
103 OriginsDescriptor::OriginsDescriptor(OriginsDescriptor&& other)
104 : OriginsDescriptor()
105 {
106     swap(*this, other);
107 }
108
109 OriginsDescriptor::~OriginsDescriptor()
110 {
111     for (uint32_t i = 0; m_NumDimensions > 0 && i < m_NumViews; ++i)
112     {
113         delete[] m_ViewOrigins[i];
114     }
115     delete[] m_ViewOrigins;
116 }
117
118 OriginsDescriptor& OriginsDescriptor::operator=(OriginsDescriptor rhs)
119 {
120     swap(*this, rhs);
121     return *this;
122 }
123
124 Status OriginsDescriptor::SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
125 {
126     if (view >= m_NumViews)
127     {
128         BOOST_LOG_TRIVIAL(error) << "OriginsDescriptor::SetViewOriginCoord: view argument:" << view <<
129             " is out of range";
130         return Status::Failure;
131     }
132     if (coord >= m_NumDimensions)
133     {
134         BOOST_LOG_TRIVIAL(error) << "OriginsDescriptor::SetViewOriginCoord: coord argument:" << coord <<
135             " is out of range";
136         return Status::Failure;
137     }
138
139     m_ViewOrigins[view][coord] = value;
140     return Status::Success;
141 }
142
143
144 uint32_t OriginsDescriptor::GetNumViews() const
145 {
146     return m_NumViews;
147 }
148
149 uint32_t OriginsDescriptor::GetNumDimensions() const
150 {
151     return m_NumDimensions;
152 }
153
154 const uint32_t* OriginsDescriptor::GetViewOrigin(uint32_t idx) const
155 {
156     return m_ViewOrigins ? m_ViewOrigins[idx] : nullptr;
157 }
158
159
160 // Reorders the viewOrigins in accordance with the indices presented in newOrdering array.
161 void OriginsDescriptor::ReorderOrigins(unsigned int*  newOrdering, unsigned int numNewOrdering)
162 {
163     BOOST_ASSERT_MSG(m_NumViews == numNewOrdering, "number of views must match number of "
164         "elements in the new ordering array");
165     std::vector<uint32_t*> viewOrigins(&m_ViewOrigins[0], &m_ViewOrigins[m_NumViews]);
166
167     for (unsigned int i = 0; i < numNewOrdering; ++i)
168     {
169         m_ViewOrigins[i] = viewOrigins[newOrdering[i]];
170     }
171 }
172
173 ViewsDescriptor::ViewsDescriptor()
174 : m_Origins()
175 , m_ViewSizes(nullptr)
176 {}
177
178 ViewsDescriptor::ViewsDescriptor(uint32_t numViews, uint32_t numDimensions /*= 4*/)
179     : m_Origins(numViews, numDimensions)
180     , m_ViewSizes(numViews > 0 && numDimensions > 0 ?
181                       new uint32_t *[numViews]() : nullptr)
182 {
183     if (m_ViewSizes)
184     {
185         for (uint32_t i = 0; GetNumDimensions() > 0 && i < GetNumViews(); ++i)
186         {
187             m_ViewSizes[i] = new uint32_t[GetNumDimensions()]();
188         }
189     }
190 }
191
192 ViewsDescriptor::ViewsDescriptor(const ViewsDescriptor& other)
193     : m_Origins(other.m_Origins)
194     , m_ViewSizes(other.GetNumViews() > 0 && other.GetNumDimensions() > 0 ?
195                       new uint32_t *[other.GetNumViews()]() : nullptr)
196 {
197     if (m_ViewSizes)
198     {
199         for (uint32_t i = 0; GetNumDimensions() > 0 && i < GetNumViews(); ++i)
200         {
201             m_ViewSizes[i] = new uint32_t[GetNumDimensions()]();
202             memcpy(m_ViewSizes[i], other.m_ViewSizes[i], GetNumDimensions() * sizeof(uint32_t));
203         }
204     }
205 }
206
207 ViewsDescriptor::ViewsDescriptor(ViewsDescriptor&& other)
208     : ViewsDescriptor()
209 {
210     swap(*this, other);
211 }
212
213 ViewsDescriptor::~ViewsDescriptor()
214 {
215     if (m_ViewSizes)
216     {
217         for (uint32_t i = 0; GetNumDimensions() > 0 && i < GetNumViews(); ++i)
218         {
219             delete[] m_ViewSizes[i];
220         }
221         delete[] m_ViewSizes;
222     }
223 }
224
225 ViewsDescriptor& ViewsDescriptor::operator=(ViewsDescriptor rhs)
226 {
227     swap(*this, rhs);
228     return *this;
229 }
230
231 uint32_t ViewsDescriptor::GetNumViews() const
232 {
233     return m_Origins.GetNumViews();
234 }
235
236 uint32_t ViewsDescriptor::GetNumDimensions() const
237 {
238     return m_Origins.GetNumDimensions();
239 }
240
241 const uint32_t* ViewsDescriptor::GetViewOrigin(uint32_t idx) const
242 {
243     return m_Origins.GetViewOrigin(idx);
244 }
245
246 Status ViewsDescriptor::SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
247 {
248     return m_Origins.SetViewOriginCoord(view, coord, value);
249 }
250
251 Status ViewsDescriptor::SetViewSize(uint32_t view, uint32_t coord, uint32_t value)
252 {
253     if (!m_ViewSizes)
254     {
255         BOOST_LOG_TRIVIAL(error) << "ViewsDescriptor::SetViewSize: invalid view sizes";
256         return Status::Failure;
257     }
258
259     if (view >= GetNumViews())
260     {
261         BOOST_LOG_TRIVIAL(error) << "ViewsDescriptor::SetViewSize: view argument:" << view <<
262                                  " is out of range";
263         return Status::Failure;
264     }
265     if (coord >= GetNumDimensions())
266     {
267         BOOST_LOG_TRIVIAL(error) << "ViewsDescriptor::SetViewSize: coord argument:" << coord <<
268                                  " is out of range";
269         return Status::Failure;
270     }
271
272     m_ViewSizes[view][coord] = value;
273     return Status::Success;
274 }
275
276 const uint32_t* ViewsDescriptor::GetViewSizes(uint32_t idx) const
277 {
278     return m_ViewSizes ? m_ViewSizes[idx] : nullptr;
279 }
280
281 void swap(OriginsDescriptor& first, OriginsDescriptor& second)
282 {
283     using std::swap;
284     swap(first.m_NumViews, second.m_NumViews);
285     swap(first.m_NumDimensions, second.m_NumDimensions);
286     swap(first.m_ViewOrigins, second.m_ViewOrigins);
287 }
288
289 void swap(ViewsDescriptor& first, ViewsDescriptor& second)
290 {
291     using std::swap;
292     swap(first.m_Origins, second.m_Origins);
293     swap(first.m_ViewSizes, second.m_ViewSizes);
294 }
295
296 }