blob: 5550560affd059612361a4e96a367060edbe830f [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Matthew Bentham043613f2023-05-30 16:43:14 +00002 * Copyright (c) 2016-2021, 2023 Arm Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
Michalis Spyrouf4643372019-11-29 16:17:13 +000024#ifndef ARM_COMPUTE_VALIDATE_H
25#define ARM_COMPUTE_VALIDATE_H
Anthony Barbier6ff3b192017-09-04 18:44:23 +010026
27#include "arm_compute/core/Error.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010028#include "arm_compute/core/IKernel.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010029#include "arm_compute/core/ITensor.h"
Matthew Bentham7d9a78e2023-05-31 13:18:33 +000030#include "arm_compute/core/QuantizationInfo.h"
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010031#include "arm_compute/core/utils/DataLayoutUtils.h"
32#include "arm_compute/core/utils/DataTypeUtils.h"
33#include "arm_compute/core/utils/FormatUtils.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010034#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{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010053 for (unsigned int i = upper_dim; i < arm_compute::Dimensions<T>::num_max_dimensions; ++i)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010054 {
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010055 if (dim1[i] != dim2[i])
Anthony Barbier6ff3b192017-09-04 18:44:23 +010056 {
57 return true;
58 }
59 }
60
61 return false;
62}
63
Alex Gildayc357c472018-03-21 13:54:09 +000064/** Function to compare two @ref Dimensions objects and throw an error on mismatch.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010065 *
66 * @param[in] dim Object to compare against.
Georgios Pinitas3faea252017-10-30 14:13:50 +000067 * @param[in] function Function in which the error occurred.
68 * @param[in] file File in which the error occurred.
69 * @param[in] line Line in which the error occurred.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010070 */
71template <typename T>
72class compare_dimension
73{
74public:
Alex Gildayc357c472018-03-21 13:54:09 +000075 /** Construct a comparison function.
76 *
77 * @param[in] dim Dimensions to compare.
78 * @param[in] function Source function. Used for error reporting.
79 * @param[in] file Source code file. Used for error reporting.
80 * @param[in] line Source code line. Used for error reporting.
81 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010082 compare_dimension(const Dimensions<T> &dim, const char *function, const char *file, int line)
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010083 : _dim{dim}, _function{function}, _file{file}, _line{line}
Anthony Barbier6ff3b192017-09-04 18:44:23 +010084 {
85 }
86
87 /** Compare the given object against the stored one.
88 *
89 * @param[in] dim To be compared object.
Alex Gildayc357c472018-03-21 13:54:09 +000090 *
91 * @return a status.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010092 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000093 arm_compute::Status operator()(const Dimensions<T> &dim)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010094 {
Georgios Pinitas3faea252017-10-30 14:13:50 +000095 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(have_different_dimensions(_dim, dim, 0), _function, _file, _line,
96 "Objects have different dimensions");
Georgios Pinitas631c41a2017-12-06 11:53:03 +000097 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +010098 }
99
100private:
101 const Dimensions<T> &_dim;
102 const char *const _function;
103 const char *const _file;
104 const int _line;
105};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000106
107template <typename F>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000108inline arm_compute::Status for_each_error(F &&)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000109{
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000110 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000111}
112
113template <typename F, typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100114inline arm_compute::Status for_each_error(F &&func, T &&arg, Ts &&...args)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000115{
116 ARM_COMPUTE_RETURN_ON_ERROR(func(arg));
117 ARM_COMPUTE_RETURN_ON_ERROR(for_each_error(func, args...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000118 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000119}
120
Alex Gildayc357c472018-03-21 13:54:09 +0000121/** Get the info for a tensor, dummy struct */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000122template <typename T>
123struct get_tensor_info_t;
Alex Gildayc357c472018-03-21 13:54:09 +0000124/** Get the info for a tensor */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000125template <>
126struct get_tensor_info_t<ITensorInfo *>
127{
Alex Gildayc357c472018-03-21 13:54:09 +0000128 /** Get the info for a tensor.
129 *
130 * @param[in] tensor Tensor.
131 *
132 * @return tensor info.
133 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000134 ITensorInfo *operator()(const ITensor *tensor)
135 {
136 return tensor->info();
137 }
138};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100139} // namespace detail
Georgios Pinitas3faea252017-10-30 14:13:50 +0000140
141/** Create an error if one of the pointers is a nullptr.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100142 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000143 * @param[in] function Function in which the error occurred.
144 * @param[in] file Name of the file where the error occurred.
145 * @param[in] line Line on which the error occurred.
146 * @param[in] pointers Pointers to check against nullptr.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000147 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000148 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100149 */
150template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100151inline arm_compute::Status error_on_nullptr(const char *function, const char *file, const int line, Ts &&...pointers)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100152{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100153 const std::array<const void *, sizeof...(Ts)> pointers_array{{std::forward<Ts>(pointers)...}};
154 bool has_nullptr =
155 std::any_of(pointers_array.begin(), pointers_array.end(), [&](const void *ptr) { return (ptr == nullptr); });
Georgios Pinitas3faea252017-10-30 14:13:50 +0000156 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(has_nullptr, function, file, line, "Nullptr object!");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000157 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100158}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000159#define ARM_COMPUTE_ERROR_ON_NULLPTR(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000160 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000161#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...) \
162 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100163
Georgios Pinitas3faea252017-10-30 14:13:50 +0000164/** Return an error if the passed window is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100165 *
166 * The subwindow is invalid if:
167 * - It is not a valid window.
168 * - Its dimensions don't match the full window's ones
169 * - The step for each of its dimension is not identical to the corresponding one of the full window.
170 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000171 * @param[in] function Function in which the error occurred.
172 * @param[in] file Name of the file where the error occurred.
173 * @param[in] line Line on which the error occurred.
174 * @param[in] full Full size window
175 * @param[in] win Window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000176 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000177 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100178 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100179arm_compute::Status error_on_mismatching_windows(
180 const char *function, const char *file, const int line, const Window &full, const Window &win);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000181#define ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000182 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000183#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
184 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100185
Georgios Pinitas3faea252017-10-30 14:13:50 +0000186/** Return an error if the passed subwindow is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100187 *
188 * The subwindow is invalid if:
189 * - It is not a valid window.
190 * - It is not fully contained inside the full window
191 * - The step for each of its dimension is not identical to the corresponding one of the full window.
192 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000193 * @param[in] function Function in which the error occurred.
194 * @param[in] file Name of the file where the error occurred.
195 * @param[in] line Line on which the error occurred.
196 * @param[in] full Full size window
197 * @param[in] sub Sub-window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000198 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000199 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100200 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100201arm_compute::Status error_on_invalid_subwindow(
202 const char *function, const char *file, const int line, const Window &full, const Window &sub);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000203#define ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(f, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000204 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000205#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBWINDOW(f, s) \
206 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100207
Georgios Pinitas3faea252017-10-30 14:13:50 +0000208/** Return an error if the window can't be collapsed at the given dimension.
steniu01868e5412017-07-17 23:16:00 +0100209 *
210 * The window cannot be collapsed if the given dimension not equal to the full window's dimension or not start from 0.
211 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000212 * @param[in] function Function in which the error occurred.
213 * @param[in] file Name of the file where the error occurred.
214 * @param[in] line Line on which the error occurred.
215 * @param[in] full Full size window
216 * @param[in] window Window to be collapsed.
217 * @param[in] dim Dimension need to be checked.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000218 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000219 * @return Status
steniu01868e5412017-07-17 23:16:00 +0100220 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100221arm_compute::Status error_on_window_not_collapsable_at_dimension(
222 const char *function, const char *file, const int line, const Window &full, const Window &window, const int dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000223#define ARM_COMPUTE_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100224 ARM_COMPUTE_ERROR_THROW_ON( \
225 ::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000226#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100227 ARM_COMPUTE_RETURN_ON_ERROR( \
228 ::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
steniu01868e5412017-07-17 23:16:00 +0100229
Georgios Pinitas3faea252017-10-30 14:13:50 +0000230/** Return an error if the passed coordinates have too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100231 *
232 * The coordinates have too many dimensions if any of the dimensions greater or equal to max_dim is different from 0.
233 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000234 * @param[in] function Function in which the error occurred.
235 * @param[in] file Name of the file where the error occurred.
236 * @param[in] line Line on which the error occurred.
237 * @param[in] pos Coordinates to validate
238 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000239 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000240 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100241 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100242arm_compute::Status error_on_coordinates_dimensions_gte(
243 const char *function, const char *file, const int line, const Coordinates &pos, unsigned int max_dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000244#define ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000245 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000246#define ARM_COMPUTE_RETURN_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
247 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100248
Georgios Pinitas3faea252017-10-30 14:13:50 +0000249/** Return an error if the passed window has too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100250 *
251 * The window has too many dimensions if any of the dimension greater or equal to max_dim is different from 0.
252 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000253 * @param[in] function Function in which the error occurred.
254 * @param[in] file Name of the file where the error occurred.
255 * @param[in] line Line on which the error occurred.
256 * @param[in] win Window to validate
257 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000258 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000259 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100260 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100261arm_compute::Status error_on_window_dimensions_gte(
262 const char *function, const char *file, const int line, const Window &win, unsigned int max_dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000263#define ARM_COMPUTE_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000264 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000265#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
266 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100267
Georgios Pinitas3faea252017-10-30 14:13:50 +0000268/** Return an error if the passed dimension objects differ.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100269 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000270 * @param[in] function Function in which the error occurred.
271 * @param[in] file Name of the file where the error occurred.
272 * @param[in] line Line on which the error occurred.
273 * @param[in] dim1 The first object to be compared.
274 * @param[in] dim2 The second object to be compared.
275 * @param[in] dims (Optional) Further allowed objects.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000276 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000277 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100278 */
279template <typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100280arm_compute::Status error_on_mismatching_dimensions(const char *function,
281 const char *file,
282 int line,
283 const Dimensions<T> &dim1,
284 const Dimensions<T> &dim2,
285 Ts &&...dims)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100286{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100287 ARM_COMPUTE_RETURN_ON_ERROR(detail::for_each_error(detail::compare_dimension<T>(dim1, function, file, line), dim2,
288 std::forward<Ts>(dims)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000289 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100290}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000291#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100292 ARM_COMPUTE_ERROR_THROW_ON( \
293 ::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000294#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100295 ARM_COMPUTE_RETURN_ON_ERROR( \
296 ::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100297
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000298/** Return true if the given format has horizontal subsampling.
299 *
300 * @param[in] format Format to determine subsampling.
301 *
302 * @return True if the format can be subsampled horizontaly.
303 */
304inline bool has_format_horizontal_subsampling(Format format)
305{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100306 return (format == Format::YUYV422 || format == Format::UYVY422 || format == Format::NV12 ||
307 format == Format::NV21 || format == Format::IYUV || format == Format::UV88)
308 ? true
309 : false;
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000310}
311
312/** Return true if the given format has vertical subsampling.
313 *
314 * @param[in] format Format to determine subsampling.
315 *
316 * @return True if the format can be subsampled verticaly.
317 */
318inline bool has_format_vertical_subsampling(Format format)
319{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100320 return (format == Format::NV12 || format == Format::NV21 || format == Format::IYUV || format == Format::UV88)
321 ? true
322 : false;
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000323}
324
Matthew Bentham043613f2023-05-30 16:43:14 +0000325/** Adjust tensor shape size if width or height are odd for a given multi-planar format. No modification is done for other formats.
326 *
327 * @note Adding here a few links discussing the issue of odd size and sharing the same solution:
328 * <a href="https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/graphics/java/android/graphics/YuvImage.java">Android Source</a>
329 * <a href="https://groups.google.com/a/webmproject.org/forum/#!topic/webm-discuss/LaCKpqiDTXM">WebM</a>
330 * <a href="https://bugs.chromium.org/p/libyuv/issues/detail?id=198&amp;can=1&amp;q=odd%20width">libYUV</a>
331 * <a href="https://sourceforge.net/p/raw-yuvplayer/bugs/1/">YUVPlayer</a> *
332 *
333 * @param[in, out] shape Tensor shape of 2D size
334 * @param[in] format Format of the tensor
335 *
336 * @return The adjusted tensor shape.
337 */
338inline TensorShape adjust_odd_shape(const TensorShape &shape, Format format)
339{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100340 TensorShape output{shape};
Matthew Bentham043613f2023-05-30 16:43:14 +0000341
342 // Force width to be even for formats which require subsampling of the U and V channels
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100343 if (has_format_horizontal_subsampling(format))
Matthew Bentham043613f2023-05-30 16:43:14 +0000344 {
345 output.set(0, (output.x() + 1) & ~1U);
346 }
347
348 // Force height to be even for formats which require subsampling of the U and V channels
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100349 if (has_format_vertical_subsampling(format))
Matthew Bentham043613f2023-05-30 16:43:14 +0000350 {
351 output.set(1, (output.y() + 1) & ~1U);
352 }
353
354 return output;
355}
356
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100357/** Return an error if the passed tensor objects are not even.
358 *
359 * @param[in] function Function in which the error occurred.
360 * @param[in] file Name of the file where the error occurred.
361 * @param[in] line Line on which the error occurred.
362 * @param[in] format Format to check if odd shape is allowed
363 * @param[in] tensor1 The first object to be compared for odd shape.
364 * @param[in] tensors (Optional) Further allowed objects.
365 *
366 * @return Status
367 */
368template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100369arm_compute::Status error_on_tensors_not_even(
370 const char *function, const char *file, int line, const Format &format, const ITensor *tensor1, Ts... tensors)
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100371{
372 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor1 == nullptr, function, file, line);
373 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100374 const std::array<const ITensor *, 1 + sizeof...(Ts)> tensors_info_array{{tensor1, std::forward<Ts>(tensors)...}};
375 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(
376 std::any_of(tensors_info_array.cbegin(), tensors_info_array.cend(),
377 [&](const ITensor *tensor)
378 {
379 const TensorShape correct_shape = adjust_odd_shape(tensor->info()->tensor_shape(), format);
380 return detail::have_different_dimensions(tensor->info()->tensor_shape(), correct_shape, 2);
381 }),
382 function, file, line, "Tensor shape has odd dimensions");
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100383 return arm_compute::Status{};
384}
385
386#define ARM_COMPUTE_ERROR_ON_TENSORS_NOT_EVEN(...) \
387 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
388#define ARM_COMPUTE_RETURN_ERROR_ON_TENSORS_NOT_EVEN(...) \
389 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
390
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000391/** Calculate subsampled shape for a given format and channel
392 *
393 * @param[in] shape Shape of the tensor to calculate the extracted channel.
394 * @param[in] format Format of the tensor.
395 * @param[in] channel Channel to create tensor shape to be extracted.
396 *
397 * @return The subsampled tensor shape.
398 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100399inline TensorShape
400calculate_subsampled_shape(const TensorShape &shape, Format format, Channel channel = Channel::UNKNOWN)
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000401{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100402 TensorShape output{shape};
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000403
404 // Subsample shape only for U or V channel
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100405 if (Channel::U == channel || Channel::V == channel || Channel::UNKNOWN == channel)
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000406 {
407 // Subsample width for the tensor shape when channel is U or V
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100408 if (has_format_horizontal_subsampling(format))
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000409 {
410 output.set(0, output.x() / 2U);
411 }
412
413 // Subsample height for the tensor shape when channel is U or V
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100414 if (has_format_vertical_subsampling(format))
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000415 {
416 output.set(1, output.y() / 2U);
417 }
418 }
419
420 return output;
421}
422
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000423/** Return an error if the passed tensor objects are not sub-sampled.
424 *
425 * @param[in] function Function in which the error occurred.
426 * @param[in] file Name of the file where the error occurred.
427 * @param[in] line Line on which the error occurred.
428 * @param[in] format Format to check if sub-sampling allowed.
429 * @param[in] shape The tensor shape to calculate sub-sampling from.
430 * @param[in] tensor1 The first object to be compared.
431 * @param[in] tensors (Optional) Further allowed objects.
432 *
433 * @return Status
434 */
435template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100436arm_compute::Status error_on_tensors_not_subsampled(const char *function,
437 const char *file,
438 int line,
439 const Format &format,
440 const TensorShape &shape,
441 const ITensor *tensor1,
442 Ts... tensors)
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000443{
444 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor1 == nullptr, function, file, line);
445 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100446 const TensorShape sub2_shape = calculate_subsampled_shape(shape, format);
447 const std::array<const ITensor *, 1 + sizeof...(Ts)> tensors_info_array{{tensor1, std::forward<Ts>(tensors)...}};
448 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(
449 std::any_of(tensors_info_array.cbegin(), tensors_info_array.cend(),
450 [&](const ITensor *tensor)
451 { return detail::have_different_dimensions(tensor->info()->tensor_shape(), sub2_shape, 2); }),
452 function, file, line, "Tensor shape has mismatch dimensions for sub-sampling");
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000453 return arm_compute::Status{};
454}
455
456#define ARM_COMPUTE_ERROR_ON_TENSORS_NOT_SUBSAMPLED(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100457 ARM_COMPUTE_ERROR_THROW_ON( \
458 ::arm_compute::error_on_tensors_not_subsampled(__func__, __FILE__, __LINE__, __VA_ARGS__))
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000459#define ARM_COMPUTE_RETURN_ERROR_ON_TENSORS_NOT_SUBSAMPLED(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100460 ARM_COMPUTE_RETURN_ON_ERROR( \
461 ::arm_compute::error_on_tensors_not_subsampled(__func__, __FILE__, __LINE__, __VA_ARGS__))
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000462
Georgios Pinitas3faea252017-10-30 14:13:50 +0000463/** Return an error if the passed two tensor infos have different shapes from the given dimension
464 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000465 * @param[in] function Function in which the error occurred.
466 * @param[in] file Name of the file where the error occurred.
467 * @param[in] line Line on which the error occurred.
468 * @param[in] tensor_info_1 The first tensor info to be compared.
469 * @param[in] tensor_info_2 The second tensor info to be compared.
470 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000471 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000472 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000473 */
474template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100475inline arm_compute::Status error_on_mismatching_shapes(const char *function,
476 const char *file,
477 const int line,
478 const ITensorInfo *tensor_info_1,
479 const ITensorInfo *tensor_info_2,
480 Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000481{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100482 return error_on_mismatching_shapes(function, file, line, 0U, tensor_info_1, tensor_info_2,
483 std::forward<Ts>(tensor_infos)...);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000484}
485/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100486 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000487 * @param[in] function Function in which the error occurred.
488 * @param[in] file Name of the file where the error occurred.
489 * @param[in] line Line on which the error occurred.
490 * @param[in] tensor_1 The first tensor to be compared.
491 * @param[in] tensor_2 The second tensor to be compared.
492 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000493 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000494 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100495 */
496template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100497inline arm_compute::Status error_on_mismatching_shapes(const char *function,
498 const char *file,
499 const int line,
500 const ITensor *tensor_1,
501 const ITensor *tensor_2,
502 Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100503{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000504 return error_on_mismatching_shapes(function, file, line, 0U, tensor_1, tensor_2, std::forward<Ts>(tensors)...);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100505}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000506/** Return an error if the passed two tensors have different shapes from the given dimension
507 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000508 * @param[in] function Function in which the error occurred.
509 * @param[in] file Name of the file where the error occurred.
510 * @param[in] line Line on which the error occurred.
511 * @param[in] upper_dim The dimension from which to check.
512 * @param[in] tensor_info_1 The first tensor info to be compared.
513 * @param[in] tensor_info_2 The second tensor info to be compared.
514 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000515 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000516 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000517 */
518template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100519inline arm_compute::Status error_on_mismatching_shapes(const char *function,
520 const char *file,
521 const int line,
522 unsigned int upper_dim,
523 const ITensorInfo *tensor_info_1,
524 const ITensorInfo *tensor_info_2,
525 Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000526{
527 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_1 == nullptr, function, file, line);
528 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_2 == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100529 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensor_infos...));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100530
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100531 const std::array<const ITensorInfo *, 2 + sizeof...(Ts)> tensors_info_array{
532 {tensor_info_1, tensor_info_2, tensor_infos...}};
533 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(std::next(tensors_info_array.cbegin()), tensors_info_array.cend(),
534 [&](const ITensorInfo *tensor_info)
535 {
536 return detail::have_different_dimensions(
537 (*tensors_info_array.cbegin())->tensor_shape(),
538 tensor_info->tensor_shape(), upper_dim);
539 }),
540 function, file, line, "Tensors have different shapes");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000541 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000542}
543/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100544 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000545 * @param[in] function Function in which the error occurred.
546 * @param[in] file Name of the file where the error occurred.
547 * @param[in] line Line on which the error occurred.
548 * @param[in] upper_dim The dimension from which to check.
549 * @param[in] tensor_1 The first tensor to be compared.
550 * @param[in] tensor_2 The second tensor to be compared.
551 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000552 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000553 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100554 */
555template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100556inline arm_compute::Status error_on_mismatching_shapes(const char *function,
557 const char *file,
558 const int line,
559 unsigned int upper_dim,
560 const ITensor *tensor_1,
561 const ITensor *tensor_2,
562 Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100563{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000564 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_1 == nullptr, function, file, line);
565 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_2 == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100566 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensors...));
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100567 ARM_COMPUTE_RETURN_ON_ERROR(
568 ::arm_compute::error_on_mismatching_shapes(function, file, line, upper_dim, tensor_1->info(), tensor_2->info(),
569 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000570 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100571}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000572#define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000573 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000574#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(...) \
575 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100576
Michalis Spyrou7a569252018-03-01 12:03:14 +0000577/** Return an error if the passed tensor infos have different data layouts
578 *
579 * @param[in] function Function in which the error occurred.
580 * @param[in] file Name of the file where the error occurred.
581 * @param[in] line Line on which the error occurred.
582 * @param[in] tensor_info The first tensor info to be compared.
583 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
584 *
585 * @return Status
586 */
587template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100588inline arm_compute::Status error_on_mismatching_data_layouts(
589 const char *function, const char *file, const int line, const ITensorInfo *tensor_info, Ts... tensor_infos)
Michalis Spyrou7a569252018-03-01 12:03:14 +0000590{
591 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100592 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensor_infos...));
Michalis Spyrou7a569252018-03-01 12:03:14 +0000593
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100594 DataLayout &&tensor_data_layout = tensor_info->data_layout();
595 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{{tensor_infos...}};
596 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(),
597 [&](const ITensorInfo *tensor_info_obj)
598 { return tensor_info_obj->data_layout() != tensor_data_layout; }),
599 function, file, line, "Tensors have different data layouts");
Michalis Spyrou7a569252018-03-01 12:03:14 +0000600 return arm_compute::Status{};
601}
602/** Return an error if the passed tensors have different data layouts
603 *
604 * @param[in] function Function in which the error occurred.
605 * @param[in] file Name of the file where the error occurred.
606 * @param[in] line Line on which the error occurred.
607 * @param[in] tensor The first tensor to be compared.
608 * @param[in] tensors (Optional) Further allowed tensors.
609 *
610 * @return Status
611 */
612template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100613inline arm_compute::Status error_on_mismatching_data_layouts(
614 const char *function, const char *file, const int line, const ITensor *tensor, Ts... tensors)
Michalis Spyrou7a569252018-03-01 12:03:14 +0000615{
616 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
617 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100618 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_layouts(
619 function, file, line, tensor->info(), detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Michalis Spyrou7a569252018-03-01 12:03:14 +0000620 return arm_compute::Status{};
621}
622#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100623 ARM_COMPUTE_ERROR_THROW_ON( \
624 ::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
Michalis Spyrou7a569252018-03-01 12:03:14 +0000625#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100626 ARM_COMPUTE_RETURN_ON_ERROR( \
627 ::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
Michalis Spyrou7a569252018-03-01 12:03:14 +0000628
Georgios Pinitas3faea252017-10-30 14:13:50 +0000629/** Return an error if the passed two tensor infos have different data types
630 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000631 * @param[in] function Function in which the error occurred.
632 * @param[in] file Name of the file where the error occurred.
633 * @param[in] line Line on which the error occurred.
634 * @param[in] tensor_info The first tensor info to be compared.
635 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000636 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000637 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000638 */
639template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100640inline arm_compute::Status error_on_mismatching_data_types(
641 const char *function, const char *file, const int line, const ITensorInfo *tensor_info, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000642{
643 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100644 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensor_infos...));
Georgios Pinitas3faea252017-10-30 14:13:50 +0000645
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100646 DataType &&tensor_data_type = tensor_info->data_type();
647 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{{tensor_infos...}};
648 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(),
649 [&](const ITensorInfo *tensor_info_obj)
650 { return tensor_info_obj->data_type() != tensor_data_type; }),
651 function, file, line, "Tensors have different data types");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000652 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000653}
654/** Return an error if the passed two tensors have different data types
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100655 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000656 * @param[in] function Function in which the error occurred.
657 * @param[in] file Name of the file where the error occurred.
658 * @param[in] line Line on which the error occurred.
659 * @param[in] tensor The first tensor to be compared.
660 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000661 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000662 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100663 */
664template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100665inline arm_compute::Status error_on_mismatching_data_types(
666 const char *function, const char *file, const int line, const ITensor *tensor, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100667{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000668 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100669 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensors...));
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100670 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(
671 function, file, line, tensor->info(), detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000672 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100673}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000674#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100675 ARM_COMPUTE_ERROR_THROW_ON( \
676 ::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000677#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100678 ARM_COMPUTE_RETURN_ON_ERROR( \
679 ::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100680
Daniil Efremoveed841c2017-11-09 19:05:25 +0700681/** Return an error if the passed tensor infos have different asymmetric quantized data types or different quantization info
682 *
683 * @note: If the first tensor info doesn't have asymmetric quantized data type, the function returns without throwing an error
684 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000685 * @param[in] function Function in which the error occurred.
686 * @param[in] file Name of the file where the error occurred.
687 * @param[in] line Line on which the error occurred.
688 * @param[in] tensor_info_1 The first tensor info to be compared.
689 * @param[in] tensor_info_2 The second tensor info to be compared.
690 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700691 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000692 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700693 */
694template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100695inline arm_compute::Status error_on_mismatching_quantization_info(const char *function,
696 const char *file,
697 const int line,
698 const ITensorInfo *tensor_info_1,
699 const ITensorInfo *tensor_info_2,
700 Ts... tensor_infos)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700701{
702 DataType &&first_data_type = tensor_info_1->data_type();
703 const QuantizationInfo first_quantization_info = tensor_info_1->quantization_info();
704
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100705 if (!is_data_type_quantized(first_data_type))
Daniil Efremoveed841c2017-11-09 19:05:25 +0700706 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000707 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700708 }
709
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100710 const std::array<const ITensorInfo *, 1 + sizeof...(Ts)> tensor_infos_array{
711 {tensor_info_2, std::forward<Ts>(tensor_infos)...}};
712 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(),
713 [&](const ITensorInfo *tensor_info)
714 { return tensor_info->data_type() != first_data_type; }),
715 function, file, line, "Tensors have different asymmetric quantized data types");
716 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(
717 std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(),
718 [&](const ITensorInfo *tensor_info)
719 { return tensor_info->quantization_info() != first_quantization_info; }),
720 function, file, line, "Tensors have different quantization information");
Daniil Efremoveed841c2017-11-09 19:05:25 +0700721
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000722 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700723}
724/** Return an error if the passed tensor have different asymmetric quantized data types or different quantization info
725 *
726 * @note: If the first tensor doesn't have asymmetric quantized data type, the function returns without throwing an error
727 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000728 * @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] tensor_1 The first tensor to be compared.
732 * @param[in] tensor_2 The second tensor to be compared.
733 * @param[in] tensors (Optional) Further allowed tensors.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700734 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000735 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700736 */
737template <typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100738inline arm_compute::Status error_on_mismatching_quantization_info(const char *function,
739 const char *file,
740 const int line,
741 const ITensor *tensor_1,
742 const ITensor *tensor_2,
743 Ts... tensors)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700744{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100745 ARM_COMPUTE_RETURN_ON_ERROR(
746 ::arm_compute::error_on_mismatching_quantization_info(function, file, line, tensor_1->info(), tensor_2->info(),
747 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000748 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700749}
750#define ARM_COMPUTE_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100751 ARM_COMPUTE_ERROR_THROW_ON( \
752 ::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
Daniil Efremoveed841c2017-11-09 19:05:25 +0700753#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100754 ARM_COMPUTE_RETURN_ON_ERROR( \
755 ::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
Daniil Efremoveed841c2017-11-09 19:05:25 +0700756
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100757/** Throw an error if the format of the passed tensor/multi-image does not match any of the formats provided.
758 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000759 * @param[in] function Function in which the error occurred.
760 * @param[in] file Name of the file where the error occurred.
761 * @param[in] line Line on which the error occurred.
762 * @param[in] object Tensor/multi-image to validate.
763 * @param[in] format First format allowed.
764 * @param[in] formats (Optional) Further allowed formats.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100765 */
766template <typename T, typename F, typename... Fs>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100767void error_on_format_not_in(
768 const char *function, const char *file, const int line, const T *object, F &&format, Fs &&...formats)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100769{
770 ARM_COMPUTE_ERROR_ON_LOC(object == nullptr, function, file, line);
771
772 Format &&object_format = object->info()->format();
773 ARM_COMPUTE_UNUSED(object_format);
774
775 ARM_COMPUTE_ERROR_ON_LOC(object_format == Format::UNKNOWN, function, file, line);
776
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100777 const std::array<F, sizeof...(Fs)> formats_array{{std::forward<Fs>(formats)...}};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100778 ARM_COMPUTE_UNUSED(formats_array);
779
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100780 ARM_COMPUTE_ERROR_ON_LOC_MSG(
781 object_format != format &&
782 std::none_of(formats_array.begin(), formats_array.end(), [&](const F &f) { return f == object_format; }),
783 function, file, line, "Format %s not supported by this kernel", string_from_format(object_format).c_str());
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100784 ARM_COMPUTE_UNUSED(function, format, file, line);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100785}
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100786#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t, ...) \
787 ::arm_compute::error_on_format_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100788
Georgios Pinitas3faea252017-10-30 14:13:50 +0000789/** Return an error if the data type of the passed tensor info does not match any of the data types provided.
790 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000791 * @param[in] function Function in which the error occurred.
792 * @param[in] file Name of the file where the error occurred.
793 * @param[in] line Line on which the error occurred.
794 * @param[in] tensor_info Tensor info to validate.
795 * @param[in] dt First data type allowed.
796 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000797 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000798 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000799 */
800template <typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100801inline arm_compute::Status error_on_data_type_not_in(
802 const char *function, const char *file, const int line, const ITensorInfo *tensor_info, T &&dt, Ts &&...dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000803{
804 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
805
806 const DataType &tensor_dt = tensor_info->data_type(); //NOLINT
807 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
808
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100809 const std::array<T, sizeof...(Ts)> dts_array{{std::forward<Ts>(dts)...}};
810 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG_VAR(
811 tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T &d) { return d == tensor_dt; }),
812 function, file, line, "ITensor data type %s not supported by this kernel",
813 string_from_data_type(tensor_dt).c_str());
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000814 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000815}
816/** 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 +0100817 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000818 * @param[in] function Function in which the error occurred.
819 * @param[in] file Name of the file where the error occurred.
820 * @param[in] line Line on which the error occurred.
821 * @param[in] tensor Tensor to validate.
822 * @param[in] dt First data type allowed.
823 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000824 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000825 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100826 */
827template <typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100828inline arm_compute::Status error_on_data_type_not_in(
829 const char *function, const char *file, const int line, const ITensor *tensor, T &&dt, Ts &&...dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100830{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000831 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100832 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_not_in(
833 function, file, line, tensor->info(), std::forward<T>(dt), std::forward<Ts>(dts)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000834 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100835}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000836#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000837 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 +0000838#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
839 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 +0100840
Georgios Pinitasf1adf112018-11-02 12:54:18 +0000841/** Return an error if the data layout of the passed tensor info does not match any of the data layouts provided.
842 *
843 * @param[in] function Function in which the error occurred.
844 * @param[in] file Name of the file where the error occurred.
845 * @param[in] line Line on which the error occurred.
846 * @param[in] tensor_info Tensor info to validate.
847 * @param[in] dl First data layout allowed.
848 * @param[in] dls (Optional) Further allowed data layouts.
849 *
850 * @return Status
851 */
852template <typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100853inline arm_compute::Status error_on_data_layout_not_in(
854 const char *function, const char *file, const int line, const ITensorInfo *tensor_info, T &&dl, Ts &&...dls)
Georgios Pinitasf1adf112018-11-02 12:54:18 +0000855{
856 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
857
858 const DataLayout &tensor_dl = tensor_info->data_layout(); //NOLINT
859 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dl == DataLayout::UNKNOWN, function, file, line);
860
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100861 const std::array<T, sizeof...(Ts)> dls_array{{std::forward<Ts>(dls)...}};
862 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG_VAR(
863 tensor_dl != dl && std::none_of(dls_array.begin(), dls_array.end(), [&](const T &l) { return l == tensor_dl; }),
864 function, file, line, "ITensor data layout %s not supported by this kernel",
865 string_from_data_layout(tensor_dl).c_str());
Georgios Pinitasf1adf112018-11-02 12:54:18 +0000866 return arm_compute::Status{};
867}
868/** Return an error if the data layout of the passed tensor does not match any of the data layout provided.
869 *
870 * @param[in] function Function in which the error occurred.
871 * @param[in] file Name of the file where the error occurred.
872 * @param[in] line Line on which the error occurred.
873 * @param[in] tensor Tensor to validate.
874 * @param[in] dl First data layout allowed.
875 * @param[in] dls (Optional) Further allowed data layouts.
876 *
877 * @return Status
878 */
879template <typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100880inline arm_compute::Status error_on_data_layout_not_in(
881 const char *function, const char *file, const int line, const ITensor *tensor, T &&dl, Ts &&...dls)
Georgios Pinitasf1adf112018-11-02 12:54:18 +0000882{
883 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100884 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_layout_not_in(
885 function, file, line, tensor->info(), std::forward<T>(dl), std::forward<Ts>(dls)...));
Georgios Pinitasf1adf112018-11-02 12:54:18 +0000886 return arm_compute::Status{};
887}
888#define ARM_COMPUTE_ERROR_ON_DATA_LAYOUT_NOT_IN(t, ...) \
889 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_data_layout_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
890#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_LAYOUT_NOT_IN(t, ...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100891 ARM_COMPUTE_RETURN_ON_ERROR( \
892 ::arm_compute::error_on_data_layout_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
Georgios Pinitasf1adf112018-11-02 12:54:18 +0000893
Georgios Pinitas3faea252017-10-30 14:13:50 +0000894/** 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.
895 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000896 * @param[in] function Function in which the error occurred.
897 * @param[in] file Name of the file where the error occurred.
898 * @param[in] line Line on which the error occurred.
899 * @param[in] tensor_info Tensor info to validate.
900 * @param[in] num_channels Number of channels to check
901 * @param[in] dt First data type allowed.
902 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000903 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000904 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000905 */
906template <typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100907inline arm_compute::Status error_on_data_type_channel_not_in(const char *function,
908 const char *file,
909 const int line,
910 const ITensorInfo *tensor_info,
911 size_t num_channels,
912 T &&dt,
913 Ts &&...dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000914{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100915 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_not_in(
916 function, file, line, tensor_info, std::forward<T>(dt), std::forward<Ts>(dts)...));
Georgios Pinitas3faea252017-10-30 14:13:50 +0000917 const size_t tensor_nc = tensor_info->num_channels();
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100918 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG_VAR(tensor_nc != num_channels, function, file, line,
919 "Number of channels %zu. Required number of channels %zu", tensor_nc,
920 num_channels);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000921 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000922}
923/** 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 +0100924 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000925 * @param[in] function Function in which the error occurred.
926 * @param[in] file Name of the file where the error occurred.
927 * @param[in] line Line on which the error occurred.
928 * @param[in] tensor Tensor to validate.
929 * @param[in] num_channels Number of channels to check
930 * @param[in] dt First data type allowed.
931 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000932 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000933 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100934 */
935template <typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100936inline arm_compute::Status error_on_data_type_channel_not_in(const char *function,
937 const char *file,
938 const int line,
939 const ITensor *tensor,
940 size_t num_channels,
941 T &&dt,
942 Ts &&...dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100943{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000944 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100945 ARM_COMPUTE_RETURN_ON_ERROR(error_on_data_type_channel_not_in(function, file, line, tensor->info(), num_channels,
946 std::forward<T>(dt), std::forward<Ts>(dts)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000947 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100948}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000949#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100950 ARM_COMPUTE_ERROR_THROW_ON( \
951 ::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000952#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100953 ARM_COMPUTE_RETURN_ON_ERROR( \
954 ::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100955
Vidhya Sudhan Loganathanf1f49062018-05-25 13:21:26 +0100956/** Return an error if the data type of the passed tensor info is FP16 and FP16 extension is not supported by the device.
957 *
958 * @param[in] function Function in which the error occurred.
959 * @param[in] file Name of the file where the error occurred.
960 * @param[in] line Line on which the error occurred.
961 * @param[in] tensor_info Tensor info to validate.
962 * @param[in] is_fp16_supported Is fp16 supported by the device.
963 *
964 * @return Status
965 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100966inline arm_compute::Status error_on_unsupported_fp16(
967 const char *function, const char *file, const int line, const ITensorInfo *tensor_info, bool is_fp16_supported)
Vidhya Sudhan Loganathanf1f49062018-05-25 13:21:26 +0100968{
969 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100970 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG((tensor_info->data_type() == DataType::F16 && !is_fp16_supported), function,
971 file, line, "FP16 not supported by the device");
Vidhya Sudhan Loganathanf1f49062018-05-25 13:21:26 +0100972 return arm_compute::Status{};
973}
974
975/** Return an error if the data type of the passed tensor is FP16 and FP16 extension is not supported by the device.
976 *
977 * @param[in] function Function in which the error occurred.
978 * @param[in] file Name of the file where the error occurred.
979 * @param[in] line Line on which the error occurred.
980 * @param[in] tensor Tensor to validate.
981 * @param[in] is_fp16_supported Is fp16 supported by the device.
982 *
983 * @return Status
984 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100985inline arm_compute::Status error_on_unsupported_fp16(
986 const char *function, const char *file, const int line, const ITensor *tensor, bool is_fp16_supported)
Vidhya Sudhan Loganathanf1f49062018-05-25 13:21:26 +0100987{
988 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100989 ARM_COMPUTE_RETURN_ON_ERROR(
990 ::arm_compute::error_on_unsupported_fp16(function, file, line, tensor->info(), is_fp16_supported));
Vidhya Sudhan Loganathanf1f49062018-05-25 13:21:26 +0100991 return arm_compute::Status{};
992}
993
Georgios Pinitas3faea252017-10-30 14:13:50 +0000994/** Return an error if the tensor is not 2D.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100995 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000996 * @param[in] function Function in which the error occurred.
997 * @param[in] file Name of the file where the error occurred.
998 * @param[in] line Line on which the error occurred.
999 * @param[in] tensor Tensor to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +00001000 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001001 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001002 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001003arm_compute::Status
1004error_on_tensor_not_2d(const char *function, const char *file, const int line, const ITensor *tensor);
Michalis Spyroud1794eb2018-06-15 16:15:26 +01001005
1006/** Return an error if the tensor info is not 2D.
1007 *
1008 * @param[in] function Function in which the error occurred.
1009 * @param[in] file Name of the file where the error occurred.
1010 * @param[in] line Line on which the error occurred.
1011 * @param[in] tensor Tensor info to validate.
1012 *
1013 * @return Status
1014 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001015arm_compute::Status
1016error_on_tensor_not_2d(const char *function, const char *file, const int line, const ITensorInfo *tensor);
Michalis Spyroud1794eb2018-06-15 16:15:26 +01001017
Georgios Pinitas3faea252017-10-30 14:13:50 +00001018#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001019 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Georgios Pinitas3faea252017-10-30 14:13:50 +00001020#define ARM_COMPUTE_RETURN_ERROR_ON_TENSOR_NOT_2D(t) \
1021 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001022
Georgios Pinitas3faea252017-10-30 14:13:50 +00001023/** Return an error if the channel is not in channels.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001024 *
Anthony Barbierf202e502017-11-23 18:02:04 +00001025 * @param[in] function Function in which the error occurred.
1026 * @param[in] file Name of the file where the error occurred.
1027 * @param[in] line Line on which the error occurred.
1028 * @param[in] cn Input channel
1029 * @param[in] channel First channel allowed.
1030 * @param[in] channels (Optional) Further allowed channels.
Georgios Pinitas3faea252017-10-30 14:13:50 +00001031 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001032 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001033 */
1034template <typename T, typename... Ts>
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001035inline arm_compute::Status
1036error_on_channel_not_in(const char *function, const char *file, const int line, T cn, T &&channel, Ts &&...channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001037{
Georgios Pinitas3faea252017-10-30 14:13:50 +00001038 ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001039
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001040 const std::array<T, sizeof...(Ts)> channels_array{{std::forward<Ts>(channels)...}};
1041 ARM_COMPUTE_RETURN_ERROR_ON_LOC(channel != cn && std::none_of(channels_array.begin(), channels_array.end(),
1042 [&](const T &f) { return f == cn; }),
1043 function, file, line);
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001044 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001045}
Georgios Pinitas3faea252017-10-30 14:13:50 +00001046#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001047 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 +00001048#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
1049 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 +01001050
Georgios Pinitas3faea252017-10-30 14:13:50 +00001051/** Return an error if the channel is not in format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001052 *
Anthony Barbierf202e502017-11-23 18:02:04 +00001053 * @param[in] function Function in which the error occurred.
1054 * @param[in] file Name of the file where the error occurred.
1055 * @param[in] line Line on which the error occurred.
1056 * @param[in] fmt Input channel
1057 * @param[in] cn First channel allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +00001058 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001059 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001060 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001061arm_compute::Status
1062error_on_channel_not_in_known_format(const char *function, const char *file, const int line, Format fmt, Channel cn);
Georgios Pinitas3faea252017-10-30 14:13:50 +00001063#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001064 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 +00001065#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
1066 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 +01001067
Georgios Pinitas3faea252017-10-30 14:13:50 +00001068/** Return an error if the kernel is not configured.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001069 *
Anthony Barbierf202e502017-11-23 18:02:04 +00001070 * @param[in] function Function in which the error occurred.
1071 * @param[in] file Name of the file where the error occurred.
1072 * @param[in] line Line on which the error occurred.
1073 * @param[in] kernel Kernel to validate.
Alex Gildayc357c472018-03-21 13:54:09 +00001074 *
1075 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001076 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001077arm_compute::Status
1078error_on_unconfigured_kernel(const char *function, const char *file, const int line, const IKernel *kernel);
Georgios Pinitas3faea252017-10-30 14:13:50 +00001079#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001080 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Georgios Pinitas3faea252017-10-30 14:13:50 +00001081#define ARM_COMPUTE_RETURN_ERROR_ON_UNCONFIGURED_KERNEL(k) \
1082 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001083
Georgios Pinitas3faea252017-10-30 14:13:50 +00001084/** Return an error if if the coordinates and shape of the subtensor are within the parent tensor.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001085 *
1086 * @param[in] function Function in which the error occurred.
1087 * @param[in] file Name of the file where the error occurred.
1088 * @param[in] line Line on which the error occurred.
1089 * @param[in] parent_shape Parent tensor shape
1090 * @param[in] coords Coordinates inside the parent tensor where the first element of the subtensor is
1091 * @param[in] shape Shape of the subtensor
Georgios Pinitas3faea252017-10-30 14:13:50 +00001092 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001093 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001094 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001095arm_compute::Status error_on_invalid_subtensor(const char *function,
1096 const char *file,
1097 const int line,
1098 const TensorShape &parent_shape,
1099 const Coordinates &coords,
1100 const TensorShape &shape);
Georgios Pinitas3faea252017-10-30 14:13:50 +00001101#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001102 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +00001103#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
1104 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001105
Georgios Pinitas3faea252017-10-30 14:13:50 +00001106/** 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 +01001107 *
1108 * @param[in] function Function in which the error occurred.
1109 * @param[in] file Name of the file where the error occurred.
1110 * @param[in] line Line on which the error occurred.
1111 * @param[in] parent_valid_region Parent valid region.
1112 * @param[in] valid_region Valid region of subtensor.
Georgios Pinitas3faea252017-10-30 14:13:50 +00001113 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001114 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001115 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001116arm_compute::Status error_on_invalid_subtensor_valid_region(const char *function,
1117 const char *file,
1118 const int line,
1119 const ValidRegion &parent_valid_region,
1120 const ValidRegion &valid_region);
Georgios Pinitas3faea252017-10-30 14:13:50 +00001121#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001122 ARM_COMPUTE_ERROR_THROW_ON( \
1123 ::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
Georgios Pinitas3faea252017-10-30 14:13:50 +00001124#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +01001125 ARM_COMPUTE_RETURN_ON_ERROR( \
1126 ::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
1127} // namespace arm_compute
Michalis Spyrouf4643372019-11-29 16:17:13 +00001128#endif /* ARM_COMPUTE_VALIDATE_H*/