blob: 5bffc16f3b56831fed298cc8ac39c582df4e2b5a [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
Matthew Bentham314d3e22023-06-23 10:53:52 +000027#include "arm_compute/core/utils/DataLayoutUtils.h"
28#include "arm_compute/core/utils/DataTypeUtils.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010029#include "arm_compute/core/Error.h"
Matthew Bentham314d3e22023-06-23 10:53:52 +000030#include "arm_compute/core/utils/FormatUtils.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010031#include "arm_compute/core/IKernel.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010032#include "arm_compute/core/ITensor.h"
Matthew Bentham7d9a78e2023-05-31 13:18:33 +000033#include "arm_compute/core/QuantizationInfo.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{
53 for(unsigned int i = upper_dim; i < arm_compute::Dimensions<T>::num_max_dimensions; ++i)
54 {
55 if(dim1[i] != dim2[i])
56 {
57 return true;
58 }
59 }
60
61 return false;
62}
63
Alex Gildayc357c472018-03-21 13:54:09 +000064/** Function to compare two @ref Dimensions objects and throw an error on mismatch.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010065 *
66 * @param[in] dim Object to compare against.
Georgios Pinitas3faea252017-10-30 14:13:50 +000067 * @param[in] function Function in which the error occurred.
68 * @param[in] file File in which the error occurred.
69 * @param[in] line Line in which the error occurred.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010070 */
71template <typename T>
72class compare_dimension
73{
74public:
Alex Gildayc357c472018-03-21 13:54:09 +000075 /** Construct a comparison function.
76 *
77 * @param[in] dim Dimensions to compare.
78 * @param[in] function Source function. Used for error reporting.
79 * @param[in] file Source code file. Used for error reporting.
80 * @param[in] line Source code line. Used for error reporting.
81 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010082 compare_dimension(const Dimensions<T> &dim, const char *function, const char *file, int line)
83 : _dim{ dim }, _function{ function }, _file{ file }, _line{ line }
84 {
85 }
86
87 /** Compare the given object against the stored one.
88 *
89 * @param[in] dim To be compared object.
Alex Gildayc357c472018-03-21 13:54:09 +000090 *
91 * @return a status.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010092 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000093 arm_compute::Status operator()(const Dimensions<T> &dim)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010094 {
Georgios Pinitas3faea252017-10-30 14:13:50 +000095 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(have_different_dimensions(_dim, dim, 0), _function, _file, _line,
96 "Objects have different dimensions");
Georgios Pinitas631c41a2017-12-06 11:53:03 +000097 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +010098 }
99
100private:
101 const Dimensions<T> &_dim;
102 const char *const _function;
103 const char *const _file;
104 const int _line;
105};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000106
107template <typename F>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000108inline arm_compute::Status for_each_error(F &&)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000109{
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000110 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000111}
112
113template <typename F, typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000114inline arm_compute::Status for_each_error(F &&func, T &&arg, Ts &&... args)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000115{
116 ARM_COMPUTE_RETURN_ON_ERROR(func(arg));
117 ARM_COMPUTE_RETURN_ON_ERROR(for_each_error(func, args...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000118 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000119}
120
Alex Gildayc357c472018-03-21 13:54:09 +0000121/** Get the info for a tensor, dummy struct */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000122template <typename T>
123struct get_tensor_info_t;
Alex Gildayc357c472018-03-21 13:54:09 +0000124/** Get the info for a tensor */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000125template <>
126struct get_tensor_info_t<ITensorInfo *>
127{
Alex Gildayc357c472018-03-21 13:54:09 +0000128 /** Get the info for a tensor.
129 *
130 * @param[in] tensor Tensor.
131 *
132 * @return tensor info.
133 */
Georgios Pinitas3faea252017-10-30 14:13:50 +0000134 ITensorInfo *operator()(const ITensor *tensor)
135 {
136 return tensor->info();
137 }
138};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100139} // namespace detail
Georgios Pinitas3faea252017-10-30 14:13:50 +0000140
141/** Create an error if one of the pointers is a nullptr.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100142 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000143 * @param[in] function Function in which the error occurred.
144 * @param[in] file Name of the file where the error occurred.
145 * @param[in] line Line on which the error occurred.
146 * @param[in] pointers Pointers to check against nullptr.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000147 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000148 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100149 */
150template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000151inline arm_compute::Status error_on_nullptr(const char *function, const char *file, const int line, Ts &&... pointers)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100152{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000153 const std::array<const void *, sizeof...(Ts)> pointers_array{ { std::forward<Ts>(pointers)... } };
154 bool has_nullptr = std::any_of(pointers_array.begin(), pointers_array.end(), [&](const void *ptr)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100155 {
Georgios Pinitas3faea252017-10-30 14:13:50 +0000156 return (ptr == nullptr);
157 });
158 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(has_nullptr, function, file, line, "Nullptr object!");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000159 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100160}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000161#define ARM_COMPUTE_ERROR_ON_NULLPTR(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000162 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000163#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...) \
164 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100165
Georgios Pinitas3faea252017-10-30 14:13:50 +0000166/** Return an error if the passed window is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100167 *
168 * The subwindow is invalid if:
169 * - It is not a valid window.
170 * - Its dimensions don't match the full window's ones
171 * - The step for each of its dimension is not identical to the corresponding one of the full window.
172 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000173 * @param[in] function Function in which the error occurred.
174 * @param[in] file Name of the file where the error occurred.
175 * @param[in] line Line on which the error occurred.
176 * @param[in] full Full size window
177 * @param[in] win Window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000178 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000179 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100180 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000181arm_compute::Status error_on_mismatching_windows(const char *function, const char *file, const int line,
182 const Window &full, const Window &win);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000183#define ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000184 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000185#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
186 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100187
Georgios Pinitas3faea252017-10-30 14:13:50 +0000188/** Return an error if the passed subwindow is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100189 *
190 * The subwindow is invalid if:
191 * - It is not a valid window.
192 * - It is not fully contained inside the full window
193 * - The step for each of its dimension is not identical to the corresponding one of the full window.
194 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000195 * @param[in] function Function in which the error occurred.
196 * @param[in] file Name of the file where the error occurred.
197 * @param[in] line Line on which the error occurred.
198 * @param[in] full Full size window
199 * @param[in] sub Sub-window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000200 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000201 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100202 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000203arm_compute::Status error_on_invalid_subwindow(const char *function, const char *file, const int line,
204 const Window &full, const Window &sub);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000205#define ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(f, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000206 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000207#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBWINDOW(f, s) \
208 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100209
Georgios Pinitas3faea252017-10-30 14:13:50 +0000210/** Return an error if the window can't be collapsed at the given dimension.
steniu01868e5412017-07-17 23:16:00 +0100211 *
212 * The window cannot be collapsed if the given dimension not equal to the full window's dimension or not start from 0.
213 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000214 * @param[in] function Function in which the error occurred.
215 * @param[in] file Name of the file where the error occurred.
216 * @param[in] line Line on which the error occurred.
217 * @param[in] full Full size window
218 * @param[in] window Window to be collapsed.
219 * @param[in] dim Dimension need to be checked.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000220 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000221 * @return Status
steniu01868e5412017-07-17 23:16:00 +0100222 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000223arm_compute::Status error_on_window_not_collapsable_at_dimension(const char *function, const char *file, const int line,
224 const Window &full, const Window &window, const int dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000225#define ARM_COMPUTE_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000226 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000227#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
228 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
steniu01868e5412017-07-17 23:16:00 +0100229
Georgios Pinitas3faea252017-10-30 14:13:50 +0000230/** Return an error if the passed coordinates have too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100231 *
232 * The coordinates have too many dimensions if any of the dimensions greater or equal to max_dim is different from 0.
233 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000234 * @param[in] function Function in which the error occurred.
235 * @param[in] file Name of the file where the error occurred.
236 * @param[in] line Line on which the error occurred.
237 * @param[in] pos Coordinates to validate
238 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000239 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000240 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100241 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000242arm_compute::Status error_on_coordinates_dimensions_gte(const char *function, const char *file, const int line,
243 const Coordinates &pos, unsigned int max_dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000244#define ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000245 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000246#define ARM_COMPUTE_RETURN_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
247 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100248
Georgios Pinitas3faea252017-10-30 14:13:50 +0000249/** Return an error if the passed window has too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100250 *
251 * The window has too many dimensions if any of the dimension greater or equal to max_dim is different from 0.
252 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000253 * @param[in] function Function in which the error occurred.
254 * @param[in] file Name of the file where the error occurred.
255 * @param[in] line Line on which the error occurred.
256 * @param[in] win Window to validate
257 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000258 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000259 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100260 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000261arm_compute::Status error_on_window_dimensions_gte(const char *function, const char *file, const int line,
262 const Window &win, unsigned int max_dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000263#define ARM_COMPUTE_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000264 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000265#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
266 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100267
Georgios Pinitas3faea252017-10-30 14:13:50 +0000268/** Return an error if the passed dimension objects differ.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100269 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000270 * @param[in] function Function in which the error occurred.
271 * @param[in] file Name of the file where the error occurred.
272 * @param[in] line Line on which the error occurred.
273 * @param[in] dim1 The first object to be compared.
274 * @param[in] dim2 The second object to be compared.
275 * @param[in] dims (Optional) Further allowed objects.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000276 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000277 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100278 */
279template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000280arm_compute::Status error_on_mismatching_dimensions(const char *function, const char *file, int line,
281 const Dimensions<T> &dim1, const Dimensions<T> &dim2, Ts &&... dims)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100282{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000283 ARM_COMPUTE_RETURN_ON_ERROR(detail::for_each_error(detail::compare_dimension<T>(dim1, function, file, line), dim2, std::forward<Ts>(dims)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000284 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100285}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000286#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000287 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000288#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
289 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100290
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000291/** Return true if the given format has horizontal subsampling.
292 *
293 * @param[in] format Format to determine subsampling.
294 *
295 * @return True if the format can be subsampled horizontaly.
296 */
297inline bool has_format_horizontal_subsampling(Format format)
298{
299 return (format == Format::YUYV422 || format == Format::UYVY422 || format == Format::NV12 || format == Format::NV21 || format == Format::IYUV || format == Format::UV88) ? true : false;
300}
301
302/** Return true if the given format has vertical subsampling.
303 *
304 * @param[in] format Format to determine subsampling.
305 *
306 * @return True if the format can be subsampled verticaly.
307 */
308inline bool has_format_vertical_subsampling(Format format)
309{
310 return (format == Format::NV12 || format == Format::NV21 || format == Format::IYUV || format == Format::UV88) ? true : false;
311}
312
Matthew Bentham043613f2023-05-30 16:43:14 +0000313/** Adjust tensor shape size if width or height are odd for a given multi-planar format. No modification is done for other formats.
314 *
315 * @note Adding here a few links discussing the issue of odd size and sharing the same solution:
316 * <a href="https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/graphics/java/android/graphics/YuvImage.java">Android Source</a>
317 * <a href="https://groups.google.com/a/webmproject.org/forum/#!topic/webm-discuss/LaCKpqiDTXM">WebM</a>
318 * <a href="https://bugs.chromium.org/p/libyuv/issues/detail?id=198&amp;can=1&amp;q=odd%20width">libYUV</a>
319 * <a href="https://sourceforge.net/p/raw-yuvplayer/bugs/1/">YUVPlayer</a> *
320 *
321 * @param[in, out] shape Tensor shape of 2D size
322 * @param[in] format Format of the tensor
323 *
324 * @return The adjusted tensor shape.
325 */
326inline TensorShape adjust_odd_shape(const TensorShape &shape, Format format)
327{
328 TensorShape output{ shape };
329
330 // Force width to be even for formats which require subsampling of the U and V channels
331 if(has_format_horizontal_subsampling(format))
332 {
333 output.set(0, (output.x() + 1) & ~1U);
334 }
335
336 // Force height to be even for formats which require subsampling of the U and V channels
337 if(has_format_vertical_subsampling(format))
338 {
339 output.set(1, (output.y() + 1) & ~1U);
340 }
341
342 return output;
343}
344
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100345/** Return an error if the passed tensor objects are not even.
346 *
347 * @param[in] function Function in which the error occurred.
348 * @param[in] file Name of the file where the error occurred.
349 * @param[in] line Line on which the error occurred.
350 * @param[in] format Format to check if odd shape is allowed
351 * @param[in] tensor1 The first object to be compared for odd shape.
352 * @param[in] tensors (Optional) Further allowed objects.
353 *
354 * @return Status
355 */
356template <typename... Ts>
357arm_compute::Status error_on_tensors_not_even(const char *function, const char *file, int line,
358 const Format &format, const ITensor *tensor1, Ts... tensors)
359{
360 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor1 == nullptr, function, file, line);
361 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
362 const std::array < const ITensor *, 1 + sizeof...(Ts) > tensors_info_array{ { tensor1, std::forward<Ts>(tensors)... } };
363 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_info_array.cbegin(), tensors_info_array.cend(), [&](const ITensor * tensor)
364 {
365 const TensorShape correct_shape = adjust_odd_shape(tensor->info()->tensor_shape(), format);
366 return detail::have_different_dimensions(tensor->info()->tensor_shape(), correct_shape, 2);
367 }),
368 function, file, line, "Tensor shape has odd dimensions");
369 return arm_compute::Status{};
370}
371
372#define ARM_COMPUTE_ERROR_ON_TENSORS_NOT_EVEN(...) \
373 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
374#define ARM_COMPUTE_RETURN_ERROR_ON_TENSORS_NOT_EVEN(...) \
375 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
376
Matthew Bentham7d9a78e2023-05-31 13:18:33 +0000377/** Calculate subsampled shape for a given format and channel
378 *
379 * @param[in] shape Shape of the tensor to calculate the extracted channel.
380 * @param[in] format Format of the tensor.
381 * @param[in] channel Channel to create tensor shape to be extracted.
382 *
383 * @return The subsampled tensor shape.
384 */
385inline TensorShape calculate_subsampled_shape(const TensorShape &shape, Format format, Channel channel = Channel::UNKNOWN)
386{
387 TensorShape output{ shape };
388
389 // Subsample shape only for U or V channel
390 if(Channel::U == channel || Channel::V == channel || Channel::UNKNOWN == channel)
391 {
392 // Subsample width for the tensor shape when channel is U or V
393 if(has_format_horizontal_subsampling(format))
394 {
395 output.set(0, output.x() / 2U);
396 }
397
398 // Subsample height for the tensor shape when channel is U or V
399 if(has_format_vertical_subsampling(format))
400 {
401 output.set(1, output.y() / 2U);
402 }
403 }
404
405 return output;
406}
407
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000408/** Return an error if the passed tensor objects are not sub-sampled.
409 *
410 * @param[in] function Function in which the error occurred.
411 * @param[in] file Name of the file where the error occurred.
412 * @param[in] line Line on which the error occurred.
413 * @param[in] format Format to check if sub-sampling allowed.
414 * @param[in] shape The tensor shape to calculate sub-sampling from.
415 * @param[in] tensor1 The first object to be compared.
416 * @param[in] tensors (Optional) Further allowed objects.
417 *
418 * @return Status
419 */
420template <typename... Ts>
421arm_compute::Status error_on_tensors_not_subsampled(const char *function, const char *file, int line,
422 const Format &format, const TensorShape &shape, const ITensor *tensor1, Ts... tensors)
423{
424 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor1 == nullptr, function, file, line);
425 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
426 const TensorShape sub2_shape = calculate_subsampled_shape(shape, format);
427 const std::array < const ITensor *, 1 + sizeof...(Ts) > tensors_info_array{ { tensor1, std::forward<Ts>(tensors)... } };
428 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_info_array.cbegin(), tensors_info_array.cend(), [&](const ITensor * tensor)
429 {
430 return detail::have_different_dimensions(tensor->info()->tensor_shape(), sub2_shape, 2);
431 }),
432 function, file, line, "Tensor shape has mismatch dimensions for sub-sampling");
433 return arm_compute::Status{};
434}
435
436#define ARM_COMPUTE_ERROR_ON_TENSORS_NOT_SUBSAMPLED(...) \
437 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensors_not_subsampled(__func__, __FILE__, __LINE__, __VA_ARGS__))
438#define ARM_COMPUTE_RETURN_ERROR_ON_TENSORS_NOT_SUBSAMPLED(...) \
439 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensors_not_subsampled(__func__, __FILE__, __LINE__, __VA_ARGS__))
440
Georgios Pinitas3faea252017-10-30 14:13:50 +0000441/** Return an error if the passed two tensor infos have different shapes from the given dimension
442 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000443 * @param[in] function Function in which the error occurred.
444 * @param[in] file Name of the file where the error occurred.
445 * @param[in] line Line on which the error occurred.
446 * @param[in] tensor_info_1 The first tensor info to be compared.
447 * @param[in] tensor_info_2 The second tensor info to be compared.
448 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000449 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000450 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000451 */
452template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000453inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
454 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000455{
456 return error_on_mismatching_shapes(function, file, line, 0U, tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)...);
457}
458/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100459 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000460 * @param[in] function Function in which the error occurred.
461 * @param[in] file Name of the file where the error occurred.
462 * @param[in] line Line on which the error occurred.
463 * @param[in] tensor_1 The first tensor to be compared.
464 * @param[in] tensor_2 The second tensor to be compared.
465 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000466 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000467 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100468 */
469template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000470inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
471 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100472{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000473 return error_on_mismatching_shapes(function, file, line, 0U, tensor_1, tensor_2, std::forward<Ts>(tensors)...);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100474}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000475/** Return an error if the passed two tensors have different shapes from the given dimension
476 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000477 * @param[in] function Function in which the error occurred.
478 * @param[in] file Name of the file where the error occurred.
479 * @param[in] line Line on which the error occurred.
480 * @param[in] upper_dim The dimension from which to check.
481 * @param[in] tensor_info_1 The first tensor info to be compared.
482 * @param[in] tensor_info_2 The second tensor info to be compared.
483 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000484 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000485 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000486 */
487template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000488inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
489 unsigned int upper_dim, const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000490{
491 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_1 == nullptr, function, file, line);
492 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_2 == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100493 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensor_infos...));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100494
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100495 const std::array < const ITensorInfo *, 2 + sizeof...(Ts) > tensors_info_array{ { tensor_info_1, tensor_info_2, tensor_infos... } };
Georgios Pinitas3faea252017-10-30 14:13:50 +0000496 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(std::next(tensors_info_array.cbegin()), tensors_info_array.cend(), [&](const ITensorInfo * tensor_info)
497 {
498 return detail::have_different_dimensions((*tensors_info_array.cbegin())->tensor_shape(), tensor_info->tensor_shape(), upper_dim);
499 }),
500 function, file, line, "Tensors have different shapes");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000501 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000502}
503/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100504 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000505 * @param[in] function Function in which the error occurred.
506 * @param[in] file Name of the file where the error occurred.
507 * @param[in] line Line on which the error occurred.
508 * @param[in] upper_dim The dimension from which to check.
509 * @param[in] tensor_1 The first tensor to be compared.
510 * @param[in] tensor_2 The second tensor to be compared.
511 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000512 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000513 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100514 */
515template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000516inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
517 unsigned int upper_dim, const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100518{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000519 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_1 == nullptr, function, file, line);
520 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_2 == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100521 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensors...));
Georgios Pinitas3faea252017-10-30 14:13:50 +0000522 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(function, file, line, upper_dim, tensor_1->info(), tensor_2->info(),
523 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000524 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100525}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000526#define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000527 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000528#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(...) \
529 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100530
Michalis Spyrou7a569252018-03-01 12:03:14 +0000531/** Return an error if the passed tensor infos have different data layouts
532 *
533 * @param[in] function Function in which the error occurred.
534 * @param[in] file Name of the file where the error occurred.
535 * @param[in] line Line on which the error occurred.
536 * @param[in] tensor_info The first tensor info to be compared.
537 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
538 *
539 * @return Status
540 */
541template <typename... Ts>
542inline arm_compute::Status error_on_mismatching_data_layouts(const char *function, const char *file, const int line,
543 const ITensorInfo *tensor_info, Ts... tensor_infos)
544{
545 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100546 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensor_infos...));
Michalis Spyrou7a569252018-03-01 12:03:14 +0000547
548 DataLayout &&tensor_data_layout = tensor_info->data_layout();
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100549 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { tensor_infos... } };
Michalis Spyrou7a569252018-03-01 12:03:14 +0000550 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
551 {
552 return tensor_info_obj->data_layout() != tensor_data_layout;
553 }),
554 function, file, line, "Tensors have different data layouts");
555 return arm_compute::Status{};
556}
557/** Return an error if the passed tensors have different data layouts
558 *
559 * @param[in] function Function in which the error occurred.
560 * @param[in] file Name of the file where the error occurred.
561 * @param[in] line Line on which the error occurred.
562 * @param[in] tensor The first tensor to be compared.
563 * @param[in] tensors (Optional) Further allowed tensors.
564 *
565 * @return Status
566 */
567template <typename... Ts>
568inline arm_compute::Status error_on_mismatching_data_layouts(const char *function, const char *file, const int line,
569 const ITensor *tensor, Ts... tensors)
570{
571 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
572 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
573 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_layouts(function, file, line, tensor->info(),
574 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
575 return arm_compute::Status{};
576}
577#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
578 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
579#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
580 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
581
Georgios Pinitas3faea252017-10-30 14:13:50 +0000582/** Return an error if the passed two tensor infos have different data types
583 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000584 * @param[in] function Function in which the error occurred.
585 * @param[in] file Name of the file where the error occurred.
586 * @param[in] line Line on which the error occurred.
587 * @param[in] tensor_info The first tensor info to be compared.
588 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000589 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000590 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000591 */
592template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000593inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
594 const ITensorInfo *tensor_info, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000595{
596 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100597 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensor_infos...));
Georgios Pinitas3faea252017-10-30 14:13:50 +0000598
599 DataType &&tensor_data_type = tensor_info->data_type();
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100600 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { tensor_infos... } };
Georgios Pinitas3faea252017-10-30 14:13:50 +0000601 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
602 {
603 return tensor_info_obj->data_type() != tensor_data_type;
604 }),
605 function, file, line, "Tensors have different data types");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000606 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000607}
608/** Return an error if the passed two tensors have different data types
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100609 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000610 * @param[in] function Function in which the error occurred.
611 * @param[in] file Name of the file where the error occurred.
612 * @param[in] line Line on which the error occurred.
613 * @param[in] tensor The first tensor to be compared.
614 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000615 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000616 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100617 */
618template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000619inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
620 const ITensor *tensor, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100621{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000622 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100623 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, tensors...));
Georgios Pinitas3faea252017-10-30 14:13:50 +0000624 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(function, file, line, tensor->info(),
625 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000626 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100627}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000628#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000629 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000630#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
631 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100632
Daniil Efremoveed841c2017-11-09 19:05:25 +0700633/** Return an error if the passed tensor infos have different asymmetric quantized data types or different quantization info
634 *
635 * @note: If the first tensor info doesn't have asymmetric quantized data type, the function returns without throwing an error
636 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000637 * @param[in] function Function in which the error occurred.
638 * @param[in] file Name of the file where the error occurred.
639 * @param[in] line Line on which the error occurred.
640 * @param[in] tensor_info_1 The first tensor info to be compared.
641 * @param[in] tensor_info_2 The second tensor info to be compared.
642 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700643 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000644 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700645 */
646template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000647inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
648 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700649{
650 DataType &&first_data_type = tensor_info_1->data_type();
651 const QuantizationInfo first_quantization_info = tensor_info_1->quantization_info();
652
Michalis Spyrouba27e442019-05-28 10:04:57 +0100653 if(!is_data_type_quantized(first_data_type))
Daniil Efremoveed841c2017-11-09 19:05:25 +0700654 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000655 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700656 }
657
658 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
659 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
660 {
661 return tensor_info->data_type() != first_data_type;
662 }),
663 function, file, line, "Tensors have different asymmetric quantized data types");
664 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
665 {
666 return tensor_info->quantization_info() != first_quantization_info;
667 }),
668 function, file, line, "Tensors have different quantization information");
669
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000670 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700671}
672/** Return an error if the passed tensor have different asymmetric quantized data types or different quantization info
673 *
674 * @note: If the first tensor doesn't have asymmetric quantized data type, the function returns without throwing an error
675 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000676 * @param[in] function Function in which the error occurred.
677 * @param[in] file Name of the file where the error occurred.
678 * @param[in] line Line on which the error occurred.
679 * @param[in] tensor_1 The first tensor to be compared.
680 * @param[in] tensor_2 The second tensor to be compared.
681 * @param[in] tensors (Optional) Further allowed tensors.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700682 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000683 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700684 */
685template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000686inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
687 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700688{
689 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(function, file, line, tensor_1->info(), tensor_2->info(),
690 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000691 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700692}
693#define ARM_COMPUTE_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
694 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
695#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
696 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
697
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100698/** Throw an error if the format of the passed tensor/multi-image does not match any of the formats provided.
699 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000700 * @param[in] function Function in which the error occurred.
701 * @param[in] file Name of the file where the error occurred.
702 * @param[in] line Line on which the error occurred.
703 * @param[in] object Tensor/multi-image to validate.
704 * @param[in] format First format allowed.
705 * @param[in] formats (Optional) Further allowed formats.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100706 */
707template <typename T, typename F, typename... Fs>
708void error_on_format_not_in(const char *function, const char *file, const int line,
709 const T *object, F &&format, Fs &&... formats)
710{
711 ARM_COMPUTE_ERROR_ON_LOC(object == nullptr, function, file, line);
712
713 Format &&object_format = object->info()->format();
714 ARM_COMPUTE_UNUSED(object_format);
715
716 ARM_COMPUTE_ERROR_ON_LOC(object_format == Format::UNKNOWN, function, file, line);
717
718 const std::array<F, sizeof...(Fs)> formats_array{ { std::forward<Fs>(formats)... } };
719 ARM_COMPUTE_UNUSED(formats_array);
720
721 ARM_COMPUTE_ERROR_ON_LOC_MSG(object_format != format && std::none_of(formats_array.begin(), formats_array.end(), [&](const F & f)
722 {
723 return f == object_format;
724 }),
725 function, file, line, "Format %s not supported by this kernel", string_from_format(object_format).c_str());
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100726 ARM_COMPUTE_UNUSED(function, format, file, line);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100727}
728#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t, ...) ::arm_compute::error_on_format_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
729
Georgios Pinitas3faea252017-10-30 14:13:50 +0000730/** Return an error if the data type of the passed tensor info does not match any of the data types provided.
731 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000732 * @param[in] function Function in which the error occurred.
733 * @param[in] file Name of the file where the error occurred.
734 * @param[in] line Line on which the error occurred.
735 * @param[in] tensor_info Tensor info to validate.
736 * @param[in] dt First data type allowed.
737 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000738 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000739 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000740 */
741template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000742inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
743 const ITensorInfo *tensor_info, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000744{
745 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
746
747 const DataType &tensor_dt = tensor_info->data_type(); //NOLINT
748 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
749
750 const std::array<T, sizeof...(Ts)> dts_array{ { std::forward<Ts>(dts)... } };
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100751 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG_VAR(tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T & d)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000752 {
753 return d == tensor_dt;
754 }),
755 function, file, line, "ITensor data type %s not supported by this kernel", string_from_data_type(tensor_dt).c_str());
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000756 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000757}
758/** 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 +0100759 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000760 * @param[in] function Function in which the error occurred.
761 * @param[in] file Name of the file where the error occurred.
762 * @param[in] line Line on which the error occurred.
763 * @param[in] tensor Tensor to validate.
764 * @param[in] dt First data type allowed.
765 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000766 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000767 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100768 */
769template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000770inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
771 const ITensor *tensor, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100772{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000773 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
774 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_not_in(function, file, line, tensor->info(), std::forward<T>(dt), std::forward<Ts>(dts)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000775 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100776}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000777#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000778 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 +0000779#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
780 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 +0100781
Georgios Pinitasf1adf112018-11-02 12:54:18 +0000782/** Return an error if the data layout of the passed tensor info does not match any of the data layouts provided.
783 *
784 * @param[in] function Function in which the error occurred.
785 * @param[in] file Name of the file where the error occurred.
786 * @param[in] line Line on which the error occurred.
787 * @param[in] tensor_info Tensor info to validate.
788 * @param[in] dl First data layout allowed.
789 * @param[in] dls (Optional) Further allowed data layouts.
790 *
791 * @return Status
792 */
793template <typename T, typename... Ts>
794inline arm_compute::Status error_on_data_layout_not_in(const char *function, const char *file, const int line,
795 const ITensorInfo *tensor_info, T &&dl, Ts &&... dls)
796{
797 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
798
799 const DataLayout &tensor_dl = tensor_info->data_layout(); //NOLINT
800 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dl == DataLayout::UNKNOWN, function, file, line);
801
802 const std::array<T, sizeof...(Ts)> dls_array{ { std::forward<Ts>(dls)... } };
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100803 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG_VAR(tensor_dl != dl && std::none_of(dls_array.begin(), dls_array.end(), [&](const T & l)
Georgios Pinitasf1adf112018-11-02 12:54:18 +0000804 {
805 return l == tensor_dl;
806 }),
807 function, file, line, "ITensor data layout %s not supported by this kernel", string_from_data_layout(tensor_dl).c_str());
808 return arm_compute::Status{};
809}
810/** Return an error if the data layout of the passed tensor does not match any of the data layout provided.
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] dl First data layout allowed.
817 * @param[in] dls (Optional) Further allowed data layouts.
818 *
819 * @return Status
820 */
821template <typename T, typename... Ts>
822inline arm_compute::Status error_on_data_layout_not_in(const char *function, const char *file, const int line,
823 const ITensor *tensor, T &&dl, Ts &&... dls)
824{
825 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
826 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)...));
827 return arm_compute::Status{};
828}
829#define ARM_COMPUTE_ERROR_ON_DATA_LAYOUT_NOT_IN(t, ...) \
830 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_data_layout_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
831#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_LAYOUT_NOT_IN(t, ...) \
832 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_layout_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
833
Georgios Pinitas3faea252017-10-30 14:13:50 +0000834/** 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.
835 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000836 * @param[in] function Function in which the error occurred.
837 * @param[in] file Name of the file where the error occurred.
838 * @param[in] line Line on which the error occurred.
839 * @param[in] tensor_info Tensor info to validate.
840 * @param[in] num_channels Number of channels to check
841 * @param[in] dt First data type allowed.
842 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000843 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000844 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000845 */
846template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000847inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
848 const ITensorInfo *tensor_info, size_t num_channels, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000849{
850 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)...));
851 const size_t tensor_nc = tensor_info->num_channels();
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100852 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);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000853 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000854}
855/** 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 +0100856 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000857 * @param[in] function Function in which the error occurred.
858 * @param[in] file Name of the file where the error occurred.
859 * @param[in] line Line on which the error occurred.
860 * @param[in] tensor Tensor to validate.
861 * @param[in] num_channels Number of channels to check
862 * @param[in] dt First data type allowed.
863 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000864 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000865 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100866 */
867template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000868inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
869 const ITensor *tensor, size_t num_channels, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100870{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000871 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
872 ARM_COMPUTE_RETURN_ON_ERROR(error_on_data_type_channel_not_in(function, file, line, tensor->info(), num_channels, std::forward<T>(dt), std::forward<Ts>(dts)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000873 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100874}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000875#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000876 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000877#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
878 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100879
Vidhya Sudhan Loganathanf1f49062018-05-25 13:21:26 +0100880/** Return an error if the data type of the passed tensor info is FP16 and FP16 extension is not supported by the device.
881 *
882 * @param[in] function Function in which the error occurred.
883 * @param[in] file Name of the file where the error occurred.
884 * @param[in] line Line on which the error occurred.
885 * @param[in] tensor_info Tensor info to validate.
886 * @param[in] is_fp16_supported Is fp16 supported by the device.
887 *
888 * @return Status
889 */
890inline arm_compute::Status error_on_unsupported_fp16(const char *function, const char *file, const int line,
891 const ITensorInfo *tensor_info, bool is_fp16_supported)
892{
893 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
894 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG((tensor_info->data_type() == DataType::F16 && !is_fp16_supported),
895 function, file, line, "FP16 not supported by the device");
896 return arm_compute::Status{};
897}
898
899/** Return an error if the data type of the passed tensor is FP16 and FP16 extension is not supported by the device.
900 *
901 * @param[in] function Function in which the error occurred.
902 * @param[in] file Name of the file where the error occurred.
903 * @param[in] line Line on which the error occurred.
904 * @param[in] tensor Tensor to validate.
905 * @param[in] is_fp16_supported Is fp16 supported by the device.
906 *
907 * @return Status
908 */
909inline arm_compute::Status error_on_unsupported_fp16(const char *function, const char *file, const int line,
910 const ITensor *tensor, bool is_fp16_supported)
911{
912 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
913 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unsupported_fp16(function, file, line, tensor->info(), is_fp16_supported));
914 return arm_compute::Status{};
915}
916
Georgios Pinitas3faea252017-10-30 14:13:50 +0000917/** Return an error if the tensor is not 2D.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100918 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000919 * @param[in] function Function in which the error occurred.
920 * @param[in] file Name of the file where the error occurred.
921 * @param[in] line Line on which the error occurred.
922 * @param[in] tensor Tensor to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000923 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000924 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100925 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000926arm_compute::Status error_on_tensor_not_2d(const char *function, const char *file, const int line,
927 const ITensor *tensor);
Michalis Spyroud1794eb2018-06-15 16:15:26 +0100928
929/** Return an error if the tensor info is not 2D.
930 *
931 * @param[in] function Function in which the error occurred.
932 * @param[in] file Name of the file where the error occurred.
933 * @param[in] line Line on which the error occurred.
934 * @param[in] tensor Tensor info to validate.
935 *
936 * @return Status
937 */
938arm_compute::Status error_on_tensor_not_2d(const char *function, const char *file, const int line,
939 const ITensorInfo *tensor);
940
Georgios Pinitas3faea252017-10-30 14:13:50 +0000941#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000942 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000943#define ARM_COMPUTE_RETURN_ERROR_ON_TENSOR_NOT_2D(t) \
944 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100945
Georgios Pinitas3faea252017-10-30 14:13:50 +0000946/** Return an error if the channel is not in channels.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100947 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000948 * @param[in] function Function in which the error occurred.
949 * @param[in] file Name of the file where the error occurred.
950 * @param[in] line Line on which the error occurred.
951 * @param[in] cn Input channel
952 * @param[in] channel First channel allowed.
953 * @param[in] channels (Optional) Further allowed channels.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000954 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000955 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100956 */
957template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000958inline arm_compute::Status error_on_channel_not_in(const char *function, const char *file, const int line,
959 T cn, T &&channel, Ts &&... channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100960{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000961 ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100962
963 const std::array<T, sizeof...(Ts)> channels_array{ { std::forward<Ts>(channels)... } };
Georgios Pinitas3faea252017-10-30 14:13:50 +0000964 ARM_COMPUTE_RETURN_ERROR_ON_LOC(channel != cn && std::none_of(channels_array.begin(), channels_array.end(), [&](const T & f)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100965 {
966 return f == cn;
967 }),
968 function, file, line);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000969 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100970}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000971#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000972 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 +0000973#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
974 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 +0100975
Georgios Pinitas3faea252017-10-30 14:13:50 +0000976/** Return an error if the channel is not in format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100977 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000978 * @param[in] function Function in which the error occurred.
979 * @param[in] file Name of the file where the error occurred.
980 * @param[in] line Line on which the error occurred.
981 * @param[in] fmt Input channel
982 * @param[in] cn First channel allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000983 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000984 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100985 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000986arm_compute::Status error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
987 Format fmt, Channel cn);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000988#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000989 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 +0000990#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
991 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 +0100992
Georgios Pinitas3faea252017-10-30 14:13:50 +0000993/** Return an error if the kernel is not configured.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100994 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000995 * @param[in] function Function in which the error occurred.
996 * @param[in] file Name of the file where the error occurred.
997 * @param[in] line Line on which the error occurred.
998 * @param[in] kernel Kernel to validate.
Alex Gildayc357c472018-03-21 13:54:09 +0000999 *
1000 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001001 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001002arm_compute::Status error_on_unconfigured_kernel(const char *function, const char *file, const int line,
1003 const IKernel *kernel);
Georgios Pinitas3faea252017-10-30 14:13:50 +00001004#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001005 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Georgios Pinitas3faea252017-10-30 14:13:50 +00001006#define ARM_COMPUTE_RETURN_ERROR_ON_UNCONFIGURED_KERNEL(k) \
1007 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001008
Georgios Pinitas3faea252017-10-30 14:13:50 +00001009/** Return an error if if the coordinates and shape of the subtensor are within the parent tensor.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001010 *
1011 * @param[in] function Function in which the error occurred.
1012 * @param[in] file Name of the file where the error occurred.
1013 * @param[in] line Line on which the error occurred.
1014 * @param[in] parent_shape Parent tensor shape
1015 * @param[in] coords Coordinates inside the parent tensor where the first element of the subtensor is
1016 * @param[in] shape Shape of the subtensor
Georgios Pinitas3faea252017-10-30 14:13:50 +00001017 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001018 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001019 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001020arm_compute::Status error_on_invalid_subtensor(const char *function, const char *file, const int line,
1021 const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape);
Georgios Pinitas3faea252017-10-30 14:13:50 +00001022#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001023 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +00001024#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
1025 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001026
Georgios Pinitas3faea252017-10-30 14:13:50 +00001027/** 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 +01001028 *
1029 * @param[in] function Function in which the error occurred.
1030 * @param[in] file Name of the file where the error occurred.
1031 * @param[in] line Line on which the error occurred.
1032 * @param[in] parent_valid_region Parent valid region.
1033 * @param[in] valid_region Valid region of subtensor.
Georgios Pinitas3faea252017-10-30 14:13:50 +00001034 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001035 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001036 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +00001037arm_compute::Status error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
1038 const ValidRegion &parent_valid_region, const ValidRegion &valid_region);
Georgios Pinitas3faea252017-10-30 14:13:50 +00001039#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +00001040 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
Georgios Pinitas3faea252017-10-30 14:13:50 +00001041#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
1042 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001043}
Michalis Spyrouf4643372019-11-29 16:17:13 +00001044#endif /* ARM_COMPUTE_VALIDATE_H*/