blob: c6a7db4f96ade65fead8a80cfb2fb8d496654730 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +00002 * Copyright (c) 2016-2018 ARM Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
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_HELPERS_H__
25#define __ARM_COMPUTE_HELPERS_H__
26
27#include "arm_compute/core/CL/CLTypes.h"
28#include "arm_compute/core/Coordinates.h"
Georgios Pinitas583137c2017-08-31 18:12:42 +010029#include "arm_compute/core/Error.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010030#include "arm_compute/core/IAccessWindow.h"
31#include "arm_compute/core/Steps.h"
32#include "arm_compute/core/Strides.h"
33#include "arm_compute/core/TensorShape.h"
34#include "arm_compute/core/Types.h"
35#include "arm_compute/core/Window.h"
Georgios Pinitas8795ffb2017-12-01 16:13:40 +000036#include "arm_compute/core/utils/misc/utility.h"
Georgios Pinitas583137c2017-08-31 18:12:42 +010037
Anthony Barbier6ff3b192017-09-04 18:44:23 +010038#include <array>
39#include <cstddef>
40#include <cstdint>
41#include <memory>
42#include <tuple>
43#include <type_traits>
44#include <utility>
45
46namespace arm_compute
47{
48class IKernel;
49class ITensor;
50class ITensorInfo;
51
Anthony Barbier6ff3b192017-09-04 18:44:23 +010052template <typename T>
53struct enable_bitwise_ops
54{
55 static constexpr bool value = false;
56};
57
58template <typename T>
59typename std::enable_if<enable_bitwise_ops<T>::value, T>::type operator&(T lhs, T rhs)
60{
61 using underlying_type = typename std::underlying_type<T>::type;
62 return static_cast<T>(static_cast<underlying_type>(lhs) & static_cast<underlying_type>(rhs));
63}
64
65namespace traits
66{
67/** Check if a type T is contained in a tuple Tuple of types */
68template <typename T, typename Tuple>
69struct is_contained;
70
71template <typename T>
72struct is_contained<T, std::tuple<>> : std::false_type
73{
74};
75
76template <typename T, typename... Ts>
77struct is_contained<T, std::tuple<T, Ts...>> : std::true_type
78{
79};
80
81template <typename T, typename U, typename... Ts>
82struct is_contained<T, std::tuple<U, Ts...>> : is_contained<T, std::tuple<Ts...>>
83{
84};
85}
86
87/** Computes bilinear interpolation using the pointer to the top-left pixel and the pixel's distance between
Georgios Pinitas583137c2017-08-31 18:12:42 +010088 * the real coordinates and the smallest following integer coordinates. Input must be in single channel format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010089 *
Georgios Pinitas583137c2017-08-31 18:12:42 +010090 * @param[in] pixel_ptr Pointer to the top-left pixel value of a single channel input.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010091 * @param[in] stride Stride to access the bottom-left and bottom-right pixel values
92 * @param[in] dx Pixel's distance between the X real coordinate and the smallest X following integer
93 * @param[in] dy Pixel's distance between the Y real coordinate and the smallest Y following integer
94 *
95 * @note dx and dy must be in the range [0, 1.0]
96 *
97 * @return The bilinear interpolated pixel value
98 */
Georgios Pinitas583137c2017-08-31 18:12:42 +010099template <typename T>
100inline T delta_bilinear_c1(const T *pixel_ptr, size_t stride, float dx, float dy)
101{
102 ARM_COMPUTE_ERROR_ON(pixel_ptr == nullptr);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100103
Georgios Pinitas583137c2017-08-31 18:12:42 +0100104 const float dx1 = 1.0f - dx;
105 const float dy1 = 1.0f - dy;
106
107 const T a00 = *pixel_ptr;
108 const T a01 = *(pixel_ptr + 1);
109 const T a10 = *(pixel_ptr + stride);
110 const T a11 = *(pixel_ptr + stride + 1);
111
112 const float w1 = dx1 * dy1;
113 const float w2 = dx * dy1;
114 const float w3 = dx1 * dy;
115 const float w4 = dx * dy;
116
117 return static_cast<T>(a00 * w1 + a01 * w2 + a10 * w3 + a11 * w4);
118}
119
Anthony Barbier9a33b542017-12-12 22:08:59 +0000120/** Computes linear interpolation using the pointer to the top pixel and the pixel's distance between
121 * the real coordinates and the smallest following integer coordinates. Input must be in single channel format.
122 *
123 * @param[in] pixel_ptr Pointer to the top pixel value of a single channel input.
124 * @param[in] stride Stride to access the bottom pixel value
125 * @param[in] dy Pixel's distance between the Y real coordinate and the smallest Y following integer
126 *
127 * @note dy must be in the range [0, 1.0]
128 *
129 * @return The linear interpolated pixel value
130 */
131template <typename T>
132inline T delta_linear_c1_y(const T *pixel_ptr, size_t stride, float dy)
133{
134 ARM_COMPUTE_ERROR_ON(pixel_ptr == nullptr);
135
136 const float dy1 = 1.0f - dy;
137
138 const T a00 = *pixel_ptr;
139 const T a10 = *(pixel_ptr + stride);
140
141 const float w1 = dy1;
142 const float w3 = dy;
143
144 return static_cast<T>(a00 * w1 + a10 * w3);
145}
146/** Computes linear interpolation using the pointer to the left pixel and the pixel's distance between
147 * the real coordinates and the smallest following integer coordinates. Input must be in single channel format.
148 *
149 * @param[in] pixel_ptr Pointer to the left pixel value of a single channel input.
150 * @param[in] dx Pixel's distance between the X real coordinate and the smallest X following integer
151 *
152 * @note dx must be in the range [0, 1.0]
153 *
154 * @return The linear interpolated pixel value
155 */
156template <typename T>
157inline T delta_linear_c1_x(const T *pixel_ptr, float dx)
158{
159 ARM_COMPUTE_ERROR_ON(pixel_ptr == nullptr);
160
161 const T a00 = *pixel_ptr;
162 const T a01 = *(pixel_ptr + 1);
163
164 const float dx1 = 1.0f - dx;
165
166 const float w1 = dx1;
167 const float w2 = dx;
168
169 return static_cast<T>(a00 * w1 + a01 * w2);
170}
Georgios Pinitas583137c2017-08-31 18:12:42 +0100171/** Return the pixel at (x,y) using bilinear interpolation.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100172 *
173 * @warning Only works if the iterator was created with an IImage
174 *
Georgios Pinitas583137c2017-08-31 18:12:42 +0100175 * @param[in] first_pixel_ptr Pointer to the first pixel of a single channel input.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100176 * @param[in] stride Stride in bytes of the image;
177 * @param[in] x X position of the wanted pixel
178 * @param[in] y Y position of the wanted pixel
179 *
180 * @return The pixel at (x, y) using bilinear interpolation.
181 */
Georgios Pinitas583137c2017-08-31 18:12:42 +0100182template <typename T>
183inline T pixel_bilinear_c1(const T *first_pixel_ptr, size_t stride, float x, float y)
184{
185 ARM_COMPUTE_ERROR_ON(first_pixel_ptr == nullptr);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100186
Georgios Pinitas583137c2017-08-31 18:12:42 +0100187 const int32_t xi = std::floor(x);
188 const int32_t yi = std::floor(y);
189
190 const float dx = x - xi;
191 const float dy = y - yi;
192
193 return delta_bilinear_c1(first_pixel_ptr + xi + yi * stride, stride, dx, dy);
194}
195
196/** Return the pixel at (x,y) using bilinear interpolation by clamping when out of borders. The image must be single channel input
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100197 *
198 * @warning Only works if the iterator was created with an IImage
199 *
Georgios Pinitas583137c2017-08-31 18:12:42 +0100200 * @param[in] first_pixel_ptr Pointer to the first pixel of a single channel image.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100201 * @param[in] stride Stride in bytes of the image
202 * @param[in] width Width of the image
203 * @param[in] height Height of the image
204 * @param[in] x X position of the wanted pixel
205 * @param[in] y Y position of the wanted pixel
206 *
207 * @return The pixel at (x, y) using bilinear interpolation.
208 */
Georgios Pinitas583137c2017-08-31 18:12:42 +0100209template <typename T>
210inline uint8_t pixel_bilinear_c1_clamp(const T *first_pixel_ptr, size_t stride, size_t width, size_t height, float x, float y)
211{
212 ARM_COMPUTE_ERROR_ON(first_pixel_ptr == nullptr);
213
214 x = std::max(-1.f, std::min(x, static_cast<float>(width)));
215 y = std::max(-1.f, std::min(y, static_cast<float>(height)));
216
217 const float xi = std::floor(x);
218 const float yi = std::floor(y);
219
220 const float dx = x - xi;
221 const float dy = y - yi;
222
Anthony Barbier9a33b542017-12-12 22:08:59 +0000223 if(dx == 0.0f)
224 {
225 if(dy == 0.0f)
226 {
227 return static_cast<T>(first_pixel_ptr[static_cast<int32_t>(xi) + static_cast<int32_t>(yi) * stride]);
228 }
229 return delta_linear_c1_y(first_pixel_ptr + static_cast<int32_t>(xi) + static_cast<int32_t>(yi) * stride, stride, dy);
230 }
231 if(dy == 0.0f)
232 {
233 return delta_linear_c1_x(first_pixel_ptr + static_cast<int32_t>(xi) + static_cast<int32_t>(yi) * stride, dx);
234 }
Georgios Pinitas583137c2017-08-31 18:12:42 +0100235 return delta_bilinear_c1(first_pixel_ptr + static_cast<int32_t>(xi) + static_cast<int32_t>(yi) * stride, stride, dx, dy);
236}
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100237
238/** Return the pixel at (x,y) using area interpolation by clamping when out of borders. The image must be single channel U8
239 *
240 * @note The interpolation area depends on the width and height ration of the input and output images
241 * @note Currently average of the contributing pixels is calculated
242 *
243 * @param[in] first_pixel_ptr Pointer to the first pixel of a single channel U8 image.
244 * @param[in] stride Stride in bytes of the image
245 * @param[in] width Width of the image
246 * @param[in] height Height of the image
247 * @param[in] wr Width ratio among the input image width and output image width.
248 * @param[in] hr Height ratio among the input image height and output image height.
249 * @param[in] x X position of the wanted pixel
250 * @param[in] y Y position of the wanted pixel
251 *
252 * @return The pixel at (x, y) using area interpolation.
253 */
254inline uint8_t pixel_area_c1u8_clamp(const uint8_t *first_pixel_ptr, size_t stride, size_t width, size_t height, float wr, float hr, int x, int y);
255
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100256/** Iterator updated by @ref execute_window_loop for each window element */
257class Iterator
258{
259public:
260 /** Default constructor to create an empty iterator */
261 constexpr Iterator();
262 /** Create a container iterator for the metadata and allocation contained in the ITensor
263 *
264 * @param[in] tensor The tensor to associate to the iterator.
265 * @param[in] window The window which will be used to iterate over the tensor.
266 */
267 Iterator(const ITensor *tensor, const Window &window);
268
269 /** Increment the iterator along the specified dimension of the step value associated to the dimension.
270 *
271 * @warning It is the caller's responsibility to call increment(dimension+1) when reaching the end of a dimension, the iterator will not check for overflow.
272 *
273 * @note When incrementing a dimension 'n' the coordinates of all the dimensions in the range (0,n-1) are reset. For example if you iterate over a 2D image, everytime you change row (dimension 1), the iterator for the width (dimension 0) is reset to its start.
274 *
275 * @param[in] dimension Dimension to increment
276 */
277 void increment(size_t dimension);
278
279 /** Return the offset in bytes from the first element to the current position of the iterator
280 *
281 * @return The current position of the iterator in bytes relative to the first element.
282 */
283 constexpr int offset() const;
284
285 /** Return a pointer to the current pixel.
286 *
287 * @warning Only works if the iterator was created with an ITensor.
288 *
289 * @return equivalent to buffer() + offset()
290 */
291 constexpr uint8_t *ptr() const;
292
293 /** Move the iterator back to the beginning of the specified dimension.
294 *
295 * @param[in] dimension Dimension to reset
296 */
297 void reset(size_t dimension);
298
299private:
300 uint8_t *_ptr;
301
302 class Dimension
303 {
304 public:
305 constexpr Dimension()
306 : _dim_start(0), _stride(0)
307 {
308 }
309
310 int _dim_start;
311 int _stride;
312 };
313
314 std::array<Dimension, Coordinates::num_max_dimensions> _dims;
315};
316
317/** Iterate through the passed window, automatically adjusting the iterators and calling the lambda_functino for each element.
318 * It passes the x and y positions to the lambda_function for each iteration
319 *
320 * @param[in] w Window to iterate through.
321 * @param[in] lambda_function The function of type void(function)( const Coordinates & id ) to call at each iteration.
322 * Where id represents the absolute coordinates of the item to process.
323 * @param[in,out] iterators Tensor iterators which will be updated by this function before calling lambda_function.
324 */
325template <typename L, typename... Ts>
326inline void execute_window_loop(const Window &w, L &&lambda_function, Ts &&... iterators);
327
328/** Update window and padding size for each of the access patterns.
329 *
330 * First the window size is reduced based on all access patterns that are not
331 * allowed to modify the padding of the underlying tensor. Then the padding of
332 * the remaining tensors is increased to match the window.
333 *
334 * @param[in] win Window that is used by the kernel.
335 * @param[in] patterns Access patterns used to calculate the final window and padding.
336 *
337 * @return True if the window has been changed. Changes to the padding do not
338 * influence the returned value.
339 */
340template <typename... Ts>
341bool update_window_and_padding(Window &win, Ts &&... patterns)
342{
343 bool window_changed = false;
344
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000345 utility::for_each([&](const IAccessWindow & w)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100346 {
347 window_changed |= w.update_window_if_needed(win);
348 },
349 patterns...);
350
351 bool padding_changed = false;
352
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000353 utility::for_each([&](IAccessWindow & w)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100354 {
355 padding_changed |= w.update_padding_if_needed(win);
356 },
357 patterns...);
358
359 return window_changed;
360}
361
362/** Calculate the maximum window for a given tensor shape and border setting
363 *
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000364 * @param[in] valid_region Valid region object defining the shape of the tensor space for which the window is created.
365 * @param[in] steps (Optional) Number of elements processed for each step.
366 * @param[in] skip_border (Optional) If true exclude the border region from the window.
367 * @param[in] border_size (Optional) Border size.
368 *
369 * @return The maximum window the kernel can be executed on.
370 */
371Window calculate_max_window(const ValidRegion &valid_region, const Steps &steps = Steps(), bool skip_border = false, BorderSize border_size = BorderSize());
372
373/** Calculate the maximum window for a given tensor shape and border setting
374 *
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100375 * @param[in] info Tensor info object defining the shape of the object for which the window is created.
376 * @param[in] steps (Optional) Number of elements processed for each step.
377 * @param[in] skip_border (Optional) If true exclude the border region from the window.
378 * @param[in] border_size (Optional) Border size.
379 *
380 * @return The maximum window the kernel can be executed on.
381 */
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000382inline Window calculate_max_window(const ITensorInfo &info, const Steps &steps = Steps(), bool skip_border = false, BorderSize border_size = BorderSize())
383{
384 return calculate_max_window(info.valid_region(), steps, skip_border, border_size);
385}
386
387/** Calculate the maximum window used by a horizontal kernel for a given tensor shape and border setting
388 *
389 * @param[in] valid_region Valid region object defining the shape of the tensor space for which the window is created.
390 * @param[in] steps (Optional) Number of elements processed for each step.
391 * @param[in] skip_border (Optional) If true exclude the border region from the window.
392 * @param[in] border_size (Optional) Border size. The border region will be excluded from the window.
393 *
394 * @return The maximum window the kernel can be executed on.
395 */
396Window calculate_max_window_horizontal(const ValidRegion &valid_region, const Steps &steps = Steps(), bool skip_border = false, BorderSize border_size = BorderSize());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100397
398/** Calculate the maximum window used by a horizontal kernel for a given tensor shape and border setting
399 *
400 * @param[in] info Tensor info object defining the shape of the object for which the window is created.
401 * @param[in] steps (Optional) Number of elements processed for each step.
402 * @param[in] skip_border (Optional) If true exclude the border region from the window.
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000403 * @param[in] border_size (Optional) Border size.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100404 *
405 * @return The maximum window the kernel can be executed on.
406 */
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000407inline Window calculate_max_window_horizontal(const ITensorInfo &info, const Steps &steps = Steps(), bool skip_border = false, BorderSize border_size = BorderSize())
408{
409 return calculate_max_window_horizontal(info.valid_region(), steps, skip_border, border_size);
410}
411
412/** Calculate the maximum window for a given tensor shape and border setting. The window will also includes the border.
413 *
414 * @param[in] valid_region Valid region object defining the shape of the tensor space for which the window is created.
415 * @param[in] steps (Optional) Number of elements processed for each step.
416 * @param[in] border_size (Optional) Border size. The border region will be included in the window.
417 *
418 * @return The maximum window the kernel can be executed on.
419 */
420Window calculate_max_enlarged_window(const ValidRegion &valid_region, const Steps &steps = Steps(), BorderSize border_size = BorderSize());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100421
422/** Calculate the maximum window for a given tensor shape and border setting. The window will also includes the border.
423 *
424 * @param[in] info Tensor info object defining the shape of the object for which the window is created.
425 * @param[in] steps (Optional) Number of elements processed for each step.
426 * @param[in] border_size (Optional) Border size. The border region will be included in the window.
427 *
428 * @return The maximum window the kernel can be executed on.
429 */
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000430inline Window calculate_max_enlarged_window(const ITensorInfo &info, const Steps &steps = Steps(), BorderSize border_size = BorderSize())
431{
432 return calculate_max_enlarged_window(info.valid_region(), steps, border_size);
433}
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100434
435/** Intersect multiple valid regions.
436 *
437 * @param[in] regions Valid regions.
438 *
439 * @return Intersection of all regions.
440 */
441template <typename... Ts>
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000442ValidRegion intersect_valid_regions(const Ts &... regions)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100443{
444 auto intersect = [](const ValidRegion & r1, const ValidRegion & r2) -> ValidRegion
445 {
446 ValidRegion region;
447
448 for(size_t d = 0; d < std::min(r1.anchor.num_dimensions(), r2.anchor.num_dimensions()); ++d)
449 {
450 region.anchor.set(d, std::max(r1.anchor[d], r2.anchor[d]));
451 }
452
453 for(size_t d = 0; d < std::min(r1.shape.num_dimensions(), r2.shape.num_dimensions()); ++d)
454 {
455 region.shape.set(d, std::min(r1.shape[d], r2.shape[d]));
456 }
457
458 return region;
459 };
460
Diego Lopez Recas490b3d82017-12-19 15:42:25 +0000461 return utility::foldl(intersect, regions...);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100462}
463
464/** Create a strides object based on the provided strides and the tensor dimensions.
465 *
466 * @param[in] info Tensor info object providing the shape of the tensor for unspecified strides.
467 * @param[in] stride_x Stride to be used in X dimension (in bytes).
468 * @param[in] fixed_strides Strides to be used in higher dimensions starting at Y (in bytes).
469 *
470 * @return Strides object based on the specified strides. Missing strides are
471 * calculated based on the tensor shape and the strides of lower dimensions.
472 */
473template <typename T, typename... Ts>
474inline Strides compute_strides(const ITensorInfo &info, T stride_x, Ts &&... fixed_strides)
475{
476 const TensorShape &shape = info.tensor_shape();
477
478 // Create strides object
479 Strides strides(stride_x, fixed_strides...);
480
481 for(size_t i = 1 + sizeof...(Ts); i < info.num_dimensions(); ++i)
482 {
483 strides.set(i, shape[i - 1] * strides[i - 1]);
484 }
485
486 return strides;
487}
488
489/** Create a strides object based on the tensor dimensions.
490 *
491 * @param[in] info Tensor info object used to compute the strides.
492 *
493 * @return Strides object based on element size and tensor shape.
494 */
495template <typename... Ts>
496inline Strides compute_strides(const ITensorInfo &info)
497{
498 return compute_strides(info, info.element_size());
499}
500
Georgios Pinitas8795ffb2017-12-01 16:13:40 +0000501/** Permutes given Dimensions according to a permutation vector
502 *
503 * @warning Validity of permutation is not checked
504 *
505 * @param[in, out] dimensions Dimensions to permute
506 * @param[in] perm Permutation vector
507 */
508template <typename T>
509inline void permute(Dimensions<T> &dimensions, const PermutationVector &perm)
510{
511 auto copy_dimensions = utility::make_array<Dimensions<T>::num_max_dimensions>(dimensions.begin(), dimensions.end());
512 for(unsigned int i = 0; i < perm.num_dimensions(); ++i)
513 {
514 dimensions[i] = copy_dimensions[perm[i]];
515 }
516}
517
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100518/* Auto initialize the tensor info (shape, number of channels, data type and fixed point position) if the current assignment is empty.
519 *
520 * @param[in,out] info Tensor info used to check and assign.
521 * @param[in] shape New shape.
522 * @param[in] num_channels New number of channels.
523 * @param[in] data_type New data type
524 * @param[in] fixed_point_position New fixed point position
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000525 * @param[in] quantization_info (Optional) New quantization info
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100526 *
527 * @return True if the tensor info has been initialized
528 */
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000529bool auto_init_if_empty(ITensorInfo &info,
530 const TensorShape &shape,
531 int num_channels, DataType data_type,
532 int fixed_point_position,
533 QuantizationInfo quantization_info = QuantizationInfo());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100534
Georgios Pinitas283c1792017-11-10 18:14:06 +0000535/** Auto initialize the tensor info using another tensor info.
536 *
537 * @param info_sink Tensor info used to check and assign
538 * @param info_source Tensor info used to assign
539 *
540 * @return True if the tensor info has been initialized
541 */
Pablo Palmiera2b89ca2017-10-05 15:01:34 +0100542bool auto_init_if_empty(ITensorInfo &info_sink, const ITensorInfo &info_source);
Georgios Pinitas283c1792017-11-10 18:14:06 +0000543
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100544/* Set the shape to the specified value if the current assignment is empty.
545 *
546 * @param[in,out] info Tensor info used to check and assign.
547 * @param[in] shape New shape.
548 *
549 * @return True if the shape has been changed.
550 */
551bool set_shape_if_empty(ITensorInfo &info, const TensorShape &shape);
552
553/* Set the format, data type and number of channels to the specified value if
554 * the current data type is unknown.
555 *
556 * @param[in,out] info Tensor info used to check and assign.
557 * @param[in] format New format.
558 *
559 * @return True if the format has been changed.
560 */
561bool set_format_if_unknown(ITensorInfo &info, Format format);
562
563/* Set the data type and number of channels to the specified value if
564 * the current data type is unknown.
565 *
566 * @param[in,out] info Tensor info used to check and assign.
567 * @param[in] data_type New data type.
568 *
569 * @return True if the data type has been changed.
570 */
571bool set_data_type_if_unknown(ITensorInfo &info, DataType data_type);
572
573/* Set the fixed point position to the specified value if
574 * the current fixed point position is 0 and the data type is QS8 or QS16
575 *
576 * @param[in,out] info Tensor info used to check and assign.
577 * @param[in] fixed_point_position New fixed point position
578 *
579 * @return True if the fixed point position has been changed.
580 */
581bool set_fixed_point_position_if_zero(ITensorInfo &info, int fixed_point_position);
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000582
583/* Set the quantization info to the specified value if
584 * the current quantization info is empty and the data type of asymmetric quantized type
585 *
586 * @param[in,out] info Tensor info used to check and assign.
587 * @param[in] quantization_info Quantization info
588 *
589 * @return True if the quantization info has been changed.
590 */
591bool set_quantization_info_if_empty(ITensorInfo &info, QuantizationInfo quantization_info);
592
Isabella Gottardi1fab09f2017-07-13 15:55:57 +0100593/** Helper function to calculate the Valid Region for Scale.
594 *
595 * @param[in] src_info Input tensor info used to check.
596 * @param[in] dst_shape Shape of the output.
597 * @param[in] policy Interpolation policy.
598 * @param[in] border_size Size of the border.
599 * @param[in] border_undefined True if the border is undefined.
600 *
601 * @return The corrispondent valid region
602 */
603ValidRegion calculate_valid_region_scale(const ITensorInfo &src_info, const TensorShape &dst_shape, InterpolationPolicy policy, BorderSize border_size, bool border_undefined);
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000604
Georgios Pinitas5ee66ea2017-09-07 17:29:16 +0100605/** Convert a linear index into n-dimensional coordinates.
606 *
607 * @param[in] shape Shape of the n-dimensional tensor.
608 * @param[in] index Linear index specifying the i-th element.
609 *
610 * @return n-dimensional coordinates.
611 */
612inline Coordinates index2coords(const TensorShape &shape, int index);
Georgios Pinitas05078ec2017-11-02 13:06:59 +0000613
Georgios Pinitas5ee66ea2017-09-07 17:29:16 +0100614/** Convert n-dimensional coordinates into a linear index.
615 *
616 * @param[in] shape Shape of the n-dimensional tensor.
617 * @param[in] coord N-dimensional coordinates.
618 *
619 * @return linead index
620 */
621inline int coords2index(const TensorShape &shape, const Coordinates &coord);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100622} // namespace arm_compute
623
624#include "arm_compute/core/Helpers.inl"
625#endif /*__ARM_COMPUTE_HELPERS_H__ */