blob: b04d293c4c7b94a18b8a8f38dd7510aa4ec8db4a [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
Georgios Pinitas3faea252017-10-30 14:13:50 +0000396/** Return an error if the passed two tensor infos have different data types
397 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000398 * @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.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000403 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000404 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000405 */
406template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000407inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
408 const ITensorInfo *tensor_info, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000409{
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 DataType &&tensor_data_type = tensor_info->data_type();
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_type() != tensor_data_type;
418 }),
419 function, file, line, "Tensors have different data types");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000420 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000421}
422/** Return an error if the passed two tensors have different data types
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100423 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000424 * @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.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000429 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000430 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100431 */
432template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000433inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
434 const ITensor *tensor, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100435{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000436 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_types(function, file, line, tensor->info(),
439 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000440 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100441}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000442#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000443 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000444#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
445 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100446
Georgios Pinitas3faea252017-10-30 14:13:50 +0000447/** Return an error if the passed tensor infos have different fixed point data types or different fixed point positions
448 *
449 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
450 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000451 * @param[in] function Function in which the error occurred.
452 * @param[in] file Name of the file where the error occurred.
453 * @param[in] line Line on which the error occurred.
454 * @param[in] tensor_info_1 The first tensor info to be compared.
455 * @param[in] tensor_info_2 The second tensor info to be compared.
456 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000457 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000458 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000459 */
460template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000461inline arm_compute::Status error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
462 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000463{
464 DataType &&first_data_type = tensor_info_1->data_type();
465 const int first_fixed_point_position = tensor_info_1->fixed_point_position();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100466
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000467 if(!is_data_type_fixed_point(first_data_type))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000468 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000469 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000470 }
471
472 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
473 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
474 {
475 return tensor_info->data_type() != first_data_type;
476 }),
477 function, file, line, "Tensors have different fixed point data types");
478 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
479 {
480 return tensor_info->fixed_point_position() != first_fixed_point_position;
481 }),
482 function, file, line, "Tensors have different fixed point positions");
483
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000484 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000485}
486/** 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 +0100487 *
488 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
489 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000490 * @param[in] function Function in which the error occurred.
491 * @param[in] file Name of the file where the error occurred.
492 * @param[in] line Line on which the error occurred.
493 * @param[in] tensor_1 The first tensor to be compared.
494 * @param[in] tensor_2 The second tensor to be compared.
495 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000496 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000497 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100498 */
499template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000500inline arm_compute::Status error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
501 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100502{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000503 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(function, file, line, tensor_1->info(), tensor_2->info(),
504 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000505 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100506}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000507#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000508 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000509#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
510 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100511
Daniil Efremoveed841c2017-11-09 19:05:25 +0700512/** Return an error if the passed tensor infos have different asymmetric quantized data types or different quantization info
513 *
514 * @note: If the first tensor info doesn't have asymmetric quantized data type, the function returns without throwing an error
515 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000516 * @param[in] function Function in which the error occurred.
517 * @param[in] file Name of the file where the error occurred.
518 * @param[in] line Line on which the error occurred.
519 * @param[in] tensor_info_1 The first tensor info to be compared.
520 * @param[in] tensor_info_2 The second tensor info to be compared.
521 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700522 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000523 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700524 */
525template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000526inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
527 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700528{
529 DataType &&first_data_type = tensor_info_1->data_type();
530 const QuantizationInfo first_quantization_info = tensor_info_1->quantization_info();
531
532 if(!is_data_type_quantized_asymmetric(first_data_type))
533 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000534 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700535 }
536
537 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
538 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
539 {
540 return tensor_info->data_type() != first_data_type;
541 }),
542 function, file, line, "Tensors have different asymmetric quantized data types");
543 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
544 {
545 return tensor_info->quantization_info() != first_quantization_info;
546 }),
547 function, file, line, "Tensors have different quantization information");
548
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000549 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700550}
551/** Return an error if the passed tensor have different asymmetric quantized data types or different quantization info
552 *
553 * @note: If the first tensor doesn't have asymmetric quantized data type, the function returns without throwing an error
554 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000555 * @param[in] function Function in which the error occurred.
556 * @param[in] file Name of the file where the error occurred.
557 * @param[in] line Line on which the error occurred.
558 * @param[in] tensor_1 The first tensor to be compared.
559 * @param[in] tensor_2 The second tensor to be compared.
560 * @param[in] tensors (Optional) Further allowed tensors.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700561 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000562 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700563 */
564template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000565inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
566 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700567{
568 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(function, file, line, tensor_1->info(), tensor_2->info(),
569 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000570 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700571}
572#define ARM_COMPUTE_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
573 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
574#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
575 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
576
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100577/** Throw an error if the format of the passed tensor/multi-image does not match any of the formats provided.
578 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000579 * @param[in] function Function in which the error occurred.
580 * @param[in] file Name of the file where the error occurred.
581 * @param[in] line Line on which the error occurred.
582 * @param[in] object Tensor/multi-image to validate.
583 * @param[in] format First format allowed.
584 * @param[in] formats (Optional) Further allowed formats.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100585 */
586template <typename T, typename F, typename... Fs>
587void error_on_format_not_in(const char *function, const char *file, const int line,
588 const T *object, F &&format, Fs &&... formats)
589{
590 ARM_COMPUTE_ERROR_ON_LOC(object == nullptr, function, file, line);
591
592 Format &&object_format = object->info()->format();
593 ARM_COMPUTE_UNUSED(object_format);
594
595 ARM_COMPUTE_ERROR_ON_LOC(object_format == Format::UNKNOWN, function, file, line);
596
597 const std::array<F, sizeof...(Fs)> formats_array{ { std::forward<Fs>(formats)... } };
598 ARM_COMPUTE_UNUSED(formats_array);
599
600 ARM_COMPUTE_ERROR_ON_LOC_MSG(object_format != format && std::none_of(formats_array.begin(), formats_array.end(), [&](const F & f)
601 {
602 return f == object_format;
603 }),
604 function, file, line, "Format %s not supported by this kernel", string_from_format(object_format).c_str());
605}
606#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t, ...) ::arm_compute::error_on_format_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
607
Georgios Pinitas3faea252017-10-30 14:13:50 +0000608/** Return an error if the data type of the passed tensor info does not match any of the data types provided.
609 *
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_info Tensor info to validate.
614 * @param[in] dt First data type allowed.
615 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000616 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000617 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000618 */
619template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000620inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
621 const ITensorInfo *tensor_info, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000622{
623 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
624
625 const DataType &tensor_dt = tensor_info->data_type(); //NOLINT
626 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
627
628 const std::array<T, sizeof...(Ts)> dts_array{ { std::forward<Ts>(dts)... } };
629 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T & d)
630 {
631 return d == tensor_dt;
632 }),
633 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 +0000634 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000635}
636/** 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 +0100637 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000638 * @param[in] function Function in which the error occurred.
639 * @param[in] file Name of the file where the error occurred.
640 * @param[in] line Line on which the error occurred.
641 * @param[in] tensor Tensor to validate.
642 * @param[in] dt First data type allowed.
643 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000644 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000645 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100646 */
647template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000648inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
649 const ITensor *tensor, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100650{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000651 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
652 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 +0000653 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100654}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000655#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000656 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 +0000657#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
658 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 +0100659
Georgios Pinitas3faea252017-10-30 14:13:50 +0000660/** 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.
661 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000662 * @param[in] function Function in which the error occurred.
663 * @param[in] file Name of the file where the error occurred.
664 * @param[in] line Line on which the error occurred.
665 * @param[in] tensor_info Tensor info to validate.
666 * @param[in] num_channels Number of channels to check
667 * @param[in] dt First data type allowed.
668 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000669 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000670 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000671 */
672template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000673inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
674 const ITensorInfo *tensor_info, size_t num_channels, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000675{
676 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)...));
677 const size_t tensor_nc = tensor_info->num_channels();
678 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 +0000679 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000680}
681/** 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 +0100682 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000683 * @param[in] function Function in which the error occurred.
684 * @param[in] file Name of the file where the error occurred.
685 * @param[in] line Line on which the error occurred.
686 * @param[in] tensor Tensor to validate.
687 * @param[in] num_channels Number of channels to check
688 * @param[in] dt First data type allowed.
689 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000690 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000691 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100692 */
693template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000694inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
695 const ITensor *tensor, size_t num_channels, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100696{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000697 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
698 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 +0000699 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100700}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000701#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000702 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 +0000703#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
704 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 +0100705
Georgios Pinitas3faea252017-10-30 14:13:50 +0000706/** Return an error if the tensor is not 2D.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100707 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000708 * @param[in] function Function in which the error occurred.
709 * @param[in] file Name of the file where the error occurred.
710 * @param[in] line Line on which the error occurred.
711 * @param[in] tensor Tensor to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000712 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000713 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100714 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000715arm_compute::Status error_on_tensor_not_2d(const char *function, const char *file, const int line,
716 const ITensor *tensor);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000717#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000718 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000719#define ARM_COMPUTE_RETURN_ERROR_ON_TENSOR_NOT_2D(t) \
720 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100721
Georgios Pinitas3faea252017-10-30 14:13:50 +0000722/** Return an error if the channel is not in channels.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100723 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000724 * @param[in] function Function in which the error occurred.
725 * @param[in] file Name of the file where the error occurred.
726 * @param[in] line Line on which the error occurred.
727 * @param[in] cn Input channel
728 * @param[in] channel First channel allowed.
729 * @param[in] channels (Optional) Further allowed channels.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000730 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000731 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100732 */
733template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000734inline arm_compute::Status error_on_channel_not_in(const char *function, const char *file, const int line,
735 T cn, T &&channel, Ts &&... channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100736{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000737 ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100738
739 const std::array<T, sizeof...(Ts)> channels_array{ { std::forward<Ts>(channels)... } };
Georgios Pinitas3faea252017-10-30 14:13:50 +0000740 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 +0100741 {
742 return f == cn;
743 }),
744 function, file, line);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000745 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100746}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000747#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000748 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 +0000749#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
750 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 +0100751
Georgios Pinitas3faea252017-10-30 14:13:50 +0000752/** Return an error if the channel is not in format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100753 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000754 * @param[in] function Function in which the error occurred.
755 * @param[in] file Name of the file where the error occurred.
756 * @param[in] line Line on which the error occurred.
757 * @param[in] fmt Input channel
758 * @param[in] cn First channel allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000759 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000760 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100761 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000762arm_compute::Status error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
763 Format fmt, Channel cn);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000764#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000765 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 +0000766#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
767 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 +0100768
Georgios Pinitas3faea252017-10-30 14:13:50 +0000769/** Return an error if the @ref IMultiHOG container is invalid
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100770 *
771 * An @ref IMultiHOG container is invalid if:
772 *
773 * -# it is a nullptr
774 * -# it doesn't contain models
775 * -# it doesn't have the HOG data objects with the same phase_type, normalization_type and l2_hyst_threshold (if normalization_type == L2HYS_NORM)
776 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000777 * @param[in] function Function in which the error occurred.
778 * @param[in] file Name of the file where the error occurred.
779 * @param[in] line Line on which the error occurred.
780 * @param[in] multi_hog IMultiHOG container to validate
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 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000784arm_compute::Status error_on_invalid_multi_hog(const char *function, const char *file, const int line,
785 const IMultiHOG *multi_hog);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000786#define ARM_COMPUTE_ERROR_ON_INVALID_MULTI_HOG(m) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000787 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000788#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_MULTI_HOG(m) \
789 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100790
Georgios Pinitas3faea252017-10-30 14:13:50 +0000791/** Return an error if the kernel is not configured.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100792 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000793 * @param[in] function Function in which the error occurred.
794 * @param[in] file Name of the file where the error occurred.
795 * @param[in] line Line on which the error occurred.
796 * @param[in] kernel Kernel to validate.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100797 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000798arm_compute::Status error_on_unconfigured_kernel(const char *function, const char *file, const int line,
799 const IKernel *kernel);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000800#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000801 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000802#define ARM_COMPUTE_RETURN_ERROR_ON_UNCONFIGURED_KERNEL(k) \
803 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100804
Georgios Pinitas3faea252017-10-30 14:13:50 +0000805/** Return an error if if the coordinates and shape of the subtensor are within the parent tensor.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100806 *
807 * @param[in] function Function in which the error occurred.
808 * @param[in] file Name of the file where the error occurred.
809 * @param[in] line Line on which the error occurred.
810 * @param[in] parent_shape Parent tensor shape
811 * @param[in] coords Coordinates inside the parent tensor where the first element of the subtensor is
812 * @param[in] shape Shape of the subtensor
Georgios Pinitas3faea252017-10-30 14:13:50 +0000813 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000814 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100815 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000816arm_compute::Status error_on_invalid_subtensor(const char *function, const char *file, const int line,
817 const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000818#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000819 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000820#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
821 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100822
Georgios Pinitas3faea252017-10-30 14:13:50 +0000823/** 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 +0100824 *
825 * @param[in] function Function in which the error occurred.
826 * @param[in] file Name of the file where the error occurred.
827 * @param[in] line Line on which the error occurred.
828 * @param[in] parent_valid_region Parent valid region.
829 * @param[in] valid_region Valid region of subtensor.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000830 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000831 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100832 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000833arm_compute::Status error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
834 const ValidRegion &parent_valid_region, const ValidRegion &valid_region);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000835#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000836 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 +0000837#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
838 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 +0100839
Georgios Pinitas3faea252017-10-30 14:13:50 +0000840/** Return an error if the input fixed-point positions are different.
841 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000842 * @param[in] function Function in which the error occurred.
843 * @param[in] file Name of the file where the error occurred.
844 * @param[in] line Line on which the error occurred.
845 * @param[in] tensor_info_1 The first tensor info to be compared.
846 * @param[in] tensor_info_2 The second tensor info to be compared.
847 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000848 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000849 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000850 */
851template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000852inline arm_compute::Status error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
853 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000854{
855 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_info_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
856 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_info_array.begin(), tensor_info_array.end(), [&](const ITensorInfo * tensor_info)
857 {
858 return tensor_info->fixed_point_position() != tensor_info_1->fixed_point_position();
859 }),
860 function, file, line, "Tensors have different fixed-point positions");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000861 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000862}
863/** Return an error if the input fixed-point positions are different.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100864 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000865 * @param[in] function Function in which the error occurred.
866 * @param[in] file Name of the file where the error occurred.
867 * @param[in] line Line on which the error occurred.
868 * @param[in] tensor_1 The first tensor to be compared.
869 * @param[in] tensor_2 The second tensor to be compared.
870 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000871 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000872 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100873 */
874template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000875inline arm_compute::Status error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
876 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100877{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000878 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point_position(function, file, line, tensor_1->info(), tensor_2->info(),
879 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000880 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100881}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000882#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000883 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 +0000884#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
885 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 +0100886
Georgios Pinitas3faea252017-10-30 14:13:50 +0000887/** Return an error if the fixed-point value is not representable in the specified Q format.
888 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000889 * @param[in] function Function in which the error occurred.
890 * @param[in] file Name of the file where the error occurred.
891 * @param[in] line Line on which the error occurred.
892 * @param[in] value The floating point value to be checked.
893 * @param[in] tensor_info Input tensor info that has information on data type and fixed-point position.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000894 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000895 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000896 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000897inline arm_compute::Status error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
898 float value, const ITensorInfo *tensor_info)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000899{
900 const int fixed_point_position = tensor_info->fixed_point_position();
901 const DataType dt = tensor_info->data_type();
902 const unsigned int q_max_range = 0xFFFFFFFFu >> (((sizeof(unsigned int) - element_size_from_data_type(dt)) * 8) + 1);
903 const float max_range = q_max_range / (static_cast<float>(1 << fixed_point_position));
904
905 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(value > max_range, function, file, line,
906 "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 +0000907 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000908}
909/** 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 +0100910 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000911 * @param[in] function Function in which the error occurred.
912 * @param[in] file Name of the file where the error occurred.
913 * @param[in] line Line on which the error occurred.
914 * @param[in] value The floating point value to be checked.
915 * @param[in] tensor Input tensor that has information on data type and fixed-point position.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000916 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000917 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100918 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000919inline arm_compute::Status error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
920 float value, const ITensor *tensor)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100921{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000922 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
923 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 +0000924 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100925}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000926#define ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000927 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 +0000928#define ARM_COMPUTE_RETURN_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
929 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 +0100930}
931#endif /* __ARM_COMPUTE_VALIDATE_H__*/