blob: 08e872fd90bb285d41f9b928e15ac6272cd7c0c2 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Ioan-Cristian Szabo91d20d92017-10-27 17:35:40 +01002 * Copyright (c) 2016-2018 ARM Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#ifndef __ARM_COMPUTE_VALIDATE_H__
25#define __ARM_COMPUTE_VALIDATE_H__
26
27#include "arm_compute/core/Error.h"
28#include "arm_compute/core/HOGInfo.h"
29#include "arm_compute/core/IKernel.h"
30#include "arm_compute/core/IMultiHOG.h"
31#include "arm_compute/core/IMultiImage.h"
32#include "arm_compute/core/ITensor.h"
33#include "arm_compute/core/MultiImageInfo.h"
34#include "arm_compute/core/Window.h"
35
36#include <algorithm>
37
38namespace arm_compute
39{
40namespace detail
41{
42/* Check whether two dimension objects differ.
43 *
44 * @param[in] dim1 First object to be compared.
45 * @param[in] dim2 Second object to be compared.
46 * @param[in] upper_dim The dimension from which to check.
47 *
48 * @return Return true if the two objects are different.
49 */
50template <typename T>
51inline bool have_different_dimensions(const Dimensions<T> &dim1, const Dimensions<T> &dim2, unsigned int upper_dim)
52{
53 for(unsigned int i = upper_dim; i < arm_compute::Dimensions<T>::num_max_dimensions; ++i)
54 {
55 if(dim1[i] != dim2[i])
56 {
57 return true;
58 }
59 }
60
61 return false;
62}
63
64/** Functor to compare two @ref Dimensions objects and throw an error on mismatch.
65 *
66 * @param[in] dim Object to compare against.
Georgios Pinitas3faea252017-10-30 14:13:50 +000067 * @param[in] function Function in which the error occurred.
68 * @param[in] file File in which the error occurred.
69 * @param[in] line Line in which the error occurred.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010070 */
71template <typename T>
72class compare_dimension
73{
74public:
75 compare_dimension(const Dimensions<T> &dim, const char *function, const char *file, int line)
76 : _dim{ dim }, _function{ function }, _file{ file }, _line{ line }
77 {
78 }
79
80 /** Compare the given object against the stored one.
81 *
82 * @param[in] dim To be compared object.
83 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000084 arm_compute::Status operator()(const Dimensions<T> &dim)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010085 {
Georgios Pinitas3faea252017-10-30 14:13:50 +000086 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(have_different_dimensions(_dim, dim, 0), _function, _file, _line,
87 "Objects have different dimensions");
Georgios Pinitas631c41a2017-12-06 11:53:03 +000088 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +010089 }
90
91private:
92 const Dimensions<T> &_dim;
93 const char *const _function;
94 const char *const _file;
95 const int _line;
96};
Georgios Pinitas3faea252017-10-30 14:13:50 +000097
98template <typename F>
Georgios Pinitas631c41a2017-12-06 11:53:03 +000099inline arm_compute::Status for_each_error(F &&)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000100{
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000101 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000102}
103
104template <typename F, typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000105inline arm_compute::Status for_each_error(F &&func, T &&arg, Ts &&... args)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000106{
107 ARM_COMPUTE_RETURN_ON_ERROR(func(arg));
108 ARM_COMPUTE_RETURN_ON_ERROR(for_each_error(func, args...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000109 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000110}
111
112template <typename T>
113struct get_tensor_info_t;
114template <>
115struct get_tensor_info_t<ITensorInfo *>
116{
117 ITensorInfo *operator()(const ITensor *tensor)
118 {
119 return tensor->info();
120 }
121};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100122} // namespace detail
Georgios Pinitas3faea252017-10-30 14:13:50 +0000123
124/** Create an error if one of the pointers is a nullptr.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100125 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000126 * @param[in] function Function in which the error occurred.
127 * @param[in] file Name of the file where the error occurred.
128 * @param[in] line Line on which the error occurred.
129 * @param[in] pointers Pointers to check against nullptr.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000130 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000131 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100132 */
133template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000134inline arm_compute::Status error_on_nullptr(const char *function, const char *file, const int line, Ts &&... pointers)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100135{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000136 const std::array<const void *, sizeof...(Ts)> pointers_array{ { std::forward<Ts>(pointers)... } };
137 bool has_nullptr = std::any_of(pointers_array.begin(), pointers_array.end(), [&](const void *ptr)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100138 {
Georgios Pinitas3faea252017-10-30 14:13:50 +0000139 return (ptr == nullptr);
140 });
141 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(has_nullptr, function, file, line, "Nullptr object!");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000142 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100143}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000144#define ARM_COMPUTE_ERROR_ON_NULLPTR(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000145 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000146#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...) \
147 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100148
Georgios Pinitas3faea252017-10-30 14:13:50 +0000149/** Return an error if the passed window is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100150 *
151 * The subwindow is invalid if:
152 * - It is not a valid window.
153 * - Its dimensions don't match the full window's ones
154 * - The step for each of its dimension is not identical to the corresponding one of the full window.
155 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000156 * @param[in] function Function in which the error occurred.
157 * @param[in] file Name of the file where the error occurred.
158 * @param[in] line Line on which the error occurred.
159 * @param[in] full Full size window
160 * @param[in] win Window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000161 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000162 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100163 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000164arm_compute::Status error_on_mismatching_windows(const char *function, const char *file, const int line,
165 const Window &full, const Window &win);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000166#define ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000167 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000168#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
169 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100170
Georgios Pinitas3faea252017-10-30 14:13:50 +0000171/** Return an error if the passed subwindow is invalid.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100172 *
173 * The subwindow is invalid if:
174 * - It is not a valid window.
175 * - It is not fully contained inside the full window
176 * - The step for each of its dimension is not identical to the corresponding one of the full window.
177 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000178 * @param[in] function Function in which the error occurred.
179 * @param[in] file Name of the file where the error occurred.
180 * @param[in] line Line on which the error occurred.
181 * @param[in] full Full size window
182 * @param[in] sub Sub-window to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000183 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000184 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100185 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000186arm_compute::Status error_on_invalid_subwindow(const char *function, const char *file, const int line,
187 const Window &full, const Window &sub);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000188#define ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(f, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000189 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000190#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBWINDOW(f, s) \
191 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100192
Georgios Pinitas3faea252017-10-30 14:13:50 +0000193/** Return an error if the window can't be collapsed at the given dimension.
steniu01868e5412017-07-17 23:16:00 +0100194 *
195 * The window cannot be collapsed if the given dimension not equal to the full window's dimension or not start from 0.
196 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000197 * @param[in] function Function in which the error occurred.
198 * @param[in] file Name of the file where the error occurred.
199 * @param[in] line Line on which the error occurred.
200 * @param[in] full Full size window
201 * @param[in] window Window to be collapsed.
202 * @param[in] dim Dimension need to be checked.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000203 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000204 * @return Status
steniu01868e5412017-07-17 23:16:00 +0100205 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000206arm_compute::Status error_on_window_not_collapsable_at_dimension(const char *function, const char *file, const int line,
207 const Window &full, const Window &window, const int dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000208#define ARM_COMPUTE_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000209 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000210#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
211 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
steniu01868e5412017-07-17 23:16:00 +0100212
Georgios Pinitas3faea252017-10-30 14:13:50 +0000213/** Return an error if the passed coordinates have too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100214 *
215 * The coordinates have too many dimensions if any of the dimensions greater or equal to max_dim is different from 0.
216 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000217 * @param[in] function Function in which the error occurred.
218 * @param[in] file Name of the file where the error occurred.
219 * @param[in] line Line on which the error occurred.
220 * @param[in] pos Coordinates to validate
221 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000222 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000223 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100224 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000225arm_compute::Status error_on_coordinates_dimensions_gte(const char *function, const char *file, const int line,
226 const Coordinates &pos, unsigned int max_dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000227#define ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000228 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000229#define ARM_COMPUTE_RETURN_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
230 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100231
Georgios Pinitas3faea252017-10-30 14:13:50 +0000232/** Return an error if the passed window has too many dimensions.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100233 *
234 * The window has too many dimensions if any of the dimension greater or equal to max_dim is different from 0.
235 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000236 * @param[in] function Function in which the error occurred.
237 * @param[in] file Name of the file where the error occurred.
238 * @param[in] line Line on which the error occurred.
239 * @param[in] win Window to validate
240 * @param[in] max_dim Maximum number of dimensions allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000241 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000242 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100243 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000244arm_compute::Status error_on_window_dimensions_gte(const char *function, const char *file, const int line,
245 const Window &win, unsigned int max_dim);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000246#define ARM_COMPUTE_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000247 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000248#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
249 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100250
Georgios Pinitas3faea252017-10-30 14:13:50 +0000251/** Return an error if the passed dimension objects differ.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100252 *
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] dim1 The first object to be compared.
257 * @param[in] dim2 The second object to be compared.
258 * @param[in] dims (Optional) Further allowed objects.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000259 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000260 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100261 */
262template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000263arm_compute::Status error_on_mismatching_dimensions(const char *function, const char *file, int line,
264 const Dimensions<T> &dim1, const Dimensions<T> &dim2, Ts &&... dims)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100265{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000266 ARM_COMPUTE_RETURN_ON_ERROR(detail::for_each_error(detail::compare_dimension<T>(dim1, function, file, line), dim2, std::forward<Ts>(dims)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000267 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100268}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000269#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000270 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000271#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
272 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100273
Ioan-Cristian Szabo9414f642017-10-27 17:35:40 +0100274/** Return an error if the passed tensor objects are not even.
275 *
276 * @param[in] function Function in which the error occurred.
277 * @param[in] file Name of the file where the error occurred.
278 * @param[in] line Line on which the error occurred.
279 * @param[in] format Format to check if odd shape is allowed
280 * @param[in] tensor1 The first object to be compared for odd shape.
281 * @param[in] tensors (Optional) Further allowed objects.
282 *
283 * @return Status
284 */
285template <typename... Ts>
286arm_compute::Status error_on_tensors_not_even(const char *function, const char *file, int line,
287 const Format &format, const ITensor *tensor1, Ts... tensors)
288{
289 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor1 == nullptr, function, file, line);
290 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
291 const std::array < const ITensor *, 1 + sizeof...(Ts) > tensors_info_array{ { tensor1, std::forward<Ts>(tensors)... } };
292 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_info_array.cbegin(), tensors_info_array.cend(), [&](const ITensor * tensor)
293 {
294 const TensorShape correct_shape = adjust_odd_shape(tensor->info()->tensor_shape(), format);
295 return detail::have_different_dimensions(tensor->info()->tensor_shape(), correct_shape, 2);
296 }),
297 function, file, line, "Tensor shape has odd dimensions");
298 return arm_compute::Status{};
299}
300
301#define ARM_COMPUTE_ERROR_ON_TENSORS_NOT_EVEN(...) \
302 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
303#define ARM_COMPUTE_RETURN_ERROR_ON_TENSORS_NOT_EVEN(...) \
304 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensors_not_even(__func__, __FILE__, __LINE__, __VA_ARGS__))
305
Georgios Pinitas3faea252017-10-30 14:13:50 +0000306/** Return an error if the passed two tensor infos have different shapes from the given dimension
307 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000308 * @param[in] function Function in which the error occurred.
309 * @param[in] file Name of the file where the error occurred.
310 * @param[in] line Line on which the error occurred.
311 * @param[in] tensor_info_1 The first tensor info to be compared.
312 * @param[in] tensor_info_2 The second tensor info to be compared.
313 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000314 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000315 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000316 */
317template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000318inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
319 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000320{
321 return error_on_mismatching_shapes(function, file, line, 0U, tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)...);
322}
323/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100324 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000325 * @param[in] function Function in which the error occurred.
326 * @param[in] file Name of the file where the error occurred.
327 * @param[in] line Line on which the error occurred.
328 * @param[in] tensor_1 The first tensor to be compared.
329 * @param[in] tensor_2 The second tensor to be compared.
330 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000331 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000332 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100333 */
334template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000335inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
336 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100337{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000338 return error_on_mismatching_shapes(function, file, line, 0U, tensor_1, tensor_2, std::forward<Ts>(tensors)...);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100339}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000340/** Return an error if the passed two tensors have different shapes from the given dimension
341 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000342 * @param[in] function Function in which the error occurred.
343 * @param[in] file Name of the file where the error occurred.
344 * @param[in] line Line on which the error occurred.
345 * @param[in] upper_dim The dimension from which to check.
346 * @param[in] tensor_info_1 The first tensor info to be compared.
347 * @param[in] tensor_info_2 The second tensor info to be compared.
348 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000349 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000350 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000351 */
352template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000353inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
354 unsigned int upper_dim, const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000355{
356 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_1 == nullptr, function, file, line);
357 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_2 == nullptr, function, file, line);
358 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100359
Georgios Pinitas3faea252017-10-30 14:13:50 +0000360 const std::array < const ITensorInfo *, 2 + sizeof...(Ts) > tensors_info_array{ { tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)... } };
361 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(std::next(tensors_info_array.cbegin()), tensors_info_array.cend(), [&](const ITensorInfo * tensor_info)
362 {
363 return detail::have_different_dimensions((*tensors_info_array.cbegin())->tensor_shape(), tensor_info->tensor_shape(), upper_dim);
364 }),
365 function, file, line, "Tensors have different shapes");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000366 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000367}
368/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100369 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000370 * @param[in] function Function in which the error occurred.
371 * @param[in] file Name of the file where the error occurred.
372 * @param[in] line Line on which the error occurred.
373 * @param[in] upper_dim The dimension from which to check.
374 * @param[in] tensor_1 The first tensor to be compared.
375 * @param[in] tensor_2 The second tensor to be compared.
376 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000377 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000378 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100379 */
380template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000381inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
382 unsigned int upper_dim, const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100383{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000384 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_1 == nullptr, function, file, line);
385 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_2 == nullptr, function, file, line);
386 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
387 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(function, file, line, upper_dim, tensor_1->info(), tensor_2->info(),
388 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000389 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100390}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000391#define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000392 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000393#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(...) \
394 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100395
Michalis Spyrou7a569252018-03-01 12:03:14 +0000396/** Return an error if the passed tensor infos have different data layouts
397 *
398 * @param[in] function Function in which the error occurred.
399 * @param[in] file Name of the file where the error occurred.
400 * @param[in] line Line on which the error occurred.
401 * @param[in] tensor_info The first tensor info to be compared.
402 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
403 *
404 * @return Status
405 */
406template <typename... Ts>
407inline arm_compute::Status error_on_mismatching_data_layouts(const char *function, const char *file, const int line,
408 const ITensorInfo *tensor_info, Ts... tensor_infos)
409{
410 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
411 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
412
413 DataLayout &&tensor_data_layout = tensor_info->data_layout();
414 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { std::forward<Ts>(tensor_infos)... } };
415 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
416 {
417 return tensor_info_obj->data_layout() != tensor_data_layout;
418 }),
419 function, file, line, "Tensors have different data layouts");
420 return arm_compute::Status{};
421}
422/** Return an error if the passed tensors have different data layouts
423 *
424 * @param[in] function Function in which the error occurred.
425 * @param[in] file Name of the file where the error occurred.
426 * @param[in] line Line on which the error occurred.
427 * @param[in] tensor The first tensor to be compared.
428 * @param[in] tensors (Optional) Further allowed tensors.
429 *
430 * @return Status
431 */
432template <typename... Ts>
433inline arm_compute::Status error_on_mismatching_data_layouts(const char *function, const char *file, const int line,
434 const ITensor *tensor, Ts... tensors)
435{
436 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
437 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
438 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_layouts(function, file, line, tensor->info(),
439 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
440 return arm_compute::Status{};
441}
442#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
443 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
444#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(...) \
445 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_layouts(__func__, __FILE__, __LINE__, __VA_ARGS__))
446
Georgios Pinitas3faea252017-10-30 14:13:50 +0000447/** Return an error if the passed two tensor infos have different data types
448 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000449 * @param[in] function Function in which the error occurred.
450 * @param[in] file Name of the file where the error occurred.
451 * @param[in] line Line on which the error occurred.
452 * @param[in] tensor_info The first tensor info to be compared.
453 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000454 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000455 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000456 */
457template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000458inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
459 const ITensorInfo *tensor_info, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000460{
461 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
462 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
463
464 DataType &&tensor_data_type = tensor_info->data_type();
465 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { std::forward<Ts>(tensor_infos)... } };
466 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
467 {
468 return tensor_info_obj->data_type() != tensor_data_type;
469 }),
470 function, file, line, "Tensors have different data types");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000471 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000472}
473/** Return an error if the passed two tensors have different data types
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100474 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000475 * @param[in] function Function in which the error occurred.
476 * @param[in] file Name of the file where the error occurred.
477 * @param[in] line Line on which the error occurred.
478 * @param[in] tensor The first tensor to be compared.
479 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000480 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000481 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100482 */
483template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000484inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
485 const ITensor *tensor, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100486{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000487 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
488 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
489 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(function, file, line, tensor->info(),
490 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000491 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100492}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000493#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000494 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000495#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
496 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100497
Georgios Pinitas3faea252017-10-30 14:13:50 +0000498/** Return an error if the passed tensor infos have different fixed point data types or different fixed point positions
499 *
500 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
501 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000502 * @param[in] function Function in which the error occurred.
503 * @param[in] file Name of the file where the error occurred.
504 * @param[in] line Line on which the error occurred.
505 * @param[in] tensor_info_1 The first tensor info to be compared.
506 * @param[in] tensor_info_2 The second tensor info to be compared.
507 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000508 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000509 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000510 */
511template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000512inline arm_compute::Status error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
513 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000514{
515 DataType &&first_data_type = tensor_info_1->data_type();
516 const int first_fixed_point_position = tensor_info_1->fixed_point_position();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100517
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000518 if(!is_data_type_fixed_point(first_data_type))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000519 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000520 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000521 }
522
523 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
524 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
525 {
526 return tensor_info->data_type() != first_data_type;
527 }),
528 function, file, line, "Tensors have different fixed point data types");
529 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
530 {
531 return tensor_info->fixed_point_position() != first_fixed_point_position;
532 }),
533 function, file, line, "Tensors have different fixed point positions");
534
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000535 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000536}
537/** Return an error if the passed tensor have different fixed point data types or different fixed point positions
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100538 *
539 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
540 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000541 * @param[in] function Function in which the error occurred.
542 * @param[in] file Name of the file where the error occurred.
543 * @param[in] line Line on which the error occurred.
544 * @param[in] tensor_1 The first tensor to be compared.
545 * @param[in] tensor_2 The second tensor to be compared.
546 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000547 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000548 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100549 */
550template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000551inline arm_compute::Status error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
552 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100553{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000554 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(function, file, line, tensor_1->info(), tensor_2->info(),
555 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000556 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100557}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000558#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000559 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000560#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
561 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100562
Daniil Efremoveed841c2017-11-09 19:05:25 +0700563/** Return an error if the passed tensor infos have different asymmetric quantized data types or different quantization info
564 *
565 * @note: If the first tensor info doesn't have asymmetric quantized data type, the function returns without throwing an error
566 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000567 * @param[in] function Function in which the error occurred.
568 * @param[in] file Name of the file where the error occurred.
569 * @param[in] line Line on which the error occurred.
570 * @param[in] tensor_info_1 The first tensor info to be compared.
571 * @param[in] tensor_info_2 The second tensor info to be compared.
572 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700573 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000574 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700575 */
576template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000577inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
578 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700579{
580 DataType &&first_data_type = tensor_info_1->data_type();
581 const QuantizationInfo first_quantization_info = tensor_info_1->quantization_info();
582
583 if(!is_data_type_quantized_asymmetric(first_data_type))
584 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000585 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700586 }
587
588 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
589 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
590 {
591 return tensor_info->data_type() != first_data_type;
592 }),
593 function, file, line, "Tensors have different asymmetric quantized data types");
594 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
595 {
596 return tensor_info->quantization_info() != first_quantization_info;
597 }),
598 function, file, line, "Tensors have different quantization information");
599
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000600 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700601}
602/** Return an error if the passed tensor have different asymmetric quantized data types or different quantization info
603 *
604 * @note: If the first tensor doesn't have asymmetric quantized data type, the function returns without throwing an error
605 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000606 * @param[in] function Function in which the error occurred.
607 * @param[in] file Name of the file where the error occurred.
608 * @param[in] line Line on which the error occurred.
609 * @param[in] tensor_1 The first tensor to be compared.
610 * @param[in] tensor_2 The second tensor to be compared.
611 * @param[in] tensors (Optional) Further allowed tensors.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700612 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000613 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700614 */
615template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000616inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
617 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700618{
619 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(function, file, line, tensor_1->info(), tensor_2->info(),
620 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000621 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700622}
623#define ARM_COMPUTE_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
624 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
625#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
626 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
627
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100628/** Throw an error if the format of the passed tensor/multi-image does not match any of the formats provided.
629 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000630 * @param[in] function Function in which the error occurred.
631 * @param[in] file Name of the file where the error occurred.
632 * @param[in] line Line on which the error occurred.
633 * @param[in] object Tensor/multi-image to validate.
634 * @param[in] format First format allowed.
635 * @param[in] formats (Optional) Further allowed formats.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100636 */
637template <typename T, typename F, typename... Fs>
638void error_on_format_not_in(const char *function, const char *file, const int line,
639 const T *object, F &&format, Fs &&... formats)
640{
641 ARM_COMPUTE_ERROR_ON_LOC(object == nullptr, function, file, line);
642
643 Format &&object_format = object->info()->format();
644 ARM_COMPUTE_UNUSED(object_format);
645
646 ARM_COMPUTE_ERROR_ON_LOC(object_format == Format::UNKNOWN, function, file, line);
647
648 const std::array<F, sizeof...(Fs)> formats_array{ { std::forward<Fs>(formats)... } };
649 ARM_COMPUTE_UNUSED(formats_array);
650
651 ARM_COMPUTE_ERROR_ON_LOC_MSG(object_format != format && std::none_of(formats_array.begin(), formats_array.end(), [&](const F & f)
652 {
653 return f == object_format;
654 }),
655 function, file, line, "Format %s not supported by this kernel", string_from_format(object_format).c_str());
656}
657#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t, ...) ::arm_compute::error_on_format_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
658
Georgios Pinitas3faea252017-10-30 14:13:50 +0000659/** Return an error if the data type of the passed tensor info does not match any of the data types provided.
660 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000661 * @param[in] function Function in which the error occurred.
662 * @param[in] file Name of the file where the error occurred.
663 * @param[in] line Line on which the error occurred.
664 * @param[in] tensor_info Tensor info to validate.
665 * @param[in] dt First data type allowed.
666 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000667 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000668 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000669 */
670template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000671inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
672 const ITensorInfo *tensor_info, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000673{
674 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
675
676 const DataType &tensor_dt = tensor_info->data_type(); //NOLINT
677 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
678
679 const std::array<T, sizeof...(Ts)> dts_array{ { std::forward<Ts>(dts)... } };
680 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T & d)
681 {
682 return d == tensor_dt;
683 }),
684 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 +0000685 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000686}
687/** 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 +0100688 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000689 * @param[in] function Function in which the error occurred.
690 * @param[in] file Name of the file where the error occurred.
691 * @param[in] line Line on which the error occurred.
692 * @param[in] tensor Tensor to validate.
693 * @param[in] dt First data type allowed.
694 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000695 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000696 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100697 */
698template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000699inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
700 const ITensor *tensor, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100701{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000702 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
703 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 +0000704 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100705}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000706#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000707 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 +0000708#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
709 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 +0100710
Georgios Pinitas3faea252017-10-30 14:13:50 +0000711/** 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.
712 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000713 * @param[in] function Function in which the error occurred.
714 * @param[in] file Name of the file where the error occurred.
715 * @param[in] line Line on which the error occurred.
716 * @param[in] tensor_info Tensor info to validate.
717 * @param[in] num_channels Number of channels to check
718 * @param[in] dt First data type allowed.
719 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000720 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000721 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000722 */
723template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000724inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
725 const ITensorInfo *tensor_info, size_t num_channels, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000726{
727 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)...));
728 const size_t tensor_nc = tensor_info->num_channels();
729 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(tensor_nc != num_channels, function, file, line, "Number of channels %d. Required number of channels %d", tensor_nc, num_channels);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000730 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000731}
732/** 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 +0100733 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000734 * @param[in] function Function in which the error occurred.
735 * @param[in] file Name of the file where the error occurred.
736 * @param[in] line Line on which the error occurred.
737 * @param[in] tensor Tensor to validate.
738 * @param[in] num_channels Number of channels to check
739 * @param[in] dt First data type allowed.
740 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000741 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000742 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100743 */
744template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000745inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
746 const ITensor *tensor, size_t num_channels, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100747{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000748 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
749 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 +0000750 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100751}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000752#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000753 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 +0000754#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
755 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 +0100756
Georgios Pinitas3faea252017-10-30 14:13:50 +0000757/** Return an error if the tensor is not 2D.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100758 *
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] tensor Tensor to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000763 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000764 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100765 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000766arm_compute::Status error_on_tensor_not_2d(const char *function, const char *file, const int line,
767 const ITensor *tensor);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000768#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000769 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000770#define ARM_COMPUTE_RETURN_ERROR_ON_TENSOR_NOT_2D(t) \
771 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100772
Georgios Pinitas3faea252017-10-30 14:13:50 +0000773/** Return an error if the channel is not in channels.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100774 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000775 * @param[in] function Function in which the error occurred.
776 * @param[in] file Name of the file where the error occurred.
777 * @param[in] line Line on which the error occurred.
778 * @param[in] cn Input channel
779 * @param[in] channel First channel allowed.
780 * @param[in] channels (Optional) Further allowed channels.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000781 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000782 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100783 */
784template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000785inline arm_compute::Status error_on_channel_not_in(const char *function, const char *file, const int line,
786 T cn, T &&channel, Ts &&... channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100787{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000788 ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100789
790 const std::array<T, sizeof...(Ts)> channels_array{ { std::forward<Ts>(channels)... } };
Georgios Pinitas3faea252017-10-30 14:13:50 +0000791 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 +0100792 {
793 return f == cn;
794 }),
795 function, file, line);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000796 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100797}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000798#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000799 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 +0000800#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
801 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 +0100802
Georgios Pinitas3faea252017-10-30 14:13:50 +0000803/** Return an error if the channel is not in format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100804 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000805 * @param[in] function Function in which the error occurred.
806 * @param[in] file Name of the file where the error occurred.
807 * @param[in] line Line on which the error occurred.
808 * @param[in] fmt Input channel
809 * @param[in] cn First channel allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000810 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000811 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100812 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000813arm_compute::Status error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
814 Format fmt, Channel cn);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000815#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000816 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 +0000817#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
818 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 +0100819
Georgios Pinitas3faea252017-10-30 14:13:50 +0000820/** Return an error if the @ref IMultiHOG container is invalid
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100821 *
822 * An @ref IMultiHOG container is invalid if:
823 *
824 * -# it is a nullptr
825 * -# it doesn't contain models
826 * -# it doesn't have the HOG data objects with the same phase_type, normalization_type and l2_hyst_threshold (if normalization_type == L2HYS_NORM)
827 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000828 * @param[in] function Function in which the error occurred.
829 * @param[in] file Name of the file where the error occurred.
830 * @param[in] line Line on which the error occurred.
831 * @param[in] multi_hog IMultiHOG container to validate
Georgios Pinitas3faea252017-10-30 14:13:50 +0000832 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000833 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100834 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000835arm_compute::Status error_on_invalid_multi_hog(const char *function, const char *file, const int line,
836 const IMultiHOG *multi_hog);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000837#define ARM_COMPUTE_ERROR_ON_INVALID_MULTI_HOG(m) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000838 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000839#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_MULTI_HOG(m) \
840 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100841
Georgios Pinitas3faea252017-10-30 14:13:50 +0000842/** Return an error if the kernel is not configured.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100843 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000844 * @param[in] function Function in which the error occurred.
845 * @param[in] file Name of the file where the error occurred.
846 * @param[in] line Line on which the error occurred.
847 * @param[in] kernel Kernel to validate.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100848 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000849arm_compute::Status error_on_unconfigured_kernel(const char *function, const char *file, const int line,
850 const IKernel *kernel);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000851#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000852 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000853#define ARM_COMPUTE_RETURN_ERROR_ON_UNCONFIGURED_KERNEL(k) \
854 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100855
Georgios Pinitas3faea252017-10-30 14:13:50 +0000856/** Return an error if if the coordinates and shape of the subtensor are within the parent tensor.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100857 *
858 * @param[in] function Function in which the error occurred.
859 * @param[in] file Name of the file where the error occurred.
860 * @param[in] line Line on which the error occurred.
861 * @param[in] parent_shape Parent tensor shape
862 * @param[in] coords Coordinates inside the parent tensor where the first element of the subtensor is
863 * @param[in] shape Shape of the subtensor
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 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000867arm_compute::Status error_on_invalid_subtensor(const char *function, const char *file, const int line,
868 const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000869#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000870 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000871#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
872 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100873
Georgios Pinitas3faea252017-10-30 14:13:50 +0000874/** 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 +0100875 *
876 * @param[in] function Function in which the error occurred.
877 * @param[in] file Name of the file where the error occurred.
878 * @param[in] line Line on which the error occurred.
879 * @param[in] parent_valid_region Parent valid region.
880 * @param[in] valid_region Valid region of subtensor.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000881 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000882 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100883 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000884arm_compute::Status error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
885 const ValidRegion &parent_valid_region, const ValidRegion &valid_region);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000886#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000887 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 +0000888#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
889 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 +0100890
Georgios Pinitas3faea252017-10-30 14:13:50 +0000891/** Return an error if the input fixed-point positions are different.
892 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000893 * @param[in] function Function in which the error occurred.
894 * @param[in] file Name of the file where the error occurred.
895 * @param[in] line Line on which the error occurred.
896 * @param[in] tensor_info_1 The first tensor info to be compared.
897 * @param[in] tensor_info_2 The second tensor info to be compared.
898 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000899 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000900 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000901 */
902template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000903inline arm_compute::Status error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
904 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000905{
906 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_info_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
907 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_info_array.begin(), tensor_info_array.end(), [&](const ITensorInfo * tensor_info)
908 {
909 return tensor_info->fixed_point_position() != tensor_info_1->fixed_point_position();
910 }),
911 function, file, line, "Tensors have different fixed-point positions");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000912 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000913}
914/** Return an error if the input fixed-point positions are different.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100915 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000916 * @param[in] function Function in which the error occurred.
917 * @param[in] file Name of the file where the error occurred.
918 * @param[in] line Line on which the error occurred.
919 * @param[in] tensor_1 The first tensor to be compared.
920 * @param[in] tensor_2 The second tensor to be compared.
921 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000922 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000923 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100924 */
925template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000926inline arm_compute::Status error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
927 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100928{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000929 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point_position(function, file, line, tensor_1->info(), tensor_2->info(),
930 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000931 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100932}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000933#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000934 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_fixed_point_position(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000935#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
936 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point_position(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100937
Georgios Pinitas3faea252017-10-30 14:13:50 +0000938/** Return an error if the fixed-point value is not representable in the specified Q format.
939 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000940 * @param[in] function Function in which the error occurred.
941 * @param[in] file Name of the file where the error occurred.
942 * @param[in] line Line on which the error occurred.
943 * @param[in] value The floating point value to be checked.
944 * @param[in] tensor_info Input tensor info that has information on data type and fixed-point position.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000945 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000946 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000947 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000948inline arm_compute::Status error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
949 float value, const ITensorInfo *tensor_info)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000950{
951 const int fixed_point_position = tensor_info->fixed_point_position();
952 const DataType dt = tensor_info->data_type();
953 const unsigned int q_max_range = 0xFFFFFFFFu >> (((sizeof(unsigned int) - element_size_from_data_type(dt)) * 8) + 1);
954 const float max_range = q_max_range / (static_cast<float>(1 << fixed_point_position));
955
956 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(value > max_range, function, file, line,
957 "Value %f is not representable in %s with fixed-point position %d", value, string_from_data_type(dt).c_str(), fixed_point_position);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000958 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000959}
960/** Return an error an error if the fixed-point value is not representable in the specified Q format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100961 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000962 * @param[in] function Function in which the error occurred.
963 * @param[in] file Name of the file where the error occurred.
964 * @param[in] line Line on which the error occurred.
965 * @param[in] value The floating point value to be checked.
966 * @param[in] tensor Input tensor that has information on data type and fixed-point position.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000967 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000968 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100969 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000970inline arm_compute::Status error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
971 float value, const ITensor *tensor)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100972{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000973 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
974 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_value_not_representable_in_fixed_point(function, file, line, value, tensor->info()));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000975 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100976}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000977#define ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000978 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_value_not_representable_in_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000979#define ARM_COMPUTE_RETURN_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
980 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_value_not_representable_in_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100981}
982#endif /* __ARM_COMPUTE_VALIDATE_H__*/