blob: 2ca9f6b64ebf2dd4d868842eec2282b88e84339b [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2016, 2017 ARM Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#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
64/** Functor to compare two @ref Dimensions objects and throw an error on mismatch.
65 *
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:
75 compare_dimension(const Dimensions<T> &dim, const char *function, const char *file, int line)
76 : _dim{ dim }, _function{ function }, _file{ file }, _line{ line }
77 {
78 }
79
80 /** Compare the given object against the stored one.
81 *
82 * @param[in] dim To be compared object.
83 */
Georgios Pinitas3faea252017-10-30 14:13:50 +000084 arm_compute::Error operator()(const Dimensions<T> &dim)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010085 {
Georgios Pinitas3faea252017-10-30 14:13:50 +000086 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(have_different_dimensions(_dim, dim, 0), _function, _file, _line,
87 "Objects have different dimensions");
88 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +010089 }
90
91private:
92 const Dimensions<T> &_dim;
93 const char *const _function;
94 const char *const _file;
95 const int _line;
96};
Georgios Pinitas3faea252017-10-30 14:13:50 +000097
98template <typename F>
99inline arm_compute::Error for_each_error(F &&)
100{
101 return arm_compute::Error{};
102}
103
104template <typename F, typename T, typename... Ts>
105inline arm_compute::Error for_each_error(F &&func, T &&arg, Ts &&... args)
106{
107 ARM_COMPUTE_RETURN_ON_ERROR(func(arg));
108 ARM_COMPUTE_RETURN_ON_ERROR(for_each_error(func, args...));
109 return arm_compute::Error{};
110}
111
112template <typename T>
113struct get_tensor_info_t;
114template <>
115struct get_tensor_info_t<ITensorInfo *>
116{
117 ITensorInfo *operator()(const ITensor *tensor)
118 {
119 return tensor->info();
120 }
121};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100122} // namespace detail
Georgios Pinitas3faea252017-10-30 14:13:50 +0000123
124/** Create an error if one of the pointers is a nullptr.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100125 *
126 * @param[in] function Function in which the error occurred.
127 * @param[in] file Name of the file where the error occurred.
128 * @param[in] line Line on which the error occurred.
129 * @param[in] pointers Pointers to check against nullptr.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000130 *
131 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100132 */
133template <typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000134inline arm_compute::Error error_on_nullptr(const char *function, const char *file, const int line, Ts &&... pointers)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100135{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000136 const std::array<const void *, sizeof...(Ts)> pointers_array{ { std::forward<Ts>(pointers)... } };
137 bool has_nullptr = std::any_of(pointers_array.begin(), pointers_array.end(), [&](const void *ptr)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100138 {
Georgios Pinitas3faea252017-10-30 14:13:50 +0000139 return (ptr == nullptr);
140 });
141 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(has_nullptr, function, file, line, "Nullptr object!");
142 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100143}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000144#define ARM_COMPUTE_ERROR_ON_NULLPTR(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000145 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000146#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...) \
147 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100148
Georgios Pinitas3faea252017-10-30 14:13:50 +0000149/** Return an error if the passed window is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100150 *
151 * The subwindow is invalid if:
152 * - It is not a valid window.
153 * - Its dimensions don't match the full window's ones
154 * - The step for each of its dimension is not identical to the corresponding one of the full window.
155 *
156 * @param[in] function Function in which the error occurred.
157 * @param[in] file Name of the file where the error occurred.
158 * @param[in] line Line on which the error occurred.
159 * @param[in] full Full size window
160 * @param[in] win Window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000161 *
162 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100163 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000164arm_compute::Error error_on_mismatching_windows(const char *function, const char *file, const int line,
165 const Window &full, const Window &win);
166#define ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000167 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000168#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
169 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100170
Georgios Pinitas3faea252017-10-30 14:13:50 +0000171/** Return an error if the passed subwindow is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100172 *
173 * The subwindow is invalid if:
174 * - It is not a valid window.
175 * - It is not fully contained inside the full window
176 * - The step for each of its dimension is not identical to the corresponding one of the full window.
177 *
178 * @param[in] function Function in which the error occurred.
179 * @param[in] file Name of the file where the error occurred.
180 * @param[in] line Line on which the error occurred.
181 * @param[in] full Full size window
182 * @param[in] sub Sub-window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000183 *
184 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100185 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000186arm_compute::Error error_on_invalid_subwindow(const char *function, const char *file, const int line,
187 const Window &full, const Window &sub);
188#define ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(f, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000189 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000190#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBWINDOW(f, s) \
191 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100192
Georgios Pinitas3faea252017-10-30 14:13:50 +0000193/** Return an error if the window can't be collapsed at the given dimension.
steniu01868e5412017-07-17 23:16:00 +0100194 *
195 * The window cannot be collapsed if the given dimension not equal to the full window's dimension or not start from 0.
196 *
197 * @param[in] function Function in which the error occurred.
198 * @param[in] file Name of the file where the error occurred.
199 * @param[in] line Line on which the error occurred.
200 * @param[in] full Full size window
201 * @param[in] window Window to be collapsed.
202 * @param[in] dim Dimension need to be checked.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000203 *
204 * @return Error
steniu01868e5412017-07-17 23:16:00 +0100205 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000206arm_compute::Error error_on_window_not_collapsable_at_dimension(const char *function, const char *file, const int line,
207 const Window &full, const Window &window, const int dim);
208#define ARM_COMPUTE_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000209 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 +0000210#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
211 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 +0100212
Georgios Pinitas3faea252017-10-30 14:13:50 +0000213/** Return an error if the passed coordinates have too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100214 *
215 * The coordinates have too many dimensions if any of the dimensions greater or equal to max_dim is different from 0.
216 *
217 * @param[in] function Function in which the error occurred.
218 * @param[in] file Name of the file where the error occurred.
219 * @param[in] line Line on which the error occurred.
220 * @param[in] pos Coordinates to validate
221 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000222 *
223 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100224 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000225arm_compute::Error error_on_coordinates_dimensions_gte(const char *function, const char *file, const int line,
226 const Coordinates &pos, unsigned int max_dim);
227#define ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000228 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000229#define ARM_COMPUTE_RETURN_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
230 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100231
Georgios Pinitas3faea252017-10-30 14:13:50 +0000232/** Return an error if the passed window has too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100233 *
234 * The window has too many dimensions if any of the dimension greater or equal to max_dim is different from 0.
235 *
236 * @param[in] function Function in which the error occurred.
237 * @param[in] file Name of the file where the error occurred.
238 * @param[in] line Line on which the error occurred.
239 * @param[in] win Window to validate
240 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000241 *
242 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100243 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000244arm_compute::Error error_on_window_dimensions_gte(const char *function, const char *file, const int line,
245 const Window &win, unsigned int max_dim);
246#define ARM_COMPUTE_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000247 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000248#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
249 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100250
Georgios Pinitas3faea252017-10-30 14:13:50 +0000251/** Return an error if the passed dimension objects differ.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100252 *
253 * @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] dim1 The first object to be compared.
257 * @param[in] dim2 The second object to be compared.
258 * @param[in] dims (Optional) Further allowed objects.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000259 *
260 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100261 */
262template <typename T, typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000263arm_compute::Error error_on_mismatching_dimensions(const char *function, const char *file, int line,
264 const Dimensions<T> &dim1, const Dimensions<T> &dim2, Ts &&... dims)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100265{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000266 ARM_COMPUTE_RETURN_ON_ERROR(detail::for_each_error(detail::compare_dimension<T>(dim1, function, file, line), dim2, std::forward<Ts>(dims)...));
267 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100268}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000269#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000270 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000271#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
272 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100273
Georgios Pinitas3faea252017-10-30 14:13:50 +0000274/** Return an error if the passed two tensor infos have different shapes from the given dimension
275 *
276 * @param[in] function Function in which the error occurred.
277 * @param[in] file Name of the file where the error occurred.
278 * @param[in] line Line on which the error occurred.
279 * @param[in] tensor_info_1 The first tensor info to be compared.
280 * @param[in] tensor_info_2 The second tensor info to be compared.
281 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
282 *
283 * @return Error
284 */
285template <typename... Ts>
286inline arm_compute::Error error_on_mismatching_shapes(const char *function, const char *file, const int line,
287 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
288{
289 return error_on_mismatching_shapes(function, file, line, 0U, tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)...);
290}
291/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100292 *
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] tensor_1 The first tensor to be compared.
297 * @param[in] tensor_2 The second tensor to be compared.
298 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000299 *
300 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100301 */
302template <typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000303inline arm_compute::Error error_on_mismatching_shapes(const char *function, const char *file, const int line,
304 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100305{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000306 return error_on_mismatching_shapes(function, file, line, 0U, tensor_1, tensor_2, std::forward<Ts>(tensors)...);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100307}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000308/** Return an error if the passed two tensors have different shapes from the given dimension
309 *
310 * @param[in] function Function in which the error occurred.
311 * @param[in] file Name of the file where the error occurred.
312 * @param[in] line Line on which the error occurred.
313 * @param[in] upper_dim The dimension from which to check.
314 * @param[in] tensor_info_1 The first tensor info to be compared.
315 * @param[in] tensor_info_2 The second tensor info to be compared.
316 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
317 *
318 * @return Error
319 */
320template <typename... Ts>
321inline arm_compute::Error error_on_mismatching_shapes(const char *function, const char *file, const int line,
322 unsigned int upper_dim, const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
323{
324 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_1 == nullptr, function, file, line);
325 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_2 == nullptr, function, file, line);
326 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 +0100327
Georgios Pinitas3faea252017-10-30 14:13:50 +0000328 const std::array < const ITensorInfo *, 2 + sizeof...(Ts) > tensors_info_array{ { tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)... } };
329 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(std::next(tensors_info_array.cbegin()), tensors_info_array.cend(), [&](const ITensorInfo * tensor_info)
330 {
331 return detail::have_different_dimensions((*tensors_info_array.cbegin())->tensor_shape(), tensor_info->tensor_shape(), upper_dim);
332 }),
333 function, file, line, "Tensors have different shapes");
334 return arm_compute::Error{};
335}
336/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100337 *
338 * @param[in] function Function in which the error occurred.
339 * @param[in] file Name of the file where the error occurred.
340 * @param[in] line Line on which the error occurred.
341 * @param[in] upper_dim The dimension from which to check.
342 * @param[in] tensor_1 The first tensor to be compared.
343 * @param[in] tensor_2 The second tensor to be compared.
344 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000345 *
346 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100347 */
348template <typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000349inline arm_compute::Error error_on_mismatching_shapes(const char *function, const char *file, const int line,
350 unsigned int upper_dim, const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100351{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000352 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_1 == nullptr, function, file, line);
353 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_2 == nullptr, function, file, line);
354 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
355 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(function, file, line, upper_dim, tensor_1->info(), tensor_2->info(),
356 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
357 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100358}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000359#define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000360 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000361#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(...) \
362 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100363
Georgios Pinitas3faea252017-10-30 14:13:50 +0000364/** Return an error if the passed two tensor infos have different data types
365 *
366 * @param[in] function Function in which the error occurred.
367 * @param[in] file Name of the file where the error occurred.
368 * @param[in] line Line on which the error occurred.
369 * @param[in] tensor_info The first tensor info to be compared.
370 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
371 *
372 * @return Error
373 */
374template <typename... Ts>
375inline arm_compute::Error error_on_mismatching_data_types(const char *function, const char *file, const int line,
376 const ITensorInfo *tensor_info, Ts... tensor_infos)
377{
378 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
379 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
380
381 DataType &&tensor_data_type = tensor_info->data_type();
382 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { std::forward<Ts>(tensor_infos)... } };
383 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
384 {
385 return tensor_info_obj->data_type() != tensor_data_type;
386 }),
387 function, file, line, "Tensors have different data types");
388 return arm_compute::Error{};
389}
390/** Return an error if the passed two tensors have different data types
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100391 *
392 * @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.
Georgios Pinitas0326eae2017-06-27 15:46:05 +0100395 * @param[in] tensor The first tensor to be compared.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100396 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000397 *
398 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100399 */
400template <typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000401inline arm_compute::Error error_on_mismatching_data_types(const char *function, const char *file, const int line,
402 const ITensor *tensor, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100403{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000404 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
405 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
406 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(function, file, line, tensor->info(),
407 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
408 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100409}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000410#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000411 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000412#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
413 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100414
Georgios Pinitas3faea252017-10-30 14:13:50 +0000415/** Return an error if the passed tensor infos have different fixed point data types or different fixed point positions
416 *
417 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
418 *
419 * @param[in] function Function in which the error occurred.
420 * @param[in] file Name of the file where the error occurred.
421 * @param[in] line Line on which the error occurred.
422 * @param[in] tensor_info_1 The first tensor info to be compared.
423 * @param[in] tensor_info_2 The second tensor info to be compared.
424 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
425 *
426 * @return Error
427 */
428template <typename... Ts>
429inline arm_compute::Error error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
430 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
431{
432 DataType &&first_data_type = tensor_info_1->data_type();
433 const int first_fixed_point_position = tensor_info_1->fixed_point_position();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100434
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000435 if(!is_data_type_fixed_point(first_data_type))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000436 {
437 return arm_compute::Error{};
438 }
439
440 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
441 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
442 {
443 return tensor_info->data_type() != first_data_type;
444 }),
445 function, file, line, "Tensors have different fixed point data types");
446 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
447 {
448 return tensor_info->fixed_point_position() != first_fixed_point_position;
449 }),
450 function, file, line, "Tensors have different fixed point positions");
451
452 return arm_compute::Error{};
453}
454/** 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 +0100455 *
456 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
457 *
458 * @param[in] function Function in which the error occurred.
459 * @param[in] file Name of the file where the error occurred.
460 * @param[in] line Line on which the error occurred.
461 * @param[in] tensor_1 The first tensor to be compared.
462 * @param[in] tensor_2 The second tensor to be compared.
463 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000464 *
465 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100466 */
467template <typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000468inline arm_compute::Error error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
469 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100470{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000471 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(function, file, line, tensor_1->info(), tensor_2->info(),
472 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
473 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100474}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000475#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000476 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000477#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
478 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100479
480/** Throw an error if the format of the passed tensor/multi-image does not match any of the formats provided.
481 *
482 * @param[in] function Function in which the error occurred.
483 * @param[in] file Name of the file where the error occurred.
484 * @param[in] line Line on which the error occurred.
485 * @param[in] object Tensor/multi-image to validate.
486 * @param[in] format First format allowed.
487 * @param[in] formats (Optional) Further allowed formats.
488 */
489template <typename T, typename F, typename... Fs>
490void error_on_format_not_in(const char *function, const char *file, const int line,
491 const T *object, F &&format, Fs &&... formats)
492{
493 ARM_COMPUTE_ERROR_ON_LOC(object == nullptr, function, file, line);
494
495 Format &&object_format = object->info()->format();
496 ARM_COMPUTE_UNUSED(object_format);
497
498 ARM_COMPUTE_ERROR_ON_LOC(object_format == Format::UNKNOWN, function, file, line);
499
500 const std::array<F, sizeof...(Fs)> formats_array{ { std::forward<Fs>(formats)... } };
501 ARM_COMPUTE_UNUSED(formats_array);
502
503 ARM_COMPUTE_ERROR_ON_LOC_MSG(object_format != format && std::none_of(formats_array.begin(), formats_array.end(), [&](const F & f)
504 {
505 return f == object_format;
506 }),
507 function, file, line, "Format %s not supported by this kernel", string_from_format(object_format).c_str());
508}
509#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t, ...) ::arm_compute::error_on_format_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
510
Georgios Pinitas3faea252017-10-30 14:13:50 +0000511/** Return an error if the data type of the passed tensor info does not match any of the data types provided.
512 *
513 * @param[in] function Function in which the error occurred.
514 * @param[in] file Name of the file where the error occurred.
515 * @param[in] line Line on which the error occurred.
516 * @param[in] tensor_info Tensor info to validate.
517 * @param[in] dt First data type allowed.
518 * @param[in] dts (Optional) Further allowed data types.
519 *
520 * @return Error
521 */
522template <typename T, typename... Ts>
523inline arm_compute::Error error_on_data_type_not_in(const char *function, const char *file, const int line,
524 const ITensorInfo *tensor_info, T &&dt, Ts &&... dts)
525{
526 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
527
528 const DataType &tensor_dt = tensor_info->data_type(); //NOLINT
529 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
530
531 const std::array<T, sizeof...(Ts)> dts_array{ { std::forward<Ts>(dts)... } };
532 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T & d)
533 {
534 return d == tensor_dt;
535 }),
536 function, file, line, "ITensor data type %s not supported by this kernel", string_from_data_type(tensor_dt).c_str());
537 return arm_compute::Error{};
538}
539/** 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 +0100540 *
541 * @param[in] function Function in which the error occurred.
542 * @param[in] file Name of the file where the error occurred.
543 * @param[in] line Line on which the error occurred.
544 * @param[in] tensor Tensor to validate.
545 * @param[in] dt First data type allowed.
546 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000547 *
548 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100549 */
550template <typename T, typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000551inline arm_compute::Error error_on_data_type_not_in(const char *function, const char *file, const int line,
552 const ITensor *tensor, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100553{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000554 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
555 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)...));
556 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100557}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000558#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000559 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 +0000560#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
561 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 +0100562
Georgios Pinitas3faea252017-10-30 14:13:50 +0000563/** 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.
564 *
565 * @param[in] function Function in which the error occurred.
566 * @param[in] file Name of the file where the error occurred.
567 * @param[in] line Line on which the error occurred.
568 * @param[in] tensor_info Tensor info to validate.
569 * @param[in] num_channels Number of channels to check
570 * @param[in] dt First data type allowed.
571 * @param[in] dts (Optional) Further allowed data types.
572 *
573 * @return Error
574 */
575template <typename T, typename... Ts>
576inline arm_compute::Error error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
577 const ITensorInfo *tensor_info, size_t num_channels, T &&dt, Ts &&... dts)
578{
579 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)...));
580 const size_t tensor_nc = tensor_info->num_channels();
581 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);
582 return arm_compute::Error{};
583}
584/** 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 +0100585 *
586 * @param[in] function Function in which the error occurred.
587 * @param[in] file Name of the file where the error occurred.
588 * @param[in] line Line on which the error occurred.
589 * @param[in] tensor Tensor to validate.
590 * @param[in] num_channels Number of channels to check
591 * @param[in] dt First data type allowed.
592 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000593 *
594 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100595 */
596template <typename T, typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000597inline arm_compute::Error error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
598 const ITensor *tensor, size_t num_channels, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100599{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000600 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
601 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)...));
602 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100603}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000604#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000605 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 +0000606#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
607 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 +0100608
Georgios Pinitas3faea252017-10-30 14:13:50 +0000609/** Return an error if the tensor is not 2D.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100610 *
611 * @param[in] function Function in which the error occurred.
612 * @param[in] file Name of the file where the error occurred.
613 * @param[in] line Line on which the error occurred.
614 * @param[in] tensor Tensor to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000615 *
616 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100617 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000618arm_compute::Error error_on_tensor_not_2d(const char *function, const char *file, const int line,
619 const ITensor *tensor);
620#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000621 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000622#define ARM_COMPUTE_RETURN_ERROR_ON_TENSOR_NOT_2D(t) \
623 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100624
Georgios Pinitas3faea252017-10-30 14:13:50 +0000625/** Return an error if the channel is not in channels.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100626 *
627 * @param[in] function Function in which the error occurred.
628 * @param[in] file Name of the file where the error occurred.
629 * @param[in] line Line on which the error occurred.
630 * @param[in] cn Input channel
631 * @param[in] channel First channel allowed.
632 * @param[in] channels (Optional) Further allowed channels.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000633 *
634 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100635 */
636template <typename T, typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000637inline arm_compute::Error error_on_channel_not_in(const char *function, const char *file, const int line,
638 T cn, T &&channel, Ts &&... channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100639{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000640 ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100641
642 const std::array<T, sizeof...(Ts)> channels_array{ { std::forward<Ts>(channels)... } };
Georgios Pinitas3faea252017-10-30 14:13:50 +0000643 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 +0100644 {
645 return f == cn;
646 }),
647 function, file, line);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000648 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100649}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000650#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000651 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 +0000652#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
653 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 +0100654
Georgios Pinitas3faea252017-10-30 14:13:50 +0000655/** Return an error if the channel is not in format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100656 *
657 * @param[in] function Function in which the error occurred.
658 * @param[in] file Name of the file where the error occurred.
659 * @param[in] line Line on which the error occurred.
660 * @param[in] fmt Input channel
661 * @param[in] cn First channel allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000662 *
663 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100664 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000665arm_compute::Error error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
666 Format fmt, Channel cn);
667#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000668 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 +0000669#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
670 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 +0100671
Georgios Pinitas3faea252017-10-30 14:13:50 +0000672/** Return an error if the @ref IMultiHOG container is invalid
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100673 *
674 * An @ref IMultiHOG container is invalid if:
675 *
676 * -# it is a nullptr
677 * -# it doesn't contain models
678 * -# it doesn't have the HOG data objects with the same phase_type, normalization_type and l2_hyst_threshold (if normalization_type == L2HYS_NORM)
679 *
680 * @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] multi_hog IMultiHOG container to validate
Georgios Pinitas3faea252017-10-30 14:13:50 +0000684 *
685 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100686 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000687arm_compute::Error error_on_invalid_multi_hog(const char *function, const char *file, const int line,
688 const IMultiHOG *multi_hog);
689#define ARM_COMPUTE_ERROR_ON_INVALID_MULTI_HOG(m) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000690 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000691#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_MULTI_HOG(m) \
692 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100693
Georgios Pinitas3faea252017-10-30 14:13:50 +0000694/** Return an error if the kernel is not configured.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100695 *
696 * @param[in] function Function in which the error occurred.
697 * @param[in] file Name of the file where the error occurred.
698 * @param[in] line Line on which the error occurred.
699 * @param[in] kernel Kernel to validate.
700 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000701arm_compute::Error error_on_unconfigured_kernel(const char *function, const char *file, const int line,
702 const IKernel *kernel);
703#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000704 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000705#define ARM_COMPUTE_RETURN_ERROR_ON_UNCONFIGURED_KERNEL(k) \
706 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100707
Georgios Pinitas3faea252017-10-30 14:13:50 +0000708/** Return an error if if the coordinates and shape of the subtensor are within the parent tensor.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100709 *
710 * @param[in] function Function in which the error occurred.
711 * @param[in] file Name of the file where the error occurred.
712 * @param[in] line Line on which the error occurred.
713 * @param[in] parent_shape Parent tensor shape
714 * @param[in] coords Coordinates inside the parent tensor where the first element of the subtensor is
715 * @param[in] shape Shape of the subtensor
Georgios Pinitas3faea252017-10-30 14:13:50 +0000716 *
717 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100718 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000719arm_compute::Error error_on_invalid_subtensor(const char *function, const char *file, const int line,
720 const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape);
721#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000722 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000723#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
724 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100725
Georgios Pinitas3faea252017-10-30 14:13:50 +0000726/** 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 +0100727 *
728 * @param[in] function Function in which the error occurred.
729 * @param[in] file Name of the file where the error occurred.
730 * @param[in] line Line on which the error occurred.
731 * @param[in] parent_valid_region Parent valid region.
732 * @param[in] valid_region Valid region of subtensor.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000733 *
734 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100735 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000736arm_compute::Error error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
737 const ValidRegion &parent_valid_region, const ValidRegion &valid_region);
738#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000739 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 +0000740#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
741 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 +0100742
Georgios Pinitas3faea252017-10-30 14:13:50 +0000743/** Return an error if the input fixed-point positions are different.
744 *
745 * @param[in] function Function in which the error occurred.
746 * @param[in] file Name of the file where the error occurred.
747 * @param[in] line Line on which the error occurred.
748 * @param[in] tensor_info_1 The first tensor info to be compared.
749 * @param[in] tensor_info_2 The second tensor info to be compared.
750 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
751 *
752 * @return Error
753 */
754template <typename... Ts>
755inline arm_compute::Error error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
756 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
757{
758 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_info_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
759 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_info_array.begin(), tensor_info_array.end(), [&](const ITensorInfo * tensor_info)
760 {
761 return tensor_info->fixed_point_position() != tensor_info_1->fixed_point_position();
762 }),
763 function, file, line, "Tensors have different fixed-point positions");
764 return arm_compute::Error{};
765}
766/** Return an error if the input fixed-point positions are different.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100767 *
768 * @param[in] function Function in which the error occurred.
769 * @param[in] file Name of the file where the error occurred.
770 * @param[in] line Line on which the error occurred.
771 * @param[in] tensor_1 The first tensor to be compared.
772 * @param[in] tensor_2 The second tensor to be compared.
773 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000774 *
775 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100776 */
777template <typename... Ts>
Georgios Pinitas3faea252017-10-30 14:13:50 +0000778inline arm_compute::Error error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
779 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100780{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000781 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point_position(function, file, line, tensor_1->info(), tensor_2->info(),
782 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
783 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100784}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000785#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000786 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 +0000787#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
788 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 +0100789
Georgios Pinitas3faea252017-10-30 14:13:50 +0000790/** Return an error if the fixed-point value is not representable in the specified Q format.
791 *
792 * @param[in] function Function in which the error occurred.
793 * @param[in] file Name of the file where the error occurred.
794 * @param[in] line Line on which the error occurred.
795 * @param[in] value The floating point value to be checked.
796 * @param[in] tensor_info Input tensor info that has information on data type and fixed-point position.
797 *
798 * @return Error
799 */
800inline arm_compute::Error error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
801 float value, const ITensorInfo *tensor_info)
802{
803 const int fixed_point_position = tensor_info->fixed_point_position();
804 const DataType dt = tensor_info->data_type();
805 const unsigned int q_max_range = 0xFFFFFFFFu >> (((sizeof(unsigned int) - element_size_from_data_type(dt)) * 8) + 1);
806 const float max_range = q_max_range / (static_cast<float>(1 << fixed_point_position));
807
808 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(value > max_range, function, file, line,
809 "Value %f is not representable in %s with fixed-point position %d", value, string_from_data_type(dt).c_str(), fixed_point_position);
810 return arm_compute::Error{};
811}
812/** 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 +0100813 *
814 * @param[in] function Function in which the error occurred.
815 * @param[in] file Name of the file where the error occurred.
816 * @param[in] line Line on which the error occurred.
817 * @param[in] value The floating point value to be checked.
818 * @param[in] tensor Input tensor that has information on data type and fixed-point position.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000819 *
820 * @return Error
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100821 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000822inline arm_compute::Error error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
823 float value, const ITensor *tensor)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100824{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000825 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
826 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_value_not_representable_in_fixed_point(function, file, line, value, tensor->info()));
827 return arm_compute::Error{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100828}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000829#define ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000830 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 +0000831#define ARM_COMPUTE_RETURN_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
832 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 +0100833}
834#endif /* __ARM_COMPUTE_VALIDATE_H__*/