blob: 4ef94f2c6d0556babad60d35bc0676d0a10390c6 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Ioan-Cristian Szabo91d20d92017-10-27 17:35:40 +01002 * 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_VALIDATE_H__
25#define __ARM_COMPUTE_VALIDATE_H__
26
27#include "arm_compute/core/Error.h"
28#include "arm_compute/core/HOGInfo.h"
29#include "arm_compute/core/IKernel.h"
30#include "arm_compute/core/IMultiHOG.h"
31#include "arm_compute/core/IMultiImage.h"
32#include "arm_compute/core/ITensor.h"
33#include "arm_compute/core/MultiImageInfo.h"
34#include "arm_compute/core/Window.h"
35
36#include <algorithm>
37
38namespace arm_compute
39{
40namespace detail
41{
42/* Check whether two dimension objects differ.
43 *
44 * @param[in] dim1 First object to be compared.
45 * @param[in] dim2 Second object to be compared.
46 * @param[in] upper_dim The dimension from which to check.
47 *
48 * @return Return true if the two objects are different.
49 */
50template <typename T>
51inline bool have_different_dimensions(const Dimensions<T> &dim1, const Dimensions<T> &dim2, unsigned int upper_dim)
52{
53 for(unsigned int i = upper_dim; i < arm_compute::Dimensions<T>::num_max_dimensions; ++i)
54 {
55 if(dim1[i] != dim2[i])
56 {
57 return true;
58 }
59 }
60
61 return false;
62}
63
Alex Gildayc357c472018-03-21 13:54:09 +000064/** Function to compare two @ref Dimensions objects and throw an error on mismatch.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010065 *
66 * @param[in] dim Object to compare against.
Georgios Pinitas3faea252017-10-30 14:13:50 +000067 * @param[in] function Function in which the error occurred.
68 * @param[in] file File in which the error occurred.
69 * @param[in] line Line in which the error occurred.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010070 */
71template <typename T>
72class compare_dimension
73{
74public:
Alex Gildayc357c472018-03-21 13:54:09 +000075 /** Construct a comparison function.
76 *
77 * @param[in] dim Dimensions to compare.
78 * @param[in] function Source function. Used for error reporting.
79 * @param[in] file Source code file. Used for error reporting.
80 * @param[in] line Source code line. Used for error reporting.
81 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010082 compare_dimension(const Dimensions<T> &dim, const char *function, const char *file, int line)
83 : _dim{ dim }, _function{ function }, _file{ file }, _line{ line }
84 {
85 }
86
87 /** Compare the given object against the stored one.
88 *
89 * @param[in] dim To be compared object.
Alex Gildayc357c472018-03-21 13:54:09 +000090 *
91 * @return a status.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010092 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000093 arm_compute::Status operator()(const Dimensions<T> &dim)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010094 {
Georgios Pinitas3faea252017-10-30 14:13:50 +000095 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(have_different_dimensions(_dim, dim, 0), _function, _file, _line,
96 "Objects have different dimensions");
Georgios Pinitas631c41a2017-12-06 11:53:03 +000097 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +010098 }
99
100private:
101 const Dimensions<T> &_dim;
102 const char *const _function;
103 const char *const _file;
104 const int _line;
105};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000106
107template <typename F>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000108inline arm_compute::Status for_each_error(F &&)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000109{
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000110 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000111}
112
113template <typename F, typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000114inline arm_compute::Status for_each_error(F &&func, T &&arg, Ts &&... args)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000115{
116 ARM_COMPUTE_RETURN_ON_ERROR(func(arg));
117 ARM_COMPUTE_RETURN_ON_ERROR(for_each_error(func, args...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000118 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000119}
120
Alex Gildayc357c472018-03-21 13:54:09 +0000121/** Get the info for a tensor, dummy struct */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000122template <typename T>
123struct get_tensor_info_t;
Alex Gildayc357c472018-03-21 13:54:09 +0000124/** Get the info for a tensor */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000125template <>
126struct get_tensor_info_t<ITensorInfo *>
127{
Alex Gildayc357c472018-03-21 13:54:09 +0000128 /** Get the info for a tensor.
129 *
130 * @param[in] tensor Tensor.
131 *
132 * @return tensor info.
133 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000134 ITensorInfo *operator()(const ITensor *tensor)
135 {
136 return tensor->info();
137 }
138};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100139} // namespace detail
Georgios Pinitas3faea252017-10-30 14:13:50 +0000140
141/** Create an error if one of the pointers is a nullptr.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100142 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000143 * @param[in] function Function in which the error occurred.
144 * @param[in] file Name of the file where the error occurred.
145 * @param[in] line Line on which the error occurred.
146 * @param[in] pointers Pointers to check against nullptr.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000147 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000148 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100149 */
150template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000151inline arm_compute::Status error_on_nullptr(const char *function, const char *file, const int line, Ts &&... pointers)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100152{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000153 const std::array<const void *, sizeof...(Ts)> pointers_array{ { std::forward<Ts>(pointers)... } };
154 bool has_nullptr = std::any_of(pointers_array.begin(), pointers_array.end(), [&](const void *ptr)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100155 {
Georgios Pinitas3faea252017-10-30 14:13:50 +0000156 return (ptr == nullptr);
157 });
158 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(has_nullptr, function, file, line, "Nullptr object!");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000159 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100160}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000161#define ARM_COMPUTE_ERROR_ON_NULLPTR(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000162 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000163#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...) \
164 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100165
Georgios Pinitas3faea252017-10-30 14:13:50 +0000166/** Return an error if the passed window is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100167 *
168 * The subwindow is invalid if:
169 * - It is not a valid window.
170 * - Its dimensions don't match the full window's ones
171 * - The step for each of its dimension is not identical to the corresponding one of the full window.
172 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000173 * @param[in] function Function in which the error occurred.
174 * @param[in] file Name of the file where the error occurred.
175 * @param[in] line Line on which the error occurred.
176 * @param[in] full Full size window
177 * @param[in] win Window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000178 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000179 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100180 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000181arm_compute::Status error_on_mismatching_windows(const char *function, const char *file, const int line,
182 const Window &full, const Window &win);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000183#define ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000184 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000185#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
186 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100187
Georgios Pinitas3faea252017-10-30 14:13:50 +0000188/** Return an error if the passed subwindow is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100189 *
190 * The subwindow is invalid if:
191 * - It is not a valid window.
192 * - It is not fully contained inside the full window
193 * - The step for each of its dimension is not identical to the corresponding one of the full window.
194 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000195 * @param[in] function Function in which the error occurred.
196 * @param[in] file Name of the file where the error occurred.
197 * @param[in] line Line on which the error occurred.
198 * @param[in] full Full size window
199 * @param[in] sub Sub-window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000200 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000201 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100202 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000203arm_compute::Status error_on_invalid_subwindow(const char *function, const char *file, const int line,
204 const Window &full, const Window &sub);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000205#define ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(f, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000206 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000207#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBWINDOW(f, s) \
208 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100209
Georgios Pinitas3faea252017-10-30 14:13:50 +0000210/** Return an error if the window can't be collapsed at the given dimension.
steniu01868e5412017-07-17 23:16:00 +0100211 *
212 * The window cannot be collapsed if the given dimension not equal to the full window's dimension or not start from 0.
213 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000214 * @param[in] function Function in which the error occurred.
215 * @param[in] file Name of the file where the error occurred.
216 * @param[in] line Line on which the error occurred.
217 * @param[in] full Full size window
218 * @param[in] window Window to be collapsed.
219 * @param[in] dim Dimension need to be checked.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000220 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000221 * @return Status
steniu01868e5412017-07-17 23:16:00 +0100222 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000223arm_compute::Status error_on_window_not_collapsable_at_dimension(const char *function, const char *file, const int line,
224 const Window &full, const Window &window, const int dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000225#define ARM_COMPUTE_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000226 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000227#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
228 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
steniu01868e5412017-07-17 23:16:00 +0100229
Georgios Pinitas3faea252017-10-30 14:13:50 +0000230/** Return an error if the passed coordinates have too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100231 *
232 * The coordinates have too many dimensions if any of the dimensions greater or equal to max_dim is different from 0.
233 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000234 * @param[in] function Function in which the error occurred.
235 * @param[in] file Name of the file where the error occurred.
236 * @param[in] line Line on which the error occurred.
237 * @param[in] pos Coordinates to validate
238 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000239 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000240 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100241 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000242arm_compute::Status error_on_coordinates_dimensions_gte(const char *function, const char *file, const int line,
243 const Coordinates &pos, unsigned int max_dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000244#define ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000245 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000246#define ARM_COMPUTE_RETURN_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
247 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100248
Georgios Pinitas3faea252017-10-30 14:13:50 +0000249/** Return an error if the passed window has too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100250 *
251 * The window has too many dimensions if any of the dimension greater or equal to max_dim is different from 0.
252 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000253 * @param[in] function Function in which the error occurred.
254 * @param[in] file Name of the file where the error occurred.
255 * @param[in] line Line on which the error occurred.
256 * @param[in] win Window to validate
257 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000258 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000259 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100260 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000261arm_compute::Status error_on_window_dimensions_gte(const char *function, const char *file, const int line,
262 const Window &win, unsigned int max_dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000263#define ARM_COMPUTE_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000264 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000265#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
266 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100267
Georgios Pinitas3faea252017-10-30 14:13:50 +0000268/** Return an error if the passed dimension objects differ.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100269 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000270 * @param[in] function Function in which the error occurred.
271 * @param[in] file Name of the file where the error occurred.
272 * @param[in] line Line on which the error occurred.
273 * @param[in] dim1 The first object to be compared.
274 * @param[in] dim2 The second object to be compared.
275 * @param[in] dims (Optional) Further allowed objects.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000276 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000277 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100278 */
279template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000280arm_compute::Status error_on_mismatching_dimensions(const char *function, const char *file, int line,
281 const Dimensions<T> &dim1, const Dimensions<T> &dim2, Ts &&... dims)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100282{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000283 ARM_COMPUTE_RETURN_ON_ERROR(detail::for_each_error(detail::compare_dimension<T>(dim1, function, file, line), dim2, std::forward<Ts>(dims)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000284 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100285}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000286#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000287 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000288#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
289 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100290
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100291/** Return an error if the passed tensor objects are not even.
292 *
293 * @param[in] function Function in which the error occurred.
294 * @param[in] file Name of the file where the error occurred.
295 * @param[in] line Line on which the error occurred.
296 * @param[in] format Format to check if odd shape is allowed
297 * @param[in] tensor1 The first object to be compared for odd shape.
298 * @param[in] tensors (Optional) Further allowed objects.
299 *
300 * @return Status
301 */
302template <typename... Ts>
303arm_compute::Status error_on_tensors_not_even(const char *function, const char *file, int line,
304 const Format &format, const ITensor *tensor1, Ts... tensors)
305{
306 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor1 == nullptr, function, file, line);
307 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
308 const std::array < const ITensor *, 1 + sizeof...(Ts) > tensors_info_array{ { tensor1, std::forward<Ts>(tensors)... } };
309 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_info_array.cbegin(), tensors_info_array.cend(), [&](const ITensor * tensor)
310 {
311 const TensorShape correct_shape = adjust_odd_shape(tensor->info()->tensor_shape(), format);
312 return detail::have_different_dimensions(tensor->info()->tensor_shape(), correct_shape, 2);
313 }),
314 function, file, line, "Tensor shape has odd dimensions");
315 return arm_compute::Status{};
316}
317
318#define ARM_COMPUTE_ERROR_ON_TENSORS_NOT_EVEN(...) \
319 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
320#define ARM_COMPUTE_RETURN_ERROR_ON_TENSORS_NOT_EVEN(...) \
321 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
322
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000323/** Return an error if the passed tensor objects are not sub-sampled.
324 *
325 * @param[in] function Function in which the error occurred.
326 * @param[in] file Name of the file where the error occurred.
327 * @param[in] line Line on which the error occurred.
328 * @param[in] format Format to check if sub-sampling allowed.
329 * @param[in] shape The tensor shape to calculate sub-sampling from.
330 * @param[in] tensor1 The first object to be compared.
331 * @param[in] tensors (Optional) Further allowed objects.
332 *
333 * @return Status
334 */
335template <typename... Ts>
336arm_compute::Status error_on_tensors_not_subsampled(const char *function, const char *file, int line,
337 const Format &format, const TensorShape &shape, const ITensor *tensor1, Ts... tensors)
338{
339 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor1 == nullptr, function, file, line);
340 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
341 const TensorShape sub2_shape = calculate_subsampled_shape(shape, format);
342 const std::array < const ITensor *, 1 + sizeof...(Ts) > tensors_info_array{ { tensor1, std::forward<Ts>(tensors)... } };
343 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_info_array.cbegin(), tensors_info_array.cend(), [&](const ITensor * tensor)
344 {
345 return detail::have_different_dimensions(tensor->info()->tensor_shape(), sub2_shape, 2);
346 }),
347 function, file, line, "Tensor shape has mismatch dimensions for sub-sampling");
348 return arm_compute::Status{};
349}
350
351#define ARM_COMPUTE_ERROR_ON_TENSORS_NOT_SUBSAMPLED(...) \
352 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensors_not_subsampled(__func__, __FILE__, __LINE__, __VA_ARGS__))
353#define ARM_COMPUTE_RETURN_ERROR_ON_TENSORS_NOT_SUBSAMPLED(...) \
354 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensors_not_subsampled(__func__, __FILE__, __LINE__, __VA_ARGS__))
355
Georgios Pinitas3faea252017-10-30 14:13:50 +0000356/** Return an error if the passed two tensor infos have different shapes from the given dimension
357 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000358 * @param[in] function Function in which the error occurred.
359 * @param[in] file Name of the file where the error occurred.
360 * @param[in] line Line on which the error occurred.
361 * @param[in] tensor_info_1 The first tensor info to be compared.
362 * @param[in] tensor_info_2 The second tensor info to be compared.
363 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000364 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000365 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000366 */
367template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000368inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
369 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000370{
371 return error_on_mismatching_shapes(function, file, line, 0U, tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)...);
372}
373/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100374 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000375 * @param[in] function Function in which the error occurred.
376 * @param[in] file Name of the file where the error occurred.
377 * @param[in] line Line on which the error occurred.
378 * @param[in] tensor_1 The first tensor to be compared.
379 * @param[in] tensor_2 The second tensor to be compared.
380 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000381 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000382 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100383 */
384template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000385inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
386 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100387{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000388 return error_on_mismatching_shapes(function, file, line, 0U, tensor_1, tensor_2, std::forward<Ts>(tensors)...);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100389}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000390/** Return an error if the passed two tensors have different shapes from the given dimension
391 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000392 * @param[in] function Function in which the error occurred.
393 * @param[in] file Name of the file where the error occurred.
394 * @param[in] line Line on which the error occurred.
395 * @param[in] upper_dim The dimension from which to check.
396 * @param[in] tensor_info_1 The first tensor info to be compared.
397 * @param[in] tensor_info_2 The second tensor info to be compared.
398 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000399 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000400 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000401 */
402template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000403inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
404 unsigned int upper_dim, const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000405{
406 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_1 == nullptr, function, file, line);
407 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_2 == nullptr, function, file, line);
408 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100409
Georgios Pinitas3faea252017-10-30 14:13:50 +0000410 const std::array < const ITensorInfo *, 2 + sizeof...(Ts) > tensors_info_array{ { tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)... } };
411 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(std::next(tensors_info_array.cbegin()), tensors_info_array.cend(), [&](const ITensorInfo * tensor_info)
412 {
413 return detail::have_different_dimensions((*tensors_info_array.cbegin())->tensor_shape(), tensor_info->tensor_shape(), upper_dim);
414 }),
415 function, file, line, "Tensors have different shapes");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000416 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000417}
418/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100419 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000420 * @param[in] function Function in which the error occurred.
421 * @param[in] file Name of the file where the error occurred.
422 * @param[in] line Line on which the error occurred.
423 * @param[in] upper_dim The dimension from which to check.
424 * @param[in] tensor_1 The first tensor to be compared.
425 * @param[in] tensor_2 The second tensor to be compared.
426 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000427 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000428 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100429 */
430template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000431inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
432 unsigned int upper_dim, const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100433{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000434 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_1 == nullptr, function, file, line);
435 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_2 == nullptr, function, file, line);
436 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
437 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(function, file, line, upper_dim, tensor_1->info(), tensor_2->info(),
438 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000439 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100440}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000441#define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000442 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000443#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(...) \
444 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100445
Michalis Spyrou7a569252018-03-01 12:03:14 +0000446/** Return an error if the passed tensor infos have different data layouts
447 *
448 * @param[in] function Function in which the error occurred.
449 * @param[in] file Name of the file where the error occurred.
450 * @param[in] line Line on which the error occurred.
451 * @param[in] tensor_info The first tensor info to be compared.
452 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
453 *
454 * @return Status
455 */
456template <typename... Ts>
457inline arm_compute::Status error_on_mismatching_data_layouts(const char *function, const char *file, const int line,
458 const ITensorInfo *tensor_info, Ts... tensor_infos)
459{
460 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
461 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
462
463 DataLayout &&tensor_data_layout = tensor_info->data_layout();
464 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { std::forward<Ts>(tensor_infos)... } };
465 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
466 {
467 return tensor_info_obj->data_layout() != tensor_data_layout;
468 }),
469 function, file, line, "Tensors have different data layouts");
470 return arm_compute::Status{};
471}
472/** Return an error if the passed tensors have different data layouts
473 *
474 * @param[in] function Function in which the error occurred.
475 * @param[in] file Name of the file where the error occurred.
476 * @param[in] line Line on which the error occurred.
477 * @param[in] tensor The first tensor to be compared.
478 * @param[in] tensors (Optional) Further allowed tensors.
479 *
480 * @return Status
481 */
482template <typename... Ts>
483inline arm_compute::Status error_on_mismatching_data_layouts(const char *function, const char *file, const int line,
484 const ITensor *tensor, Ts... tensors)
485{
486 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
487 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
488 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_layouts(function, file, line, tensor->info(),
489 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
490 return arm_compute::Status{};
491}
492#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
493 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
494#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
495 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
496
Georgios Pinitas3faea252017-10-30 14:13:50 +0000497/** Return an error if the passed two tensor infos have different data types
498 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000499 * @param[in] function Function in which the error occurred.
500 * @param[in] file Name of the file where the error occurred.
501 * @param[in] line Line on which the error occurred.
502 * @param[in] tensor_info The first tensor info to be compared.
503 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000504 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000505 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000506 */
507template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000508inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
509 const ITensorInfo *tensor_info, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000510{
511 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
512 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
513
514 DataType &&tensor_data_type = tensor_info->data_type();
515 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { std::forward<Ts>(tensor_infos)... } };
516 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
517 {
518 return tensor_info_obj->data_type() != tensor_data_type;
519 }),
520 function, file, line, "Tensors have different data types");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000521 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000522}
523/** Return an error if the passed two tensors have different data types
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100524 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000525 * @param[in] function Function in which the error occurred.
526 * @param[in] file Name of the file where the error occurred.
527 * @param[in] line Line on which the error occurred.
528 * @param[in] tensor The first tensor to be compared.
529 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000530 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000531 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100532 */
533template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000534inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
535 const ITensor *tensor, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100536{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000537 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
538 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
539 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(function, file, line, tensor->info(),
540 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000541 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100542}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000543#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000544 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000545#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
546 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100547
Georgios Pinitas3faea252017-10-30 14:13:50 +0000548/** Return an error if the passed tensor infos have different fixed point data types or different fixed point positions
549 *
550 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
551 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000552 * @param[in] function Function in which the error occurred.
553 * @param[in] file Name of the file where the error occurred.
554 * @param[in] line Line on which the error occurred.
555 * @param[in] tensor_info_1 The first tensor info to be compared.
556 * @param[in] tensor_info_2 The second tensor info to be compared.
557 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000558 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000559 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000560 */
561template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000562inline arm_compute::Status error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
563 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000564{
565 DataType &&first_data_type = tensor_info_1->data_type();
566 const int first_fixed_point_position = tensor_info_1->fixed_point_position();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100567
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000568 if(!is_data_type_fixed_point(first_data_type))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000569 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000570 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000571 }
572
573 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
574 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
575 {
576 return tensor_info->data_type() != first_data_type;
577 }),
578 function, file, line, "Tensors have different fixed point data types");
579 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
580 {
581 return tensor_info->fixed_point_position() != first_fixed_point_position;
582 }),
583 function, file, line, "Tensors have different fixed point positions");
584
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000585 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000586}
587/** Return an error if the passed tensor have different fixed point data types or different fixed point positions
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100588 *
589 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
590 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000591 * @param[in] function Function in which the error occurred.
592 * @param[in] file Name of the file where the error occurred.
593 * @param[in] line Line on which the error occurred.
594 * @param[in] tensor_1 The first tensor to be compared.
595 * @param[in] tensor_2 The second tensor to be compared.
596 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000597 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000598 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100599 */
600template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000601inline arm_compute::Status error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
602 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100603{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000604 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(function, file, line, tensor_1->info(), tensor_2->info(),
605 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000606 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100607}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000608#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000609 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000610#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
611 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100612
Daniil Efremoveed841c2017-11-09 19:05:25 +0700613/** Return an error if the passed tensor infos have different asymmetric quantized data types or different quantization info
614 *
615 * @note: If the first tensor info doesn't have asymmetric quantized data type, the function returns without throwing an error
616 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000617 * @param[in] function Function in which the error occurred.
618 * @param[in] file Name of the file where the error occurred.
619 * @param[in] line Line on which the error occurred.
620 * @param[in] tensor_info_1 The first tensor info to be compared.
621 * @param[in] tensor_info_2 The second tensor info to be compared.
622 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700623 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000624 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700625 */
626template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000627inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
628 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700629{
630 DataType &&first_data_type = tensor_info_1->data_type();
631 const QuantizationInfo first_quantization_info = tensor_info_1->quantization_info();
632
633 if(!is_data_type_quantized_asymmetric(first_data_type))
634 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000635 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700636 }
637
638 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
639 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
640 {
641 return tensor_info->data_type() != first_data_type;
642 }),
643 function, file, line, "Tensors have different asymmetric quantized data types");
644 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
645 {
646 return tensor_info->quantization_info() != first_quantization_info;
647 }),
648 function, file, line, "Tensors have different quantization information");
649
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000650 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700651}
652/** Return an error if the passed tensor have different asymmetric quantized data types or different quantization info
653 *
654 * @note: If the first tensor doesn't have asymmetric quantized data type, the function returns without throwing an error
655 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000656 * @param[in] function Function in which the error occurred.
657 * @param[in] file Name of the file where the error occurred.
658 * @param[in] line Line on which the error occurred.
659 * @param[in] tensor_1 The first tensor to be compared.
660 * @param[in] tensor_2 The second tensor to be compared.
661 * @param[in] tensors (Optional) Further allowed tensors.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700662 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000663 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700664 */
665template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000666inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
667 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700668{
669 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(function, file, line, tensor_1->info(), tensor_2->info(),
670 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000671 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700672}
673#define ARM_COMPUTE_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
674 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
675#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
676 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
677
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100678/** Throw an error if the format of the passed tensor/multi-image does not match any of the formats provided.
679 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000680 * @param[in] function Function in which the error occurred.
681 * @param[in] file Name of the file where the error occurred.
682 * @param[in] line Line on which the error occurred.
683 * @param[in] object Tensor/multi-image to validate.
684 * @param[in] format First format allowed.
685 * @param[in] formats (Optional) Further allowed formats.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100686 */
687template <typename T, typename F, typename... Fs>
688void error_on_format_not_in(const char *function, const char *file, const int line,
689 const T *object, F &&format, Fs &&... formats)
690{
691 ARM_COMPUTE_ERROR_ON_LOC(object == nullptr, function, file, line);
692
693 Format &&object_format = object->info()->format();
694 ARM_COMPUTE_UNUSED(object_format);
695
696 ARM_COMPUTE_ERROR_ON_LOC(object_format == Format::UNKNOWN, function, file, line);
697
698 const std::array<F, sizeof...(Fs)> formats_array{ { std::forward<Fs>(formats)... } };
699 ARM_COMPUTE_UNUSED(formats_array);
700
701 ARM_COMPUTE_ERROR_ON_LOC_MSG(object_format != format && std::none_of(formats_array.begin(), formats_array.end(), [&](const F & f)
702 {
703 return f == object_format;
704 }),
705 function, file, line, "Format %s not supported by this kernel", string_from_format(object_format).c_str());
706}
707#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t, ...) ::arm_compute::error_on_format_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
708
Georgios Pinitas3faea252017-10-30 14:13:50 +0000709/** Return an error if the data type of the passed tensor info does not match any of the data types provided.
710 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000711 * @param[in] function Function in which the error occurred.
712 * @param[in] file Name of the file where the error occurred.
713 * @param[in] line Line on which the error occurred.
714 * @param[in] tensor_info Tensor info to validate.
715 * @param[in] dt First data type allowed.
716 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000717 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000718 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000719 */
720template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000721inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
722 const ITensorInfo *tensor_info, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000723{
724 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
725
726 const DataType &tensor_dt = tensor_info->data_type(); //NOLINT
727 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
728
729 const std::array<T, sizeof...(Ts)> dts_array{ { std::forward<Ts>(dts)... } };
730 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T & d)
731 {
732 return d == tensor_dt;
733 }),
734 function, file, line, "ITensor data type %s not supported by this kernel", string_from_data_type(tensor_dt).c_str());
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000735 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000736}
737/** Return an error if the data type of the passed tensor does not match any of the data types provided.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100738 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000739 * @param[in] function Function in which the error occurred.
740 * @param[in] file Name of the file where the error occurred.
741 * @param[in] line Line on which the error occurred.
742 * @param[in] tensor Tensor to validate.
743 * @param[in] dt First data type allowed.
744 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000745 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000746 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100747 */
748template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000749inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
750 const ITensor *tensor, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100751{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000752 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
753 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_not_in(function, file, line, tensor->info(), std::forward<T>(dt), std::forward<Ts>(dts)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000754 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100755}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000756#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000757 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_data_type_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000758#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
759 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100760
Georgios Pinitas3faea252017-10-30 14:13:50 +0000761/** Return an error if the data type or the number of channels of the passed tensor info does not match any of the data types and number of channels provided.
762 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000763 * @param[in] function Function in which the error occurred.
764 * @param[in] file Name of the file where the error occurred.
765 * @param[in] line Line on which the error occurred.
766 * @param[in] tensor_info Tensor info to validate.
767 * @param[in] num_channels Number of channels to check
768 * @param[in] dt First data type allowed.
769 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000770 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000771 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000772 */
773template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000774inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
775 const ITensorInfo *tensor_info, size_t num_channels, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000776{
777 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_not_in(function, file, line, tensor_info, std::forward<T>(dt), std::forward<Ts>(dts)...));
778 const size_t tensor_nc = tensor_info->num_channels();
779 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(tensor_nc != num_channels, function, file, line, "Number of channels %d. Required number of channels %d", tensor_nc, num_channels);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000780 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000781}
782/** Return an error if the data type or the number of channels of the passed tensor does not match any of the data types and number of channels provided.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100783 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000784 * @param[in] function Function in which the error occurred.
785 * @param[in] file Name of the file where the error occurred.
786 * @param[in] line Line on which the error occurred.
787 * @param[in] tensor Tensor to validate.
788 * @param[in] num_channels Number of channels to check
789 * @param[in] dt First data type allowed.
790 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000791 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000792 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100793 */
794template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000795inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
796 const ITensor *tensor, size_t num_channels, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100797{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000798 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
799 ARM_COMPUTE_RETURN_ON_ERROR(error_on_data_type_channel_not_in(function, file, line, tensor->info(), num_channels, std::forward<T>(dt), std::forward<Ts>(dts)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000800 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100801}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000802#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000803 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000804#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
805 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100806
Vidhya Sudhan Loganathanf1f49062018-05-25 13:21:26 +0100807/** Return an error if the data type of the passed tensor info is FP16 and FP16 extension is not supported by the device.
808 *
809 * @param[in] function Function in which the error occurred.
810 * @param[in] file Name of the file where the error occurred.
811 * @param[in] line Line on which the error occurred.
812 * @param[in] tensor_info Tensor info to validate.
813 * @param[in] is_fp16_supported Is fp16 supported by the device.
814 *
815 * @return Status
816 */
817inline arm_compute::Status error_on_unsupported_fp16(const char *function, const char *file, const int line,
818 const ITensorInfo *tensor_info, bool is_fp16_supported)
819{
820 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
821 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG((tensor_info->data_type() == DataType::F16 && !is_fp16_supported),
822 function, file, line, "FP16 not supported by the device");
823 return arm_compute::Status{};
824}
825
826/** Return an error if the data type of the passed tensor is FP16 and FP16 extension is not supported by the device.
827 *
828 * @param[in] function Function in which the error occurred.
829 * @param[in] file Name of the file where the error occurred.
830 * @param[in] line Line on which the error occurred.
831 * @param[in] tensor Tensor to validate.
832 * @param[in] is_fp16_supported Is fp16 supported by the device.
833 *
834 * @return Status
835 */
836inline arm_compute::Status error_on_unsupported_fp16(const char *function, const char *file, const int line,
837 const ITensor *tensor, bool is_fp16_supported)
838{
839 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
840 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unsupported_fp16(function, file, line, tensor->info(), is_fp16_supported));
841 return arm_compute::Status{};
842}
843
Georgios Pinitas3faea252017-10-30 14:13:50 +0000844/** Return an error if the tensor is not 2D.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100845 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000846 * @param[in] function Function in which the error occurred.
847 * @param[in] file Name of the file where the error occurred.
848 * @param[in] line Line on which the error occurred.
849 * @param[in] tensor Tensor to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000850 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000851 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100852 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000853arm_compute::Status error_on_tensor_not_2d(const char *function, const char *file, const int line,
854 const ITensor *tensor);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000855#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000856 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000857#define ARM_COMPUTE_RETURN_ERROR_ON_TENSOR_NOT_2D(t) \
858 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100859
Georgios Pinitas3faea252017-10-30 14:13:50 +0000860/** Return an error if the channel is not in channels.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100861 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000862 * @param[in] function Function in which the error occurred.
863 * @param[in] file Name of the file where the error occurred.
864 * @param[in] line Line on which the error occurred.
865 * @param[in] cn Input channel
866 * @param[in] channel First channel allowed.
867 * @param[in] channels (Optional) Further allowed channels.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000868 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000869 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100870 */
871template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000872inline arm_compute::Status error_on_channel_not_in(const char *function, const char *file, const int line,
873 T cn, T &&channel, Ts &&... channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100874{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000875 ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100876
877 const std::array<T, sizeof...(Ts)> channels_array{ { std::forward<Ts>(channels)... } };
Georgios Pinitas3faea252017-10-30 14:13:50 +0000878 ARM_COMPUTE_RETURN_ERROR_ON_LOC(channel != cn && std::none_of(channels_array.begin(), channels_array.end(), [&](const T & f)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100879 {
880 return f == cn;
881 }),
882 function, file, line);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000883 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100884}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000885#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000886 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_channel_not_in(__func__, __FILE__, __LINE__, c, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000887#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
888 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_channel_not_in(__func__, __FILE__, __LINE__, c, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100889
Georgios Pinitas3faea252017-10-30 14:13:50 +0000890/** Return an error if the channel is not in format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100891 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000892 * @param[in] function Function in which the error occurred.
893 * @param[in] file Name of the file where the error occurred.
894 * @param[in] line Line on which the error occurred.
895 * @param[in] fmt Input channel
896 * @param[in] cn First channel allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000897 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000898 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100899 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000900arm_compute::Status error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
901 Format fmt, Channel cn);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000902#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000903 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_channel_not_in_known_format(__func__, __FILE__, __LINE__, f, c))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000904#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
905 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_channel_not_in_known_format(__func__, __FILE__, __LINE__, f, c))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100906
Georgios Pinitas3faea252017-10-30 14:13:50 +0000907/** Return an error if the @ref IMultiHOG container is invalid
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100908 *
909 * An @ref IMultiHOG container is invalid if:
910 *
911 * -# it is a nullptr
912 * -# it doesn't contain models
913 * -# it doesn't have the HOG data objects with the same phase_type, normalization_type and l2_hyst_threshold (if normalization_type == L2HYS_NORM)
914 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000915 * @param[in] function Function in which the error occurred.
916 * @param[in] file Name of the file where the error occurred.
917 * @param[in] line Line on which the error occurred.
918 * @param[in] multi_hog IMultiHOG container to validate
Georgios Pinitas3faea252017-10-30 14:13:50 +0000919 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000920 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100921 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000922arm_compute::Status error_on_invalid_multi_hog(const char *function, const char *file, const int line,
923 const IMultiHOG *multi_hog);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000924#define ARM_COMPUTE_ERROR_ON_INVALID_MULTI_HOG(m) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000925 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000926#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_MULTI_HOG(m) \
927 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100928
Georgios Pinitas3faea252017-10-30 14:13:50 +0000929/** Return an error if the kernel is not configured.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100930 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000931 * @param[in] function Function in which the error occurred.
932 * @param[in] file Name of the file where the error occurred.
933 * @param[in] line Line on which the error occurred.
934 * @param[in] kernel Kernel to validate.
Alex Gildayc357c472018-03-21 13:54:09 +0000935 *
936 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100937 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000938arm_compute::Status error_on_unconfigured_kernel(const char *function, const char *file, const int line,
939 const IKernel *kernel);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000940#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000941 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000942#define ARM_COMPUTE_RETURN_ERROR_ON_UNCONFIGURED_KERNEL(k) \
943 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100944
Georgios Pinitas3faea252017-10-30 14:13:50 +0000945/** Return an error if if the coordinates and shape of the subtensor are within the parent tensor.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100946 *
947 * @param[in] function Function in which the error occurred.
948 * @param[in] file Name of the file where the error occurred.
949 * @param[in] line Line on which the error occurred.
950 * @param[in] parent_shape Parent tensor shape
951 * @param[in] coords Coordinates inside the parent tensor where the first element of the subtensor is
952 * @param[in] shape Shape of the subtensor
Georgios Pinitas3faea252017-10-30 14:13:50 +0000953 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000954 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100955 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000956arm_compute::Status error_on_invalid_subtensor(const char *function, const char *file, const int line,
957 const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000958#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000959 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000960#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
961 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100962
Georgios Pinitas3faea252017-10-30 14:13:50 +0000963/** Return an error if the valid region of a subtensor is not inside the valid region of the parent tensor.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100964 *
965 * @param[in] function Function in which the error occurred.
966 * @param[in] file Name of the file where the error occurred.
967 * @param[in] line Line on which the error occurred.
968 * @param[in] parent_valid_region Parent valid region.
969 * @param[in] valid_region Valid region of subtensor.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000970 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000971 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100972 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000973arm_compute::Status error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
974 const ValidRegion &parent_valid_region, const ValidRegion &valid_region);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000975#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000976 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000977#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
978 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100979
Georgios Pinitas3faea252017-10-30 14:13:50 +0000980/** Return an error if the input fixed-point positions are different.
981 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000982 * @param[in] function Function in which the error occurred.
983 * @param[in] file Name of the file where the error occurred.
984 * @param[in] line Line on which the error occurred.
985 * @param[in] tensor_info_1 The first tensor info to be compared.
986 * @param[in] tensor_info_2 The second tensor info to be compared.
987 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000988 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000989 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000990 */
991template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000992inline arm_compute::Status error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
993 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000994{
995 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_info_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
996 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_info_array.begin(), tensor_info_array.end(), [&](const ITensorInfo * tensor_info)
997 {
998 return tensor_info->fixed_point_position() != tensor_info_1->fixed_point_position();
999 }),
1000 function, file, line, "Tensors have different fixed-point positions");
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001001 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +00001002}
1003/** Return an error if the input fixed-point positions are different.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001004 *
Anthony Barbierf202e502017-11-23 18:02:04 +00001005 * @param[in] function Function in which the error occurred.
1006 * @param[in] file Name of the file where the error occurred.
1007 * @param[in] line Line on which the error occurred.
1008 * @param[in] tensor_1 The first tensor to be compared.
1009 * @param[in] tensor_2 The second tensor to be compared.
1010 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +00001011 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001012 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001013 */
1014template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001015inline arm_compute::Status error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
1016 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001017{
Georgios Pinitas3faea252017-10-30 14:13:50 +00001018 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point_position(function, file, line, tensor_1->info(), tensor_2->info(),
1019 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001020 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001021}
Georgios Pinitas3faea252017-10-30 14:13:50 +00001022#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001023 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_fixed_point_position(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +00001024#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
1025 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point_position(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001026
Georgios Pinitas3faea252017-10-30 14:13:50 +00001027/** Return an error if the fixed-point value is not representable in the specified Q format.
1028 *
Anthony Barbierf202e502017-11-23 18:02:04 +00001029 * @param[in] function Function in which the error occurred.
1030 * @param[in] file Name of the file where the error occurred.
1031 * @param[in] line Line on which the error occurred.
1032 * @param[in] value The floating point value to be checked.
1033 * @param[in] tensor_info Input tensor info that has information on data type and fixed-point position.
Georgios Pinitas3faea252017-10-30 14:13:50 +00001034 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001035 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +00001036 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001037inline arm_compute::Status error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
1038 float value, const ITensorInfo *tensor_info)
Georgios Pinitas3faea252017-10-30 14:13:50 +00001039{
1040 const int fixed_point_position = tensor_info->fixed_point_position();
1041 const DataType dt = tensor_info->data_type();
1042 const unsigned int q_max_range = 0xFFFFFFFFu >> (((sizeof(unsigned int) - element_size_from_data_type(dt)) * 8) + 1);
1043 const float max_range = q_max_range / (static_cast<float>(1 << fixed_point_position));
1044
1045 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(value > max_range, function, file, line,
1046 "Value %f is not representable in %s with fixed-point position %d", value, string_from_data_type(dt).c_str(), fixed_point_position);
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001047 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +00001048}
1049/** Return an error an error if the fixed-point value is not representable in the specified Q format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001050 *
Anthony Barbierf202e502017-11-23 18:02:04 +00001051 * @param[in] function Function in which the error occurred.
1052 * @param[in] file Name of the file where the error occurred.
1053 * @param[in] line Line on which the error occurred.
1054 * @param[in] value The floating point value to be checked.
1055 * @param[in] tensor Input tensor that has information on data type and fixed-point position.
Georgios Pinitas3faea252017-10-30 14:13:50 +00001056 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001057 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001058 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001059inline arm_compute::Status error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
1060 float value, const ITensor *tensor)
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001061{
Georgios Pinitas3faea252017-10-30 14:13:50 +00001062 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
1063 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_value_not_representable_in_fixed_point(function, file, line, value, tensor->info()));
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001064 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001065}
Georgios Pinitas3faea252017-10-30 14:13:50 +00001066#define ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001067 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_value_not_representable_in_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +00001068#define ARM_COMPUTE_RETURN_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
1069 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_value_not_representable_in_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001070}
1071#endif /* __ARM_COMPUTE_VALIDATE_H__*/