blob: f3cd776497e5fcca7aee361498cd64f363c86f3f [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2016, 2017 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#include "arm_compute/core/TensorInfo.h"
25
26#include "arm_compute/core/Error.h"
27#include "arm_compute/core/HOGInfo.h"
28#include "arm_compute/core/Helpers.h"
Michel Iwaniec00633802017-10-12 14:14:15 +010029#include "arm_compute/core/TensorInfo.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010030#include "arm_compute/core/Validate.h"
31
32using namespace arm_compute;
33
34TensorInfo::TensorInfo()
35 : _total_size(0), _fixed_point_position(0), _offset_first_element_in_bytes(0), _strides_in_bytes(), _num_channels(0), _tensor_shape(), _data_type(DataType::UNKNOWN), _format(Format::UNKNOWN),
Michel Iwaniec00633802017-10-12 14:14:15 +010036 _is_resizable{ true }, _valid_region{ Coordinates(), _tensor_shape }, _padding{ 0 }, _quantization_info()
Anthony Barbier6ff3b192017-09-04 18:44:23 +010037{
38}
39
40TensorInfo::TensorInfo(const ITensorInfo &info)
41 : TensorInfo()
42{
43 _total_size = info.total_size();
44 _fixed_point_position = info.fixed_point_position();
45 _offset_first_element_in_bytes = info.offset_first_element_in_bytes();
46 _strides_in_bytes = info.strides_in_bytes();
47 _num_channels = info.num_channels();
48 _tensor_shape = info.tensor_shape();
49 _data_type = info.data_type();
50 _format = info.format();
51 _is_resizable = info.is_resizable();
52 _valid_region = info.valid_region();
53 _padding = info.padding();
54}
55
56TensorInfo::TensorInfo(Format format)
57 : TensorInfo(TensorShape(), format)
58{
59}
60
61TensorInfo::TensorInfo(unsigned int width, unsigned int height, Format format)
62 : TensorInfo(TensorShape(width, height), format)
63{
64}
65
66TensorInfo::TensorInfo(const TensorShape &tensor_shape, Format format)
67 : TensorInfo()
68{
69 init(tensor_shape, format);
70}
71
72TensorInfo::TensorInfo(size_t num_channels, DataType data_type, size_t fixed_point_position)
73 : TensorInfo()
74{
75 init(TensorShape(), num_channels, data_type, fixed_point_position);
76}
77
78TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, int fixed_point_position)
79 : TensorInfo()
80{
81 init(tensor_shape, num_channels, data_type, fixed_point_position);
82}
83
Michel Iwaniec00633802017-10-12 14:14:15 +010084TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, QuantizationInfo quantization_info)
85 : TensorInfo()
86{
87 init(tensor_shape, num_channels, data_type, 0);
88 _quantization_info = quantization_info;
89}
90
Anthony Barbier6ff3b192017-09-04 18:44:23 +010091TensorInfo::TensorInfo(const HOGInfo &hog_info, unsigned int width, unsigned int height)
92 : TensorInfo()
93{
94 init(hog_info, width, height);
95}
96
97void TensorInfo::init(Format format)
98{
99 init(TensorShape(), format);
100}
101
102void TensorInfo::init(const TensorShape &tensor_shape, Format format)
103{
104 size_t num_channels = num_channels_from_format(format);
105 const DataType type = data_type_from_format(format);
106
107 init(tensor_shape, num_channels, type);
108
109 _format = format;
110}
111
112void TensorInfo::init(const TensorShape &tensor_shape, Format format,
113 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
114 size_t total_size_in_bytes)
115{
116 size_t num_channels = num_channels_from_format(format);
117 const DataType type = data_type_from_format(format);
118
119 init(tensor_shape, num_channels, type, strides_in_bytes, offset_first_element_in_bytes, total_size_in_bytes);
120
121 _format = format;
122}
123
124void TensorInfo::init(size_t num_channels, DataType data_type, size_t fixed_point_position)
125{
126 init(TensorShape(), num_channels, data_type, fixed_point_position);
127}
128
129void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, int fixed_point_position)
130{
131 ARM_COMPUTE_ERROR_ON(num_channels == 0);
132 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
133 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
134
135 _fixed_point_position = fixed_point_position;
136 _data_type = data_type;
137 _num_channels = num_channels;
138 _format = Format::UNKNOWN;
139
140 set_tensor_shape(tensor_shape);
141}
142
143void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type,
144 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
145 size_t total_size_in_bytes, int fixed_point_position)
146{
147 ARM_COMPUTE_ERROR_ON(num_channels == 0);
148 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
149 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
150
151 _fixed_point_position = fixed_point_position;
152 _data_type = data_type;
153 _num_channels = num_channels;
154 _format = Format::UNKNOWN;
155 _tensor_shape = tensor_shape;
156 _offset_first_element_in_bytes = offset_first_element_in_bytes;
157 _strides_in_bytes = strides_in_bytes;
158 _total_size = total_size_in_bytes;
159
160 Coordinates coordinates;
161 coordinates.set_num_dimensions(_tensor_shape.num_dimensions());
162 _valid_region = ValidRegion{ coordinates, _tensor_shape };
163}
164
165void TensorInfo::init(const HOGInfo &hog_info, unsigned int width, unsigned int height)
166{
167 // Number of cells for each block
168 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
169
170 // Tensor Size = (Number of horizontal blocks) * (Number of vertical blocks )
171 const Size2D num_blocks_per_img = hog_info.num_blocks_per_image(Size2D(width, height));
172
173 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
174 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
175
176 init(TensorShape(num_blocks_per_img.width, num_blocks_per_img.height), num_channels, DataType::F32);
177}
178
179size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, Format format)
180{
181 const size_t num_channels = num_channels_from_format(format);
182 const DataType type = data_type_from_format(format);
183 size_t total_size = init_auto_padding(tensor_shape, num_channels, type);
184
185 _format = format;
186
187 return total_size;
188}
189
190size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, int fixed_point_position)
191{
192 ARM_COMPUTE_ERROR_ON(num_channels == 0);
193 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
194 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
195
196 _fixed_point_position = fixed_point_position;
197 _data_type = data_type;
198 _num_channels = num_channels;
199 _format = Format::UNKNOWN;
200 _tensor_shape = tensor_shape;
201
202 Coordinates coordinates;
203 coordinates.set_num_dimensions(_tensor_shape.num_dimensions());
204 _valid_region = ValidRegion{ coordinates, _tensor_shape };
205
206 auto_padding();
207
208 return _total_size;
209}
210
211size_t TensorInfo::init_auto_padding(const HOGInfo &hog_info, unsigned int width, unsigned int height)
212{
213 // Number of cells for each block
214 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
215
216 // Tensor Size = (Number of horizontal blocks) * (Number of vertical blocks )
217 const Size2D num_blocks_per_img = hog_info.num_blocks_per_image(Size2D(width, height));
218
219 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
220 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
221
222 return init_auto_padding(TensorShape(num_blocks_per_img.width, num_blocks_per_img.height), num_channels, DataType::F32);
223}
224
225bool TensorInfo::auto_padding()
226{
227 ARM_COMPUTE_ERROR_ON(!_is_resizable);
228
229 // Some kernels compute 32 elements at the time, worst case scenario they
230 // will read 32 values after the last element
231 const size_t extra_pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 32;
232 const size_t pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 4;
233 const size_t pad_y = _tensor_shape.num_dimensions() < 2 ? 0 : 4;
234
235 return extend_padding(PaddingSize(pad_y, pad_x + extra_pad_x, pad_y, pad_x));
236}
237
238std::tuple<Strides, size_t, size_t> TensorInfo::calculate_padding_requirements(const PaddingSize &padding)
239{
240 // Calculate resulting stride for the X, Y and Z dimension
241 const size_t stride_x = element_size();
242 const size_t stride_y = (padding.left + _tensor_shape[0] + padding.right) * stride_x;
243 const size_t stride_z = (padding.top + _tensor_shape[1] + padding.bottom) * stride_y;
244
245 Strides required_strides;
246 size_t required_total_size = 0;
247 const size_t required_offset_first_element = padding.left * stride_x + padding.top * stride_y;
248
249 switch(_tensor_shape.num_dimensions())
250 {
251 case 0:
252 {
253 if(_tensor_shape.total_size() > 0)
254 {
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100255 required_strides = Strides(stride_x, stride_x);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100256 required_total_size = stride_z;
257 }
258 break;
259 }
260 case 1:
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100261 required_strides = compute_strides(*this, stride_x, stride_y);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100262 required_total_size = stride_z;
263 break;
264 case 2:
265 required_strides = compute_strides(*this, stride_x, stride_y);
266 required_total_size = stride_z;
267 break;
268 default:
269 {
270 required_strides = compute_strides(*this, stride_x, stride_y, stride_z);
271
272 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
273
274 required_total_size = _tensor_shape[idx_last_dimension] * required_strides[idx_last_dimension];
275 break;
276 }
277 }
278
279 return std::make_tuple(required_strides, required_offset_first_element, required_total_size);
280}
281
282bool TensorInfo::extend_padding(const PaddingSize &padding)
283{
284 ARM_COMPUTE_ERROR_ON(!_is_resizable);
285
286 bool updated = false;
287
288 if(padding.top > _padding.top)
289 {
290 _padding.top = padding.top;
291 updated = true;
292 }
293
294 if(padding.right > _padding.right)
295 {
296 _padding.right = padding.right;
297 updated = true;
298 }
299
300 if(padding.bottom > _padding.bottom)
301 {
302 _padding.bottom = padding.bottom;
303 updated = true;
304 }
305
306 if(padding.left > _padding.left)
307 {
308 _padding.left = padding.left;
309 updated = true;
310 }
311
312 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
313
314 return updated;
315}
316
317void TensorInfo::set_data_type(DataType data_type)
318{
319 _data_type = data_type;
320 _format = Format::UNKNOWN;
321}
322
323void TensorInfo::set_num_channels(int num_channels)
324{
325 _num_channels = num_channels;
326 _format = Format::UNKNOWN;
327}
328
329void TensorInfo::set_format(Format format)
330{
331 _format = format;
332
333 if(_data_type == DataType::UNKNOWN)
334 {
335 _num_channels = num_channels_from_format(format);
336 _data_type = data_type_from_format(format);
337 }
338 else
339 {
340 ARM_COMPUTE_ERROR_ON(num_channels_from_format(format) != _num_channels);
341 ARM_COMPUTE_ERROR_ON(data_type_from_format(format) != _data_type);
342 }
343}
344
345void TensorInfo::set_tensor_shape(TensorShape shape)
346{
347 _tensor_shape = shape;
348 _offset_first_element_in_bytes = 0;
349 _strides_in_bytes = compute_strides(*this);
350
351 if(_tensor_shape.num_dimensions() == 0)
352 {
353 _total_size = _strides_in_bytes[0];
354 }
355 else
356 {
357 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
358 _total_size = _tensor_shape[idx_last_dimension] * _strides_in_bytes[idx_last_dimension];
359 }
360
361 Coordinates coordinates;
362 coordinates.set_num_dimensions(_tensor_shape.num_dimensions());
363 _valid_region = ValidRegion{ coordinates, _tensor_shape };
364}
365
366void TensorInfo::set_fixed_point_position(int fixed_point_position)
367{
368 ARM_COMPUTE_ERROR_ON(_data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
369 ARM_COMPUTE_ERROR_ON(_data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
370 _fixed_point_position = fixed_point_position;
371}
372
373size_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
374{
375 ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
376
377 size_t offset = _offset_first_element_in_bytes;
378
379 for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
380 {
381 offset += pos[i] * _strides_in_bytes[i];
382 }
383
384 return offset;
385}