• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017-2019 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef ARM_COMPUTE_DIMENSIONS_H
25 #define ARM_COMPUTE_DIMENSIONS_H
26 
27 #include "arm_compute/core/Error.h"
28 
29 #include <algorithm>
30 #include <array>
31 #include <functional>
32 #include <numeric>
33 
34 namespace arm_compute
35 {
36 /** Constant value used to indicate maximum dimensions of a Window, TensorShape and Coordinates */
37 constexpr size_t MAX_DIMS = 6;
38 
39 /** Dimensions with dimensionality */
40 template <typename T>
41 class Dimensions
42 {
43 public:
44     /** Number of dimensions the tensor has */
45     static constexpr size_t num_max_dimensions = MAX_DIMS;
46 
47     /** Constructor to initialize the tensor shape.
48      *
49      * @param[in] dims Values to initialize the dimensions.
50      */
51     template <typename... Ts>
Dimensions(Ts...dims)52     explicit Dimensions(Ts... dims)
53         : _id{ { static_cast<T>(dims)... } }, _num_dimensions{ sizeof...(dims) }
54     {
55     }
56 
57     /** Allow instances of this class to be copy constructed */
58     Dimensions(const Dimensions &) = default;
59 
60     /** Allow instances of this class to be copied */
61     Dimensions &operator=(const Dimensions &) = default;
62 
63     /** Allow instances of this class to be move constructed */
64     Dimensions(Dimensions &&) = default;
65 
66     /** Allow instances of this class to be moved */
67     Dimensions &operator=(Dimensions &&) = default;
68 
69     /** Accessor to set the value of one of the dimensions.
70      *
71      * @param[in] dimension Dimension for which the value is set.
72      * @param[in] value     Value to be set for the dimension.
73      */
set(size_t dimension,T value)74     void set(size_t dimension, T value)
75     {
76         ARM_COMPUTE_ERROR_ON(dimension >= num_max_dimensions);
77         _id[dimension]  = value;
78         _num_dimensions = std::max(_num_dimensions, dimension + 1);
79     }
80     /** Alias to access the size of the first dimension */
x()81     T x() const
82     {
83         return _id[0];
84     }
85     /** Alias to access the size of the second dimension */
y()86     T y() const
87     {
88         return _id[1];
89     }
90     /** Alias to access the size of the third dimension */
z()91     T z() const
92     {
93         return _id[2];
94     }
95     /** Generic accessor to get the size of any dimension
96      *
97      * @note Precondition: dimension < Dimensions::num_max_dimensions
98      *
99      * @param[in] dimension Dimension of the wanted size
100      *
101      * @return The size of the requested dimension.
102      */
103     const T &operator[](size_t dimension) const
104     {
105         ARM_COMPUTE_ERROR_ON(dimension >= num_max_dimensions);
106         return _id[dimension];
107     }
108     /** Generic accessor to get the size of any dimension
109      *
110      * @note Precondition: dimension < Dimensions::num_max_dimensions
111      *
112      * @param[in] dimension Dimension of the wanted size
113      *
114      * @return The size of the requested dimension.
115      */
116     T &operator[](size_t dimension)
117     {
118         ARM_COMPUTE_ERROR_ON(dimension >= num_max_dimensions);
119         return _id[dimension];
120     }
121     /** Returns the effective dimensionality of the tensor */
num_dimensions()122     unsigned int num_dimensions() const
123     {
124         return _num_dimensions;
125     }
126 
127     /** Set number of dimensions */
set_num_dimensions(size_t num_dimensions)128     void set_num_dimensions(size_t num_dimensions)
129     {
130         _num_dimensions = num_dimensions;
131     }
132 
133     /** Collapse dimensions.
134      *
135      * @param[in] n     Number of dimensions to collapse into @p first.
136      * @param[in] first Dimensions into which the following @p n are collapsed.
137      */
138     void collapse(const size_t n, const size_t first = 0)
139     {
140         ARM_COMPUTE_ERROR_ON(first + n > _id.size());
141 
142         const size_t last = std::min(_num_dimensions, first + n);
143 
144         if(last > (first + 1))
145         {
146             // Collapse dimensions into the first
147             _id[first] = std::accumulate(&_id[first], &_id[last], 1, std::multiplies<T>());
148             // Shift the remaining dimensions down
149             std::copy(&_id[last], &_id[_num_dimensions], &_id[first + 1]);
150             // Reduce the number of dimensions
151             const size_t old_num_dimensions = _num_dimensions;
152             _num_dimensions -= last - first - 1;
153             // Fill the now empty dimensions with zero
154             std::fill(&_id[_num_dimensions], &_id[old_num_dimensions], 0);
155         }
156     }
157 
158     /** Collapse dimensions starting from a given point
159      *
160      * @param[in] start Starting point of collapsing dimensions
161      */
collapse_from(size_t start)162     void collapse_from(size_t start)
163     {
164         ARM_COMPUTE_ERROR_ON(start > num_dimensions());
165 
166         collapse(num_dimensions() - start, start);
167     }
168 
169     /** Remove dimension of a given index
170      *
171      * @note If index is greater than the number of dimensions no operation is performed
172      *
173      * @param[in] idx Dimension index to remove
174      */
remove(size_t idx)175     void remove(size_t idx)
176     {
177         ARM_COMPUTE_ERROR_ON(_num_dimensions < 1);
178         if(idx >= _num_dimensions)
179         {
180             return;
181         }
182 
183         std::copy(_id.begin() + idx + 1, _id.end(), _id.begin() + idx);
184         _num_dimensions--;
185 
186         // Make sure all empty dimensions are filled with 0
187         std::fill(_id.begin() + _num_dimensions, _id.end(), 0);
188     }
189 
190     /** Returns a read/write iterator that points to the first element in the dimension array.
191      *
192      * @return an iterator.
193      */
begin()194     typename std::array<T, num_max_dimensions>::iterator begin()
195     {
196         return _id.begin();
197     }
198     /** Returns a read-only (constant) iterator that points to the first element in the dimension array.
199      *
200      * @return an iterator.
201      */
begin()202     typename std::array<T, num_max_dimensions>::const_iterator begin() const
203     {
204         return _id.begin();
205     }
206     /** Returns a read-only (constant) iterator that points to the first element in the dimension array.
207      *
208      * @return an iterator.
209      */
cbegin()210     typename std::array<T, num_max_dimensions>::const_iterator cbegin() const
211     {
212         return begin();
213     }
214     /** Returns a read/write iterator that points one past the last element in the dimension array.
215      *
216      * @return an iterator.
217      */
end()218     typename std::array<T, num_max_dimensions>::iterator end()
219     {
220         return _id.end();
221     }
222     /** Returns a read-only (constant) iterator that points one past the last element in the dimension array.
223      *
224      * @return an iterator.
225      */
end()226     typename std::array<T, num_max_dimensions>::const_iterator end() const
227     {
228         return _id.end();
229     }
230     /** Returns a read-only (constant) iterator that points one past the last element in the dimension array.
231      *
232      * @return an iterator.
233      */
cend()234     typename std::array<T, num_max_dimensions>::const_iterator cend() const
235     {
236         return end();
237     }
238 
239 protected:
240     /** Protected destructor. */
241     ~Dimensions() = default;
242 
243     std::array<T, num_max_dimensions> _id;
244     size_t _num_dimensions{ 0 };
245 };
246 
247 /** Check that given dimensions are equal.
248  *
249  * @param[in] lhs Left-hand side Dimensions.
250  * @param[in] rhs Right-hand side Dimensions.
251  *
252  * @return True if the given dimensions are equal.
253  */
254 template <typename T>
255 inline bool operator==(const Dimensions<T> &lhs, const Dimensions<T> &rhs)
256 {
257     return ((lhs.num_dimensions() == rhs.num_dimensions()) && std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()));
258 }
259 /** Check that given dimensions are not equal.
260  *
261  * @param[in] lhs Left-hand side Dimensions.
262  * @param[in] rhs Right-hand side Dimensions.
263  *
264  * @return True if the given dimensions are not equal.
265  */
266 template <typename T>
267 inline bool operator!=(const Dimensions<T> &lhs, const Dimensions<T> &rhs)
268 {
269     return !(lhs == rhs);
270 }
271 }
272 #endif /*ARM_COMPUTE_DIMENSIONS_H*/
273