blob: 4ef0e11433f50d159bb3880085f67533e375b160 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2016, 2017 ARM Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#ifndef __ARM_COMPUTE_VALIDATE_H__
25#define __ARM_COMPUTE_VALIDATE_H__
26
27#include "arm_compute/core/Error.h"
28#include "arm_compute/core/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
Georgios Pinitas3faea252017-10-30 14:13:50 +0000274/** Return an error if the passed two tensor infos have different shapes from the given dimension
275 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000276 * @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] tensor_info_1 The first tensor info to be compared.
280 * @param[in] tensor_info_2 The second tensor info to be compared.
281 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000282 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000283 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000284 */
285template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000286inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
287 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000288{
289 return error_on_mismatching_shapes(function, file, line, 0U, tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)...);
290}
291/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100292 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000293 * @param[in] function Function in which the error occurred.
294 * @param[in] file Name of the file where the error occurred.
295 * @param[in] line Line on which the error occurred.
296 * @param[in] tensor_1 The first tensor to be compared.
297 * @param[in] tensor_2 The second tensor to be compared.
298 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000299 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000300 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100301 */
302template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000303inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
304 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100305{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000306 return error_on_mismatching_shapes(function, file, line, 0U, tensor_1, tensor_2, std::forward<Ts>(tensors)...);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100307}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000308/** Return an error if the passed two tensors have different shapes from the given dimension
309 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000310 * @param[in] function Function in which the error occurred.
311 * @param[in] file Name of the file where the error occurred.
312 * @param[in] line Line on which the error occurred.
313 * @param[in] upper_dim The dimension from which to check.
314 * @param[in] tensor_info_1 The first tensor info to be compared.
315 * @param[in] tensor_info_2 The second tensor info to be compared.
316 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000317 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000318 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000319 */
320template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000321inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
322 unsigned int upper_dim, const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000323{
324 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_1 == nullptr, function, file, line);
325 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_2 == nullptr, function, file, line);
326 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 +0100327
Georgios Pinitas3faea252017-10-30 14:13:50 +0000328 const std::array < const ITensorInfo *, 2 + sizeof...(Ts) > tensors_info_array{ { tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)... } };
329 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(std::next(tensors_info_array.cbegin()), tensors_info_array.cend(), [&](const ITensorInfo * tensor_info)
330 {
331 return detail::have_different_dimensions((*tensors_info_array.cbegin())->tensor_shape(), tensor_info->tensor_shape(), upper_dim);
332 }),
333 function, file, line, "Tensors have different shapes");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000334 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000335}
336/** Return an error if the passed two tensors have different shapes from the given dimension
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100337 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000338 * @param[in] function Function in which the error occurred.
339 * @param[in] file Name of the file where the error occurred.
340 * @param[in] line Line on which the error occurred.
341 * @param[in] upper_dim The dimension from which to check.
342 * @param[in] tensor_1 The first tensor to be compared.
343 * @param[in] tensor_2 The second tensor to be compared.
344 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000345 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000346 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100347 */
348template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000349inline arm_compute::Status error_on_mismatching_shapes(const char *function, const char *file, const int line,
350 unsigned int upper_dim, const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100351{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000352 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_1 == nullptr, function, file, line);
353 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_2 == nullptr, function, file, line);
354 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
355 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(function, file, line, upper_dim, tensor_1->info(), tensor_2->info(),
356 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000357 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100358}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000359#define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000360 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000361#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(...) \
362 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100363
Georgios Pinitas3faea252017-10-30 14:13:50 +0000364/** Return an error if the passed two tensor infos have different data types
365 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000366 * @param[in] function Function in which the error occurred.
367 * @param[in] file Name of the file where the error occurred.
368 * @param[in] line Line on which the error occurred.
369 * @param[in] tensor_info The first tensor info to be compared.
370 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000371 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000372 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000373 */
374template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000375inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
376 const ITensorInfo *tensor_info, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000377{
378 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
379 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
380
381 DataType &&tensor_data_type = tensor_info->data_type();
382 const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { std::forward<Ts>(tensor_infos)... } };
383 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
384 {
385 return tensor_info_obj->data_type() != tensor_data_type;
386 }),
387 function, file, line, "Tensors have different data types");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000388 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000389}
390/** Return an error if the passed two tensors have different data types
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100391 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000392 * @param[in] function Function in which the error occurred.
393 * @param[in] file Name of the file where the error occurred.
394 * @param[in] line Line on which the error occurred.
395 * @param[in] tensor The first tensor to be compared.
396 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000397 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000398 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100399 */
400template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000401inline arm_compute::Status error_on_mismatching_data_types(const char *function, const char *file, const int line,
402 const ITensor *tensor, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100403{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000404 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
405 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
406 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(function, file, line, tensor->info(),
407 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000408 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100409}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000410#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000411 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000412#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
413 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100414
Georgios Pinitas3faea252017-10-30 14:13:50 +0000415/** Return an error if the passed tensor infos have different fixed point data types or different fixed point positions
416 *
417 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
418 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000419 * @param[in] function Function in which the error occurred.
420 * @param[in] file Name of the file where the error occurred.
421 * @param[in] line Line on which the error occurred.
422 * @param[in] tensor_info_1 The first tensor info to be compared.
423 * @param[in] tensor_info_2 The second tensor info to be compared.
424 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000425 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000426 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000427 */
428template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000429inline arm_compute::Status error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
430 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000431{
432 DataType &&first_data_type = tensor_info_1->data_type();
433 const int first_fixed_point_position = tensor_info_1->fixed_point_position();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100434
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000435 if(!is_data_type_fixed_point(first_data_type))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000436 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000437 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000438 }
439
440 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
441 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
442 {
443 return tensor_info->data_type() != first_data_type;
444 }),
445 function, file, line, "Tensors have different fixed point data types");
446 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
447 {
448 return tensor_info->fixed_point_position() != first_fixed_point_position;
449 }),
450 function, file, line, "Tensors have different fixed point positions");
451
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000452 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000453}
454/** 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 +0100455 *
456 * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
457 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000458 * @param[in] function Function in which the error occurred.
459 * @param[in] file Name of the file where the error occurred.
460 * @param[in] line Line on which the error occurred.
461 * @param[in] tensor_1 The first tensor to be compared.
462 * @param[in] tensor_2 The second tensor to be compared.
463 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000464 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000465 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100466 */
467template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000468inline arm_compute::Status error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
469 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100470{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000471 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(function, file, line, tensor_1->info(), tensor_2->info(),
472 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000473 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100474}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000475#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000476 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000477#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
478 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100479
Daniil Efremoveed841c2017-11-09 19:05:25 +0700480/** Return an error if the passed tensor infos have different asymmetric quantized data types or different quantization info
481 *
482 * @note: If the first tensor info doesn't have asymmetric quantized data type, the function returns without throwing an error
483 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000484 * @param[in] function Function in which the error occurred.
485 * @param[in] file Name of the file where the error occurred.
486 * @param[in] line Line on which the error occurred.
487 * @param[in] tensor_info_1 The first tensor info to be compared.
488 * @param[in] tensor_info_2 The second tensor info to be compared.
489 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700490 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000491 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700492 */
493template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000494inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
495 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700496{
497 DataType &&first_data_type = tensor_info_1->data_type();
498 const QuantizationInfo first_quantization_info = tensor_info_1->quantization_info();
499
500 if(!is_data_type_quantized_asymmetric(first_data_type))
501 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000502 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700503 }
504
505 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
506 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
507 {
508 return tensor_info->data_type() != first_data_type;
509 }),
510 function, file, line, "Tensors have different asymmetric quantized data types");
511 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
512 {
513 return tensor_info->quantization_info() != first_quantization_info;
514 }),
515 function, file, line, "Tensors have different quantization information");
516
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000517 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700518}
519/** Return an error if the passed tensor have different asymmetric quantized data types or different quantization info
520 *
521 * @note: If the first tensor doesn't have asymmetric quantized data type, the function returns without throwing an error
522 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000523 * @param[in] function Function in which the error occurred.
524 * @param[in] file Name of the file where the error occurred.
525 * @param[in] line Line on which the error occurred.
526 * @param[in] tensor_1 The first tensor to be compared.
527 * @param[in] tensor_2 The second tensor to be compared.
528 * @param[in] tensors (Optional) Further allowed tensors.
Daniil Efremoveed841c2017-11-09 19:05:25 +0700529 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000530 * @return Status
Daniil Efremoveed841c2017-11-09 19:05:25 +0700531 */
532template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000533inline arm_compute::Status error_on_mismatching_quantization_info(const char *function, const char *file, const int line,
534 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Daniil Efremoveed841c2017-11-09 19:05:25 +0700535{
536 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(function, file, line, tensor_1->info(), tensor_2->info(),
537 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000538 return arm_compute::Status{};
Daniil Efremoveed841c2017-11-09 19:05:25 +0700539}
540#define ARM_COMPUTE_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
541 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
542#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(...) \
543 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_quantization_info(__func__, __FILE__, __LINE__, __VA_ARGS__))
544
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100545/** Throw an error if the format of the passed tensor/multi-image does not match any of the formats provided.
546 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000547 * @param[in] function Function in which the error occurred.
548 * @param[in] file Name of the file where the error occurred.
549 * @param[in] line Line on which the error occurred.
550 * @param[in] object Tensor/multi-image to validate.
551 * @param[in] format First format allowed.
552 * @param[in] formats (Optional) Further allowed formats.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100553 */
554template <typename T, typename F, typename... Fs>
555void error_on_format_not_in(const char *function, const char *file, const int line,
556 const T *object, F &&format, Fs &&... formats)
557{
558 ARM_COMPUTE_ERROR_ON_LOC(object == nullptr, function, file, line);
559
560 Format &&object_format = object->info()->format();
561 ARM_COMPUTE_UNUSED(object_format);
562
563 ARM_COMPUTE_ERROR_ON_LOC(object_format == Format::UNKNOWN, function, file, line);
564
565 const std::array<F, sizeof...(Fs)> formats_array{ { std::forward<Fs>(formats)... } };
566 ARM_COMPUTE_UNUSED(formats_array);
567
568 ARM_COMPUTE_ERROR_ON_LOC_MSG(object_format != format && std::none_of(formats_array.begin(), formats_array.end(), [&](const F & f)
569 {
570 return f == object_format;
571 }),
572 function, file, line, "Format %s not supported by this kernel", string_from_format(object_format).c_str());
573}
574#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t, ...) ::arm_compute::error_on_format_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
575
Georgios Pinitas3faea252017-10-30 14:13:50 +0000576/** Return an error if the data type of the passed tensor info does not match any of the data types provided.
577 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000578 * @param[in] function Function in which the error occurred.
579 * @param[in] file Name of the file where the error occurred.
580 * @param[in] line Line on which the error occurred.
581 * @param[in] tensor_info Tensor info to validate.
582 * @param[in] dt First data type allowed.
583 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000584 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000585 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000586 */
587template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000588inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
589 const ITensorInfo *tensor_info, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000590{
591 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
592
593 const DataType &tensor_dt = tensor_info->data_type(); //NOLINT
594 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
595
596 const std::array<T, sizeof...(Ts)> dts_array{ { std::forward<Ts>(dts)... } };
597 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T & d)
598 {
599 return d == tensor_dt;
600 }),
601 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 +0000602 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000603}
604/** 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 +0100605 *
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 Tensor to validate.
610 * @param[in] dt First data type allowed.
611 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000612 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000613 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100614 */
615template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000616inline arm_compute::Status error_on_data_type_not_in(const char *function, const char *file, const int line,
617 const ITensor *tensor, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100618{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000619 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
620 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 +0000621 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100622}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000623#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000624 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 +0000625#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
626 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 +0100627
Georgios Pinitas3faea252017-10-30 14:13:50 +0000628/** 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.
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] tensor_info Tensor info to validate.
634 * @param[in] num_channels Number of channels to check
635 * @param[in] dt First data type allowed.
636 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000637 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000638 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000639 */
640template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000641inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
642 const ITensorInfo *tensor_info, size_t num_channels, T &&dt, Ts &&... dts)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000643{
644 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)...));
645 const size_t tensor_nc = tensor_info->num_channels();
646 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 +0000647 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000648}
649/** 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 +0100650 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000651 * @param[in] function Function in which the error occurred.
652 * @param[in] file Name of the file where the error occurred.
653 * @param[in] line Line on which the error occurred.
654 * @param[in] tensor Tensor to validate.
655 * @param[in] num_channels Number of channels to check
656 * @param[in] dt First data type allowed.
657 * @param[in] dts (Optional) Further allowed data types.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000658 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000659 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100660 */
661template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000662inline arm_compute::Status error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
663 const ITensor *tensor, size_t num_channels, T &&dt, Ts &&... dts)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100664{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000665 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
666 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 +0000667 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100668}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000669#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000670 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 +0000671#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
672 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 +0100673
Georgios Pinitas3faea252017-10-30 14:13:50 +0000674/** Return an error if the tensor is not 2D.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100675 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000676 * @param[in] function Function in which the error occurred.
677 * @param[in] file Name of the file where the error occurred.
678 * @param[in] line Line on which the error occurred.
679 * @param[in] tensor Tensor to validate.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000680 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000681 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100682 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000683arm_compute::Status error_on_tensor_not_2d(const char *function, const char *file, const int line,
684 const ITensor *tensor);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000685#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000686 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000687#define ARM_COMPUTE_RETURN_ERROR_ON_TENSOR_NOT_2D(t) \
688 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100689
Georgios Pinitas3faea252017-10-30 14:13:50 +0000690/** Return an error if the channel is not in channels.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100691 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000692 * @param[in] function Function in which the error occurred.
693 * @param[in] file Name of the file where the error occurred.
694 * @param[in] line Line on which the error occurred.
695 * @param[in] cn Input channel
696 * @param[in] channel First channel allowed.
697 * @param[in] channels (Optional) Further allowed channels.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000698 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000699 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100700 */
701template <typename T, typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000702inline arm_compute::Status error_on_channel_not_in(const char *function, const char *file, const int line,
703 T cn, T &&channel, Ts &&... channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100704{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000705 ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100706
707 const std::array<T, sizeof...(Ts)> channels_array{ { std::forward<Ts>(channels)... } };
Georgios Pinitas3faea252017-10-30 14:13:50 +0000708 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 +0100709 {
710 return f == cn;
711 }),
712 function, file, line);
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000713 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100714}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000715#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000716 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 +0000717#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
718 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 +0100719
Georgios Pinitas3faea252017-10-30 14:13:50 +0000720/** Return an error if the channel is not in format.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100721 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000722 * @param[in] function Function in which the error occurred.
723 * @param[in] file Name of the file where the error occurred.
724 * @param[in] line Line on which the error occurred.
725 * @param[in] fmt Input channel
726 * @param[in] cn First channel allowed.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000727 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000728 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100729 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000730arm_compute::Status error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
731 Format fmt, Channel cn);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000732#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000733 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 +0000734#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
735 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 +0100736
Georgios Pinitas3faea252017-10-30 14:13:50 +0000737/** Return an error if the @ref IMultiHOG container is invalid
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100738 *
739 * An @ref IMultiHOG container is invalid if:
740 *
741 * -# it is a nullptr
742 * -# it doesn't contain models
743 * -# it doesn't have the HOG data objects with the same phase_type, normalization_type and l2_hyst_threshold (if normalization_type == L2HYS_NORM)
744 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000745 * @param[in] function Function in which the error occurred.
746 * @param[in] file Name of the file where the error occurred.
747 * @param[in] line Line on which the error occurred.
748 * @param[in] multi_hog IMultiHOG container to validate
Georgios Pinitas3faea252017-10-30 14:13:50 +0000749 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000750 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100751 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000752arm_compute::Status error_on_invalid_multi_hog(const char *function, const char *file, const int line,
753 const IMultiHOG *multi_hog);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000754#define ARM_COMPUTE_ERROR_ON_INVALID_MULTI_HOG(m) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000755 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000756#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_MULTI_HOG(m) \
757 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100758
Georgios Pinitas3faea252017-10-30 14:13:50 +0000759/** Return an error if the kernel is not configured.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100760 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000761 * @param[in] function Function in which the error occurred.
762 * @param[in] file Name of the file where the error occurred.
763 * @param[in] line Line on which the error occurred.
764 * @param[in] kernel Kernel to validate.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100765 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000766arm_compute::Status error_on_unconfigured_kernel(const char *function, const char *file, const int line,
767 const IKernel *kernel);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000768#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000769 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000770#define ARM_COMPUTE_RETURN_ERROR_ON_UNCONFIGURED_KERNEL(k) \
771 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100772
Georgios Pinitas3faea252017-10-30 14:13:50 +0000773/** Return an error if if the coordinates and shape of the subtensor are within the parent tensor.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100774 *
775 * @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] parent_shape Parent tensor shape
779 * @param[in] coords Coordinates inside the parent tensor where the first element of the subtensor is
780 * @param[in] shape Shape of the subtensor
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_subtensor(const char *function, const char *file, const int line,
785 const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000786#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000787 ARM_COMPUTE_ERROR_THROW_ON(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000788#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
789 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100790
Georgios Pinitas3faea252017-10-30 14:13:50 +0000791/** 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 +0100792 *
793 * @param[in] function Function in which the error occurred.
794 * @param[in] file Name of the file where the error occurred.
795 * @param[in] line Line on which the error occurred.
796 * @param[in] parent_valid_region Parent valid region.
797 * @param[in] valid_region Valid region of subtensor.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000798 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000799 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100800 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000801arm_compute::Status error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
802 const ValidRegion &parent_valid_region, const ValidRegion &valid_region);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000803#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000804 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 +0000805#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
806 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 +0100807
Georgios Pinitas3faea252017-10-30 14:13:50 +0000808/** Return an error if the input fixed-point positions are different.
809 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000810 * @param[in] function Function in which the error occurred.
811 * @param[in] file Name of the file where the error occurred.
812 * @param[in] line Line on which the error occurred.
813 * @param[in] tensor_info_1 The first tensor info to be compared.
814 * @param[in] tensor_info_2 The second tensor info to be compared.
815 * @param[in] tensor_infos (Optional) Further allowed tensor infos.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000816 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000817 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000818 */
819template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000820inline arm_compute::Status error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
821 const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000822{
823 const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_info_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
824 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_info_array.begin(), tensor_info_array.end(), [&](const ITensorInfo * tensor_info)
825 {
826 return tensor_info->fixed_point_position() != tensor_info_1->fixed_point_position();
827 }),
828 function, file, line, "Tensors have different fixed-point positions");
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000829 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000830}
831/** Return an error if the input fixed-point positions are different.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100832 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000833 * @param[in] function Function in which the error occurred.
834 * @param[in] file Name of the file where the error occurred.
835 * @param[in] line Line on which the error occurred.
836 * @param[in] tensor_1 The first tensor to be compared.
837 * @param[in] tensor_2 The second tensor to be compared.
838 * @param[in] tensors (Optional) Further allowed tensors.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000839 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000840 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100841 */
842template <typename... Ts>
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000843inline arm_compute::Status error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
844 const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100845{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000846 ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point_position(function, file, line, tensor_1->info(), tensor_2->info(),
847 detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000848 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100849}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000850#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000851 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 +0000852#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
853 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 +0100854
Georgios Pinitas3faea252017-10-30 14:13:50 +0000855/** Return an error if the fixed-point value is not representable in the specified Q format.
856 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000857 * @param[in] function Function in which the error occurred.
858 * @param[in] file Name of the file where the error occurred.
859 * @param[in] line Line on which the error occurred.
860 * @param[in] value The floating point value to be checked.
861 * @param[in] tensor_info Input tensor info that has information on data type and fixed-point position.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000862 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000863 * @return Status
Georgios Pinitas3faea252017-10-30 14:13:50 +0000864 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000865inline arm_compute::Status error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
866 float value, const ITensorInfo *tensor_info)
Georgios Pinitas3faea252017-10-30 14:13:50 +0000867{
868 const int fixed_point_position = tensor_info->fixed_point_position();
869 const DataType dt = tensor_info->data_type();
870 const unsigned int q_max_range = 0xFFFFFFFFu >> (((sizeof(unsigned int) - element_size_from_data_type(dt)) * 8) + 1);
871 const float max_range = q_max_range / (static_cast<float>(1 << fixed_point_position));
872
873 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(value > max_range, function, file, line,
874 "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 +0000875 return arm_compute::Status{};
Georgios Pinitas3faea252017-10-30 14:13:50 +0000876}
877/** 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 +0100878 *
Anthony Barbierf202e502017-11-23 18:02:04 +0000879 * @param[in] function Function in which the error occurred.
880 * @param[in] file Name of the file where the error occurred.
881 * @param[in] line Line on which the error occurred.
882 * @param[in] value The floating point value to be checked.
883 * @param[in] tensor Input tensor that has information on data type and fixed-point position.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000884 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000885 * @return Status
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100886 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000887inline arm_compute::Status error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
888 float value, const ITensor *tensor)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100889{
Georgios Pinitas3faea252017-10-30 14:13:50 +0000890 ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
891 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 +0000892 return arm_compute::Status{};
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100893}
Georgios Pinitas3faea252017-10-30 14:13:50 +0000894#define ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
Georgios Pinitasf9d3a0a2017-11-03 19:01:44 +0000895 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 +0000896#define ARM_COMPUTE_RETURN_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
897 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 +0100898}
899#endif /* __ARM_COMPUTE_VALIDATE_H__*/