1 /*
2 * Copyright (c) 2016-2021 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/IKernel.h"
29 #include "arm_compute/core/ITensor.h"
30 #include "arm_compute/core/Window.h"
31
32 #include <algorithm>
33
34 namespace arm_compute
35 {
36 namespace detail
37 {
38 /* Check whether two dimension objects differ.
39 *
40 * @param[in] dim1 First object to be compared.
41 * @param[in] dim2 Second object to be compared.
42 * @param[in] upper_dim The dimension from which to check.
43 *
44 * @return Return true if the two objects are different.
45 */
46 template <typename T>
have_different_dimensions(const Dimensions<T> & dim1,const Dimensions<T> & dim2,unsigned int upper_dim)47 inline bool have_different_dimensions(const Dimensions<T> &dim1, const Dimensions<T> &dim2, unsigned int upper_dim)
48 {
49 for(unsigned int i = upper_dim; i < arm_compute::Dimensions<T>::num_max_dimensions; ++i)
50 {
51 if(dim1[i] != dim2[i])
52 {
53 return true;
54 }
55 }
56
57 return false;
58 }
59
60 /** Function to compare two @ref Dimensions objects and throw an error on mismatch.
61 *
62 * @param[in] dim Object to compare against.
63 * @param[in] function Function in which the error occurred.
64 * @param[in] file File in which the error occurred.
65 * @param[in] line Line in which the error occurred.
66 */
67 template <typename T>
68 class compare_dimension
69 {
70 public:
71 /** Construct a comparison function.
72 *
73 * @param[in] dim Dimensions to compare.
74 * @param[in] function Source function. Used for error reporting.
75 * @param[in] file Source code file. Used for error reporting.
76 * @param[in] line Source code line. Used for error reporting.
77 */
compare_dimension(const Dimensions<T> & dim,const char * function,const char * file,int line)78 compare_dimension(const Dimensions<T> &dim, const char *function, const char *file, int line)
79 : _dim{ dim }, _function{ function }, _file{ file }, _line{ line }
80 {
81 }
82
83 /** Compare the given object against the stored one.
84 *
85 * @param[in] dim To be compared object.
86 *
87 * @return a status.
88 */
operator()89 arm_compute::Status operator()(const Dimensions<T> &dim)
90 {
91 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(have_different_dimensions(_dim, dim, 0), _function, _file, _line,
92 "Objects have different dimensions");
93 return arm_compute::Status{};
94 }
95
96 private:
97 const Dimensions<T> &_dim;
98 const char *const _function;
99 const char *const _file;
100 const int _line;
101 };
102
103 template <typename F>
for_each_error(F &&)104 inline arm_compute::Status for_each_error(F &&)
105 {
106 return arm_compute::Status{};
107 }
108
109 template <typename F, typename T, typename... Ts>
for_each_error(F && func,T && arg,Ts &&...args)110 inline arm_compute::Status for_each_error(F &&func, T &&arg, Ts &&... args)
111 {
112 ARM_COMPUTE_RETURN_ON_ERROR(func(arg));
113 ARM_COMPUTE_RETURN_ON_ERROR(for_each_error(func, args...));
114 return arm_compute::Status{};
115 }
116
117 /** Get the info for a tensor, dummy struct */
118 template <typename T>
119 struct get_tensor_info_t;
120 /** Get the info for a tensor */
121 template <>
122 struct get_tensor_info_t<ITensorInfo *>
123 {
124 /** Get the info for a tensor.
125 *
126 * @param[in] tensor Tensor.
127 *
128 * @return tensor info.
129 */
130 ITensorInfo *operator()(const ITensor *tensor)
131 {
132 return tensor->info();
133 }
134 };
135 } // namespace detail
136
137 /** Create an error if one of the pointers is a nullptr.
138 *
139 * @param[in] function Function in which the error occurred.
140 * @param[in] file Name of the file where the error occurred.
141 * @param[in] line Line on which the error occurred.
142 * @param[in] pointers Pointers to check against nullptr.
143 *
144 * @return Status
145 */
146 template <typename... Ts>
147 inline arm_compute::Status error_on_nullptr(const char *function, const char *file, const int line, Ts &&... pointers)
148 {
149 const std::array<const void *, sizeof...(Ts)> pointers_array{ { std::forward<Ts>(pointers)... } };
150 bool has_nullptr = std::any_of(pointers_array.begin(), pointers_array.end(), [&](const void *ptr)
151 {
152 return (ptr == nullptr);
153 });
154 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(has_nullptr, function, file, line, "Nullptr object!");
155 return arm_compute::Status{};
156 }
157 #define ARM_COMPUTE_ERROR_ON_NULLPTR(...) \
158 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
159 #define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...) \
160 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
161
162 /** Return an error if the passed window is invalid.
163 *
164 * The subwindow is invalid if:
165 * - It is not a valid window.
166 * - Its dimensions don't match the full window's ones
167 * - The step for each of its dimension is not identical to the corresponding one of the full window.
168 *
169 * @param[in] function Function in which the error occurred.
170 * @param[in] file Name of the file where the error occurred.
171 * @param[in] line Line on which the error occurred.
172 * @param[in] full Full size window
173 * @param[in] win Window to validate.
174 *
175 * @return Status
176 */
177 arm_compute::Status error_on_mismatching_windows(const char *function, const char *file, const int line,
178 const Window &full, const Window &win);
179 #define ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
180 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
181 #define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
182 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
183
184 /** Return an error if the passed subwindow is invalid.
185 *
186 * The subwindow is invalid if:
187 * - It is not a valid window.
188 * - It is not fully contained inside the full window
189 * - The step for each of its dimension is not identical to the corresponding one of the full window.
190 *
191 * @param[in] function Function in which the error occurred.
192 * @param[in] file Name of the file where the error occurred.
193 * @param[in] line Line on which the error occurred.
194 * @param[in] full Full size window
195 * @param[in] sub Sub-window to validate.
196 *
197 * @return Status
198 */
199 arm_compute::Status error_on_invalid_subwindow(const char *function, const char *file, const int line,
200 const Window &full, const Window &sub);
201 #define ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(f, s) \
202 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
203 #define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBWINDOW(f, s) \
204 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
205
206 /** Return an error if the window can't be collapsed at the given dimension.
207 *
208 * The window cannot be collapsed if the given dimension not equal to the full window's dimension or not start from 0.
209 *
210 * @param[in] function Function in which the error occurred.
211 * @param[in] file Name of the file where the error occurred.
212 * @param[in] line Line on which the error occurred.
213 * @param[in] full Full size window
214 * @param[in] window Window to be collapsed.
215 * @param[in] dim Dimension need to be checked.
216 *
217 * @return Status
218 */
219 arm_compute::Status error_on_window_not_collapsable_at_dimension(const char *function, const char *file, const int line,
220 const Window &full, const Window &window, const int dim);
221 #define ARM_COMPUTE_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
222 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
223 #define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
224 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
225
226 /** Return an error if the passed coordinates have too many dimensions.
227 *
228 * The coordinates have too many dimensions if any of the dimensions greater or equal to max_dim is different from 0.
229 *
230 * @param[in] function Function in which the error occurred.
231 * @param[in] file Name of the file where the error occurred.
232 * @param[in] line Line on which the error occurred.
233 * @param[in] pos Coordinates to validate
234 * @param[in] max_dim Maximum number of dimensions allowed.
235 *
236 * @return Status
237 */
238 arm_compute::Status error_on_coordinates_dimensions_gte(const char *function, const char *file, const int line,
239 const Coordinates &pos, unsigned int max_dim);
240 #define ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
241 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
242 #define ARM_COMPUTE_RETURN_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
243 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
244
245 /** Return an error if the passed window has too many dimensions.
246 *
247 * The window has too many dimensions if any of the dimension greater or equal to max_dim is different from 0.
248 *
249 * @param[in] function Function in which the error occurred.
250 * @param[in] file Name of the file where the error occurred.
251 * @param[in] line Line on which the error occurred.
252 * @param[in] win Window to validate
253 * @param[in] max_dim Maximum number of dimensions allowed.
254 *
255 * @return Status
256 */
257 arm_compute::Status error_on_window_dimensions_gte(const char *function, const char *file, const int line,
258 const Window &win, unsigned int max_dim);
259 #define ARM_COMPUTE_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
260 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
261 #define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
262 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
263
264 /** Return an error if the passed dimension objects differ.
265 *
266 * @param[in] function Function in which the error occurred.
267 * @param[in] file Name of the file where the error occurred.
268 * @param[in] line Line on which the error occurred.
269 * @param[in] dim1 The first object to be compared.
270 * @param[in] dim2 The second object to be compared.
271 * @param[in] dims (Optional) Further allowed objects.
272 *
273 * @return Status
274 */
275 template <typename T, typename... Ts>
276 arm_compute::Status error_on_mismatching_dimensions(const char *function, const char *file, int line,
277 const Dimensions<T> &dim1, const Dimensions<T> &dim2, Ts &&... dims)
278 {
279 ARM_COMPUTE_RETURN_ON_ERROR(detail::for_each_error(detail::compare_dimension<T>(dim1, function, file, line), dim2, std::forward<Ts>(dims)...));
280 return arm_compute::Status{};
281 }
282 #define ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
283 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
284 #define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
285 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
286
287 /** Return an error if the passed tensor objects are not even.
288 *
289 * @param[in] function Function in which the error occurred.
290 * @param[in] file Name of the file where the error occurred.
291 * @param[in] line Line on which the error occurred.
292 * @param[in] format Format to check if odd shape is allowed
293 * @param[in] tensor1 The first object to be compared for odd shape.
294 * @param[in] tensors (Optional) Further allowed objects.
295 *
296 * @return Status
297 */
298 template <typename... Ts>
299 arm_compute::Status error_on_tensors_not_even(const char *function, const char *file, int line,
300 const Format &format, const ITensor *tensor1, Ts... tensors)
301 {
302 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor1 == nullptr, function, file, line);
303 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
304 const std::array < const ITensor *, 1 + sizeof...(Ts) > tensors_info_array{ { tensor1, std::forward<Ts>(tensors)... } };
305 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_info_array.cbegin(), tensors_info_array.cend(), [&](const ITensor * tensor)
306 {
307 const TensorShape correct_shape = adjust_odd_shape(tensor->info()->tensor_shape(), format);
308 return detail::have_different_dimensions(tensor->info()->tensor_shape(), correct_shape, 2);
309 }),
310 function, file, line, "Tensor shape has odd dimensions");
311 return arm_compute::Status{};
312 }
313
314 #define ARM_COMPUTE_ERROR_ON_TENSORS_NOT_EVEN(...) \
315 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
316 #define ARM_COMPUTE_RETURN_ERROR_ON_TENSORS_NOT_EVEN(...) \
317 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
318
319 /** Return an error if the passed tensor objects are not sub-sampled.
320 *
321 * @param[in] function Function in which the error occurred.
322 * @param[in] file Name of the file where the error occurred.
323 * @param[in] line Line on which the error occurred.
324 * @param[in] format Format to check if sub-sampling allowed.
325 * @param[in] shape The tensor shape to calculate sub-sampling from.
326 * @param[in] tensor1 The first object to be compared.
327 * @param[in] tensors (Optional) Further allowed objects.
328 *
329 * @return Status
330 */
331 template <typename... Ts>
332 arm_compute::Status error_on_tensors_not_subsampled(const char *function, const char *file, int line,
333 const Format &format, const TensorShape &shape, const ITensor *tensor1, Ts... tensors)
334 {
335 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor1 == nullptr, function, file, line);
336 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
337 const TensorShape sub2_shape = calculate_subsampled_shape(shape, format);
338 const std::array < const ITensor *, 1 + sizeof...(Ts) > tensors_info_array{ { tensor1, std::forward<Ts>(tensors)... } };
339 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_info_array.cbegin(), tensors_info_array.cend(), [&](const ITensor * tensor)
340 {
341 return detail::have_different_dimensions(tensor->info()->tensor_shape(), sub2_shape, 2);
342 }),
343 function, file, line, "Tensor shape has mismatch dimensions for sub-sampling");
344 return arm_compute::Status{};
345 }
346
347 #define ARM_COMPUTE_ERROR_ON_TENSORS_NOT_SUBSAMPLED(...) \
348 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensors_not_subsampled(__func__, __FILE__, __LINE__, __VA_ARGS__))
349 #define ARM_COMPUTE_RETURN_ERROR_ON_TENSORS_NOT_SUBSAMPLED(...) \
350 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensors_not_subsampled(__func__, __FILE__, __LINE__, __VA_ARGS__))
351
352 /** Return an error if the passed two tensor infos have different shapes from the given dimension
353 *
354 * @param[in] function Function in which the error occurred.
355 * @param[in] file Name of the file where the error occurred.
356 * @param[in] line Line on which the error occurred.
357 * @param[in] tensor_info_1 The first tensor info to be compared.
358 * @param[in] tensor_info_2 The second tensor info to be compared.
359 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
360 *
361 * @return Status
362 */
363 template <typename... Ts>
364 inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
365 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
366 {
367 return error_on_mismatching_shapes(function, file, line, 0U, tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)...);
368 }
369 /** Return an error if the passed two tensors have different shapes from the given dimension
370 *
371 * @param[in] function Function in which the error occurred.
372 * @param[in] file Name of the file where the error occurred.
373 * @param[in] line Line on which the error occurred.
374 * @param[in] tensor_1 The first tensor to be compared.
375 * @param[in] tensor_2 The second tensor to be compared.
376 * @param[in] tensors (Optional) Further allowed tensors.
377 *
378 * @return Status
379 */
380 template <typename... Ts>
381 inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
382 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
383 {
384 return error_on_mismatching_shapes(function, file, line, 0U, tensor_1, tensor_2, std::forward<Ts>(tensors)...);
385 }
386 /** Return an error if the passed two tensors have different shapes from the given dimension
387 *
388 * @param[in] function Function in which the error occurred.
389 * @param[in] file Name of the file where the error occurred.
390 * @param[in] line Line on which the error occurred.
391 * @param[in] upper_dim The dimension from which to check.
392 * @param[in] tensor_info_1 The first tensor info to be compared.
393 * @param[in] tensor_info_2 The second tensor info to be compared.
394 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
395 *
396 * @return Status
397 */
398 template <typename... Ts>
399 inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
400 unsigned int upper_dim, const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
401 {
402 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_1 == nullptr, function, file, line);
403 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_2 == nullptr, function, file, line);
404 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
405
406 const std::array < const ITensorInfo *, 2 + sizeof...(Ts) > tensors_info_array{ { tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)... } };
407 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(std::next(tensors_info_array.cbegin()), tensors_info_array.cend(), [&](const ITensorInfo * tensor_info)
408 {
409 return detail::have_different_dimensions((*tensors_info_array.cbegin())->tensor_shape(), tensor_info->tensor_shape(), upper_dim);
410 }),
411 function, file, line, "Tensors have different shapes");
412 return arm_compute::Status{};
413 }
414 /** Return an error if the passed two tensors have different shapes from the given dimension
415 *
416 * @param[in] function Function in which the error occurred.
417 * @param[in] file Name of the file where the error occurred.
418 * @param[in] line Line on which the error occurred.
419 * @param[in] upper_dim The dimension from which to check.
420 * @param[in] tensor_1 The first tensor to be compared.
421 * @param[in] tensor_2 The second tensor to be compared.
422 * @param[in] tensors (Optional) Further allowed tensors.
423 *
424 * @return Status
425 */
426 template <typename... Ts>
427 inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
428 unsigned int upper_dim, const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
429 {
430 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_1 == nullptr, function, file, line);
431 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_2 == nullptr, function, file, line);
432 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
433 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(function, file, line, upper_dim, tensor_1->info(), tensor_2->info(),
434 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
435 return arm_compute::Status{};
436 }
437 #define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...) \
438 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
439 #define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(...) \
440 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
441
442 /** Return an error if the passed tensor infos have different data layouts
443 *
444 * @param[in] function Function in which the error occurred.
445 * @param[in] file Name of the file where the error occurred.
446 * @param[in] line Line on which the error occurred.
447 * @param[in] tensor_info The first tensor info to be compared.
448 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
449 *
450 * @return Status
451 */
452 template <typename... Ts>
453 inline arm_compute::Status error_on_mismatching_data_layouts(const char *function, const char *file, const int line,
454 const ITensorInfo *tensor_info, Ts... tensor_infos)
455 {
456 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
457 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
458
459 DataLayout &&tensor_data_layout = tensor_info->data_layout();
460 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { std::forward<Ts>(tensor_infos)... } };
461 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
462 {
463 return tensor_info_obj->data_layout() != tensor_data_layout;
464 }),
465 function, file, line, "Tensors have different data layouts");
466 return arm_compute::Status{};
467 }
468 /** Return an error if the passed tensors have different data layouts
469 *
470 * @param[in] function Function in which the error occurred.
471 * @param[in] file Name of the file where the error occurred.
472 * @param[in] line Line on which the error occurred.
473 * @param[in] tensor The first tensor to be compared.
474 * @param[in] tensors (Optional) Further allowed tensors.
475 *
476 * @return Status
477 */
478 template <typename... Ts>
479 inline arm_compute::Status error_on_mismatching_data_layouts(const char *function, const char *file, const int line,
480 const ITensor *tensor, Ts... tensors)
481 {
482 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
483 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
484 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_layouts(function, file, line, tensor->info(),
485 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
486 return arm_compute::Status{};
487 }
488 #define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
489 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
490 #define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
491 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
492
493 /** Return an error if the passed two tensor infos have different data types
494 *
495 * @param[in] function Function in which the error occurred.
496 * @param[in] file Name of the file where the error occurred.
497 * @param[in] line Line on which the error occurred.
498 * @param[in] tensor_info The first tensor info to be compared.
499 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
500 *
501 * @return Status
502 */
503 template <typename... Ts>
504 inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
505 const ITensorInfo *tensor_info, Ts... tensor_infos)
506 {
507 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
508 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
509
510 DataType &&tensor_data_type = tensor_info->data_type();
511 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { std::forward<Ts>(tensor_infos)... } };
512 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
513 {
514 return tensor_info_obj->data_type() != tensor_data_type;
515 }),
516 function, file, line, "Tensors have different data types");
517 return arm_compute::Status{};
518 }
519 /** Return an error if the passed two tensors have different data types
520 *
521 * @param[in] function Function in which the error occurred.
522 * @param[in] file Name of the file where the error occurred.
523 * @param[in] line Line on which the error occurred.
524 * @param[in] tensor The first tensor to be compared.
525 * @param[in] tensors (Optional) Further allowed tensors.
526 *
527 * @return Status
528 */
529 template <typename... Ts>
530 inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
531 const ITensor *tensor, Ts... tensors)
532 {
533 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
534 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
535 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(function, file, line, tensor->info(),
536 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
537 return arm_compute::Status{};
538 }
539 #define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
540 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
541 #define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
542 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
543
544 /** Return an error if the passed tensor infos have different asymmetric quantized data types or different quantization info
545 *
546 * @note: If the first tensor info doesn't have asymmetric quantized data type, the function returns without throwing an error
547 *
548 * @param[in] function Function in which the error occurred.
549 * @param[in] file Name of the file where the error occurred.
550 * @param[in] line Line on which the error occurred.
551 * @param[in] tensor_info_1 The first tensor info to be compared.
552 * @param[in] tensor_info_2 The second tensor info to be compared.
553 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
554 *
555 * @return Status
556 */
557 template <typename... Ts>
558 inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
559 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
560 {
561 DataType &&first_data_type = tensor_info_1->data_type();
562 const QuantizationInfo first_quantization_info = tensor_info_1->quantization_info();
563
564 if(!is_data_type_quantized(first_data_type))
565 {
566 return arm_compute::Status{};
567 }
568
569 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
570 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
571 {
572 return tensor_info->data_type() != first_data_type;
573 }),
574 function, file, line, "Tensors have different asymmetric quantized data types");
575 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
576 {
577 return tensor_info->quantization_info() != first_quantization_info;
578 }),
579 function, file, line, "Tensors have different quantization information");
580
581 return arm_compute::Status{};
582 }
583 /** Return an error if the passed tensor have different asymmetric quantized data types or different quantization info
584 *
585 * @note: If the first tensor doesn't have asymmetric quantized data type, the function returns without throwing an error
586 *
587 * @param[in] function Function in which the error occurred.
588 * @param[in] file Name of the file where the error occurred.
589 * @param[in] line Line on which the error occurred.
590 * @param[in] tensor_1 The first tensor to be compared.
591 * @param[in] tensor_2 The second tensor to be compared.
592 * @param[in] tensors (Optional) Further allowed tensors.
593 *
594 * @return Status
595 */
596 template <typename... Ts>
597 inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
598 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
599 {
600 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(function, file, line, tensor_1->info(), tensor_2->info(),
601 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
602 return arm_compute::Status{};
603 }
604 #define ARM_COMPUTE_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
605 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
606 #define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
607 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
608
609 /** Throw an error if the format of the passed tensor/multi-image does not match any of the formats provided.
610 *
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] object Tensor/multi-image to validate.
615 * @param[in] format First format allowed.
616 * @param[in] formats (Optional) Further allowed formats.
617 */
618 template <typename T, typename F, typename... Fs>
619 void error_on_format_not_in(const char *function, const char *file, const int line,
620 const T *object, F &&format, Fs &&... formats)
621 {
622 ARM_COMPUTE_ERROR_ON_LOC(object == nullptr, function, file, line);
623
624 Format &&object_format = object->info()->format();
625 ARM_COMPUTE_UNUSED(object_format);
626
627 ARM_COMPUTE_ERROR_ON_LOC(object_format == Format::UNKNOWN, function, file, line);
628
629 const std::array<F, sizeof...(Fs)> formats_array{ { std::forward<Fs>(formats)... } };
630 ARM_COMPUTE_UNUSED(formats_array);
631
632 ARM_COMPUTE_ERROR_ON_LOC_MSG(object_format != format && std::none_of(formats_array.begin(), formats_array.end(), [&](const F & f)
633 {
634 return f == object_format;
635 }),
636 function, file, line, "Format %s not supported by this kernel", string_from_format(object_format).c_str());
637 ARM_COMPUTE_UNUSED(function, format, file, line);
638 }
639 #define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t, ...) ::arm_compute::error_on_format_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
640
641 /** Return an error if the data type of the passed tensor info does not match any of the data types provided.
642 *
643 * @param[in] function Function in which the error occurred.
644 * @param[in] file Name of the file where the error occurred.
645 * @param[in] line Line on which the error occurred.
646 * @param[in] tensor_info Tensor info to validate.
647 * @param[in] dt First data type allowed.
648 * @param[in] dts (Optional) Further allowed data types.
649 *
650 * @return Status
651 */
652 template <typename T, typename... Ts>
653 inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
654 const ITensorInfo *tensor_info, T &&dt, Ts &&... dts)
655 {
656 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
657
658 const DataType &tensor_dt = tensor_info->data_type(); //NOLINT
659 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
660
661 const std::array<T, sizeof...(Ts)> dts_array{ { std::forward<Ts>(dts)... } };
662 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG_VAR(tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T & d)
663 {
664 return d == tensor_dt;
665 }),
666 function, file, line, "ITensor data type %s not supported by this kernel", string_from_data_type(tensor_dt).c_str());
667 return arm_compute::Status{};
668 }
669 /** Return an error if the data type of the passed tensor does not match any of the data types provided.
670 *
671 * @param[in] function Function in which the error occurred.
672 * @param[in] file Name of the file where the error occurred.
673 * @param[in] line Line on which the error occurred.
674 * @param[in] tensor Tensor to validate.
675 * @param[in] dt First data type allowed.
676 * @param[in] dts (Optional) Further allowed data types.
677 *
678 * @return Status
679 */
680 template <typename T, typename... Ts>
681 inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
682 const ITensor *tensor, T &&dt, Ts &&... dts)
683 {
684 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
685 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)...));
686 return arm_compute::Status{};
687 }
688 #define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
689 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_data_type_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
690 #define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
691 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
692
693 /** Return an error if the data layout of the passed tensor info does not match any of the data layouts provided.
694 *
695 * @param[in] function Function in which the error occurred.
696 * @param[in] file Name of the file where the error occurred.
697 * @param[in] line Line on which the error occurred.
698 * @param[in] tensor_info Tensor info to validate.
699 * @param[in] dl First data layout allowed.
700 * @param[in] dls (Optional) Further allowed data layouts.
701 *
702 * @return Status
703 */
704 template <typename T, typename... Ts>
705 inline arm_compute::Status error_on_data_layout_not_in(const char *function, const char *file, const int line,
706 const ITensorInfo *tensor_info, T &&dl, Ts &&... dls)
707 {
708 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
709
710 const DataLayout &tensor_dl = tensor_info->data_layout(); //NOLINT
711 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dl == DataLayout::UNKNOWN, function, file, line);
712
713 const std::array<T, sizeof...(Ts)> dls_array{ { std::forward<Ts>(dls)... } };
714 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG_VAR(tensor_dl != dl && std::none_of(dls_array.begin(), dls_array.end(), [&](const T & l)
715 {
716 return l == tensor_dl;
717 }),
718 function, file, line, "ITensor data layout %s not supported by this kernel", string_from_data_layout(tensor_dl).c_str());
719 return arm_compute::Status{};
720 }
721 /** Return an error if the data layout of the passed tensor does not match any of the data layout provided.
722 *
723 * @param[in] function Function in which the error occurred.
724 * @param[in] file Name of the file where the error occurred.
725 * @param[in] line Line on which the error occurred.
726 * @param[in] tensor Tensor to validate.
727 * @param[in] dl First data layout allowed.
728 * @param[in] dls (Optional) Further allowed data layouts.
729 *
730 * @return Status
731 */
732 template <typename T, typename... Ts>
733 inline arm_compute::Status error_on_data_layout_not_in(const char *function, const char *file, const int line,
734 const ITensor *tensor, T &&dl, Ts &&... dls)
735 {
736 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
737 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_layout_not_in(function, file, line, tensor->info(), std::forward<T>(dl), std::forward<Ts>(dls)...));
738 return arm_compute::Status{};
739 }
740 #define ARM_COMPUTE_ERROR_ON_DATA_LAYOUT_NOT_IN(t, ...) \
741 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_data_layout_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
742 #define ARM_COMPUTE_RETURN_ERROR_ON_DATA_LAYOUT_NOT_IN(t, ...) \
743 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_layout_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
744
745 /** 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.
746 *
747 * @param[in] function Function in which the error occurred.
748 * @param[in] file Name of the file where the error occurred.
749 * @param[in] line Line on which the error occurred.
750 * @param[in] tensor_info Tensor info to validate.
751 * @param[in] num_channels Number of channels to check
752 * @param[in] dt First data type allowed.
753 * @param[in] dts (Optional) Further allowed data types.
754 *
755 * @return Status
756 */
757 template <typename T, typename... Ts>
758 inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
759 const ITensorInfo *tensor_info, size_t num_channels, T &&dt, Ts &&... dts)
760 {
761 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)...));
762 const size_t tensor_nc = tensor_info->num_channels();
763 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG_VAR(tensor_nc != num_channels, function, file, line, "Number of channels %zu. Required number of channels %zu", tensor_nc, num_channels);
764 return arm_compute::Status{};
765 }
766 /** 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.
767 *
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 Tensor to validate.
772 * @param[in] num_channels Number of channels to check
773 * @param[in] dt First data type allowed.
774 * @param[in] dts (Optional) Further allowed data types.
775 *
776 * @return Status
777 */
778 template <typename T, typename... Ts>
779 inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
780 const ITensor *tensor, size_t num_channels, T &&dt, Ts &&... dts)
781 {
782 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
783 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)...));
784 return arm_compute::Status{};
785 }
786 #define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
787 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
788 #define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
789 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
790
791 /** Return an error if the data type of the passed tensor info is FP16 and FP16 extension is not supported by the device.
792 *
793 * @param[in] function Function in which the error occurred.
794 * @param[in] file Name of the file where the error occurred.
795 * @param[in] line Line on which the error occurred.
796 * @param[in] tensor_info Tensor info to validate.
797 * @param[in] is_fp16_supported Is fp16 supported by the device.
798 *
799 * @return Status
800 */
801 inline arm_compute::Status error_on_unsupported_fp16(const char *function, const char *file, const int line,
802 const ITensorInfo *tensor_info, bool is_fp16_supported)
803 {
804 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
805 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG((tensor_info->data_type() == DataType::F16 && !is_fp16_supported),
806 function, file, line, "FP16 not supported by the device");
807 return arm_compute::Status{};
808 }
809
810 /** Return an error if the data type of the passed tensor is FP16 and FP16 extension is not supported by the device.
811 *
812 * @param[in] function Function in which the error occurred.
813 * @param[in] file Name of the file where the error occurred.
814 * @param[in] line Line on which the error occurred.
815 * @param[in] tensor Tensor to validate.
816 * @param[in] is_fp16_supported Is fp16 supported by the device.
817 *
818 * @return Status
819 */
820 inline arm_compute::Status error_on_unsupported_fp16(const char *function, const char *file, const int line,
821 const ITensor *tensor, bool is_fp16_supported)
822 {
823 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
824 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unsupported_fp16(function, file, line, tensor->info(), is_fp16_supported));
825 return arm_compute::Status{};
826 }
827
828 /** Return an error if the tensor is not 2D.
829 *
830 * @param[in] function Function in which the error occurred.
831 * @param[in] file Name of the file where the error occurred.
832 * @param[in] line Line on which the error occurred.
833 * @param[in] tensor Tensor to validate.
834 *
835 * @return Status
836 */
837 arm_compute::Status error_on_tensor_not_2d(const char *function, const char *file, const int line,
838 const ITensor *tensor);
839
840 /** Return an error if the tensor info is not 2D.
841 *
842 * @param[in] function Function in which the error occurred.
843 * @param[in] file Name of the file where the error occurred.
844 * @param[in] line Line on which the error occurred.
845 * @param[in] tensor Tensor info to validate.
846 *
847 * @return Status
848 */
849 arm_compute::Status error_on_tensor_not_2d(const char *function, const char *file, const int line,
850 const ITensorInfo *tensor);
851
852 #define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) \
853 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
854 #define ARM_COMPUTE_RETURN_ERROR_ON_TENSOR_NOT_2D(t) \
855 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
856
857 /** Return an error if the channel is not in channels.
858 *
859 * @param[in] function Function in which the error occurred.
860 * @param[in] file Name of the file where the error occurred.
861 * @param[in] line Line on which the error occurred.
862 * @param[in] cn Input channel
863 * @param[in] channel First channel allowed.
864 * @param[in] channels (Optional) Further allowed channels.
865 *
866 * @return Status
867 */
868 template <typename T, typename... Ts>
869 inline arm_compute::Status error_on_channel_not_in(const char *function, const char *file, const int line,
870 T cn, T &&channel, Ts &&... channels)
871 {
872 ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
873
874 const std::array<T, sizeof...(Ts)> channels_array{ { std::forward<Ts>(channels)... } };
875 ARM_COMPUTE_RETURN_ERROR_ON_LOC(channel != cn && std::none_of(channels_array.begin(), channels_array.end(), [&](const T & f)
876 {
877 return f == cn;
878 }),
879 function, file, line);
880 return arm_compute::Status{};
881 }
882 #define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
883 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_channel_not_in(__func__, __FILE__, __LINE__, c, __VA_ARGS__))
884 #define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
885 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_channel_not_in(__func__, __FILE__, __LINE__, c, __VA_ARGS__))
886
887 /** Return an error if the channel is not in format.
888 *
889 * @param[in] function Function in which the error occurred.
890 * @param[in] file Name of the file where the error occurred.
891 * @param[in] line Line on which the error occurred.
892 * @param[in] fmt Input channel
893 * @param[in] cn First channel allowed.
894 *
895 * @return Status
896 */
897 arm_compute::Status error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
898 Format fmt, Channel cn);
899 #define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
900 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_channel_not_in_known_format(__func__, __FILE__, __LINE__, f, c))
901 #define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
902 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_channel_not_in_known_format(__func__, __FILE__, __LINE__, f, c))
903
904 /** Return an error if the kernel is not configured.
905 *
906 * @param[in] function Function in which the error occurred.
907 * @param[in] file Name of the file where the error occurred.
908 * @param[in] line Line on which the error occurred.
909 * @param[in] kernel Kernel to validate.
910 *
911 * @return Status
912 */
913 arm_compute::Status error_on_unconfigured_kernel(const char *function, const char *file, const int line,
914 const IKernel *kernel);
915 #define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) \
916 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
917 #define ARM_COMPUTE_RETURN_ERROR_ON_UNCONFIGURED_KERNEL(k) \
918 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
919
920 /** Return an error if if the coordinates and shape of the subtensor are within the parent tensor.
921 *
922 * @param[in] function Function in which the error occurred.
923 * @param[in] file Name of the file where the error occurred.
924 * @param[in] line Line on which the error occurred.
925 * @param[in] parent_shape Parent tensor shape
926 * @param[in] coords Coordinates inside the parent tensor where the first element of the subtensor is
927 * @param[in] shape Shape of the subtensor
928 *
929 * @return Status
930 */
931 arm_compute::Status error_on_invalid_subtensor(const char *function, const char *file, const int line,
932 const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape);
933 #define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
934 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
935 #define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
936 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
937
938 /** Return an error if the valid region of a subtensor is not inside the valid region of the parent tensor.
939 *
940 * @param[in] function Function in which the error occurred.
941 * @param[in] file Name of the file where the error occurred.
942 * @param[in] line Line on which the error occurred.
943 * @param[in] parent_valid_region Parent valid region.
944 * @param[in] valid_region Valid region of subtensor.
945 *
946 * @return Status
947 */
948 arm_compute::Status error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
949 const ValidRegion &parent_valid_region, const ValidRegion &valid_region);
950 #define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
951 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
952 #define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
953 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
954 }
955 #endif /* ARM_COMPUTE_VALIDATE_H*/
956