2 * Copyright (c) 2016, 2017 ARM Limited.
4 * SPDX-License-Identifier: MIT
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:
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
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
24 #include "arm_compute/core/TensorInfo.h"
26 #include "arm_compute/core/Error.h"
27 #include "arm_compute/core/HOGInfo.h"
28 #include "arm_compute/core/Helpers.h"
29 #include "arm_compute/core/Validate.h"
31 using namespace arm_compute;
33 TensorInfo::TensorInfo()
34 : _total_size(0), _fixed_point_pos(0), _offset_first_element_in_bytes(0), _strides_in_bytes(), _num_channels(0), _tensor_shape(), _data_type(DataType::UNKNOWN), _format(Format::UNKNOWN), _is_resizable{ true },
35 _valid_region{ Coordinates(), _tensor_shape }, _padding{ 0 }
39 TensorInfo::TensorInfo(unsigned int width, unsigned int height, Format format)
40 : TensorInfo(TensorShape(width, height), format)
44 TensorInfo::TensorInfo(const TensorShape &tensor_shape, Format format)
47 init(tensor_shape, format);
50 TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, size_t fixed_point_pos)
53 init(tensor_shape, num_channels, data_type, fixed_point_pos);
56 TensorInfo::TensorInfo(const HOGInfo &hog_info, unsigned int width, unsigned int height)
59 init(hog_info, width, height);
62 void TensorInfo::init(const TensorShape &tensor_shape, Format format)
64 size_t num_channels = num_channels_from_format(format);
65 const DataType type = data_type_from_format(format);
67 init(tensor_shape, num_channels, type);
72 void TensorInfo::init(const TensorShape &tensor_shape, Format format,
73 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
74 size_t total_size_in_bytes)
76 size_t num_channels = num_channels_from_format(format);
77 const DataType type = data_type_from_format(format);
79 init(tensor_shape, num_channels, type, strides_in_bytes, offset_first_element_in_bytes, total_size_in_bytes);
84 void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, size_t fixed_point_pos)
86 ARM_COMPUTE_ERROR_ON(0 == num_channels);
88 _fixed_point_pos = fixed_point_pos;
89 _data_type = data_type;
90 _num_channels = num_channels;
91 _format = Format::UNKNOWN;
92 _tensor_shape = tensor_shape;
93 _offset_first_element_in_bytes = 0;
94 _strides_in_bytes = compute_strides(*this);
96 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
97 _total_size = _tensor_shape[idx_last_dimension] * _strides_in_bytes[idx_last_dimension];
99 Coordinates coordinates;
100 coordinates.set_num_dimensions(_tensor_shape.num_dimensions());
101 _valid_region = ValidRegion{ coordinates, _tensor_shape };
104 void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type,
105 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
106 size_t total_size_in_bytes, size_t fixed_point_pos)
108 ARM_COMPUTE_ERROR_ON(0 == num_channels);
110 _fixed_point_pos = fixed_point_pos;
111 _data_type = data_type;
112 _num_channels = num_channels;
113 _format = Format::UNKNOWN;
114 _tensor_shape = tensor_shape;
115 _offset_first_element_in_bytes = offset_first_element_in_bytes;
116 _strides_in_bytes = strides_in_bytes;
117 _total_size = total_size_in_bytes;
119 Coordinates coordinates;
120 coordinates.set_num_dimensions(_tensor_shape.num_dimensions());
121 _valid_region = ValidRegion{ coordinates, _tensor_shape };
124 void TensorInfo::init(const HOGInfo &hog_info, unsigned int width, unsigned int height)
126 // Number of cells for each block
127 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
129 // Tensor Size = (Number of horizontal blocks) * (Number of vertical blocks )
130 const Size2D num_blocks_per_img = hog_info.num_blocks_per_image(Size2D(width, height));
132 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
133 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
135 init(TensorShape(num_blocks_per_img.width, num_blocks_per_img.height), num_channels, DataType::F32);
138 size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, Format format)
140 const size_t num_channels = num_channels_from_format(format);
141 const DataType type = data_type_from_format(format);
142 size_t total_size = init_auto_padding(tensor_shape, num_channels, type);
149 size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, size_t fixed_point_pos)
151 ARM_COMPUTE_ERROR_ON(0 == num_channels);
153 _fixed_point_pos = fixed_point_pos;
154 _data_type = data_type;
155 _num_channels = num_channels;
156 _format = Format::UNKNOWN;
157 _tensor_shape = tensor_shape;
159 Coordinates coordinates;
160 coordinates.set_num_dimensions(_tensor_shape.num_dimensions());
161 _valid_region = ValidRegion{ coordinates, _tensor_shape };
168 size_t TensorInfo::init_auto_padding(const HOGInfo &hog_info, unsigned int width, unsigned int height)
170 // Number of cells for each block
171 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
173 // Tensor Size = (Number of horizontal blocks) * (Number of vertical blocks )
174 const Size2D num_blocks_per_img = hog_info.num_blocks_per_image(Size2D(width, height));
176 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
177 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
179 return init_auto_padding(TensorShape(num_blocks_per_img.width, num_blocks_per_img.height), num_channels, DataType::F32);
182 bool TensorInfo::auto_padding()
184 ARM_COMPUTE_ERROR_ON(!_is_resizable);
186 /* Some kernels compute 32 elements at the time, worst case scenario they will read 32 values after the last element */
187 const size_t extra_pad_x = 32;
188 const size_t pad_x = 4;
189 const size_t pad_y = (_tensor_shape.num_dimensions() == 1 ? 0 : 4); // Skip pad_y if the tensor has just 1 dimension
191 return extend_padding(PaddingSize(pad_y, pad_x + extra_pad_x, pad_y, pad_x));
194 std::tuple<Strides, size_t, size_t> TensorInfo::calculate_padding_requirements(const PaddingSize &padding)
196 // Calculate resulting stride for the X, Y and Z dimension
197 const size_t stride_x = element_size();
198 const size_t stride_y = (padding.left + _tensor_shape[0] + padding.right) * stride_x;
199 const size_t stride_z = _tensor_shape.num_dimensions() == 1 ? 0 : (padding.top + _tensor_shape[1] + padding.bottom) * stride_y;
201 Strides required_strides;
202 size_t required_total_size = 0;
203 const size_t required_offset_first_element = padding.left * stride_x + padding.top * stride_y;
205 switch(_tensor_shape.num_dimensions())
208 required_strides = compute_strides(*this, stride_x);
209 required_total_size = stride_y;
212 required_strides = compute_strides(*this, stride_x, stride_y);
213 required_total_size = stride_z;
217 required_strides = compute_strides(*this, stride_x, stride_y, stride_z);
219 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
221 required_total_size = _tensor_shape[idx_last_dimension] * required_strides[idx_last_dimension];
226 return std::make_tuple(required_strides, required_offset_first_element, required_total_size);
229 bool TensorInfo::extend_padding(const PaddingSize &padding)
231 ARM_COMPUTE_ERROR_ON(!_is_resizable);
233 bool updated = false;
235 if(padding.top > _padding.top)
237 _padding.top = padding.top;
241 if(padding.right > _padding.right)
243 _padding.right = padding.right;
247 if(padding.bottom > _padding.bottom)
249 _padding.bottom = padding.bottom;
253 if(padding.left > _padding.left)
255 _padding.left = padding.left;
259 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
264 void TensorInfo::set_format(Format format)
266 ARM_COMPUTE_ERROR_ON(num_channels_from_format(format) != _num_channels);
267 ARM_COMPUTE_ERROR_ON(data_type_from_format(format) != _data_type);
272 size_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
274 ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
276 size_t offset = _offset_first_element_in_bytes;
278 for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
280 offset += pos[i] * _strides_in_bytes[i];