aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgios Pinitas <georgios.pinitas@arm.com>2017-10-30 14:13:50 +0000
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:35:24 +0000
commit3faea25fe0bcb9f72bfe3da185085ed634d1b162 (patch)
treea53a50bf9e889b9d913dc47d5375a382aed57e58
parentb5908c257d554009a00de3aaa95b3721000ed185 (diff)
downloadComputeLibrary-3faea25fe0bcb9f72bfe3da185085ed634d1b162.tar.gz
COMPMID-617: Adds validation to CLPoolingLayer
Change-Id: Ied405a9c0e9746598d03ac6a944ad87e9b6494eb Reviewed-on: http://mpd-gerrit.cambridge.arm.com/93680 Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com> Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
-rw-r--r--SConstruct3
-rw-r--r--arm_compute/core/CL/kernels/CLPoolingLayerKernel.h11
-rw-r--r--arm_compute/core/Error.h252
-rw-r--r--arm_compute/core/Log.h95
-rw-r--r--arm_compute/core/Validate.h659
-rw-r--r--arm_compute/core/utils/logging/LoggerRegistry.h14
-rw-r--r--arm_compute/core/utils/logging/Macros.h51
-rw-r--r--arm_compute/graph/Types.h19
-rw-r--r--arm_compute/runtime/CL/functions/CLPoolingLayer.h10
-rw-r--r--examples/graph_alexnet.cpp2
-rw-r--r--examples/graph_lenet.cpp2
-rw-r--r--examples/graph_squeezenet.cpp2
-rwxr-xr-xscripts/clang_tidy_rules.py9
-rw-r--r--src/core/CL/CLHelpers.cpp5
-rw-r--r--src/core/CL/kernels/CLPoolingLayerKernel.cpp32
-rw-r--r--src/core/Error.cpp14
-rw-r--r--src/core/Utils.cpp1
-rw-r--r--src/core/Validate.cpp194
-rw-r--r--src/runtime/CL/functions/CLPoolingLayer.cpp5
-rw-r--r--tests/validation/CL/PoolingLayer.cpp32
-rw-r--r--utils/TypePrinter.h12
21 files changed, 1003 insertions, 421 deletions
diff --git a/SConstruct b/SConstruct
index c8fad8da0c..904a85fe43 100644
--- a/SConstruct
+++ b/SConstruct
@@ -39,7 +39,7 @@ vars = Variables("scons")
vars.AddVariables(
BoolVariable("debug", "Debug", False),
BoolVariable("asserts", "Enable asserts (this flag is forced to 1 for debug=1)", False),
- BoolVariable("logging", "Logging", False),
+ BoolVariable("logging", "Logging (this flag is forced to 1 for debug=1)", False),
EnumVariable("arch", "Target Architecture", "armv7a", allowed_values=("armv7a", "arm64-v8a", "arm64-v8.2-a", "x86_32", "x86_64")),
EnumVariable("os", "Target OS", "linux", allowed_values=("linux", "android", "bare_metal")),
EnumVariable("build", "Build type", "cross_compile", allowed_values=("native", "cross_compile")),
@@ -204,6 +204,7 @@ if env['opencl']:
if env['debug']:
env['asserts'] = True
+ env['logging'] = True
env.Append(CXXFLAGS = ['-O0','-g','-gdwarf-2'])
env.Append(CPPDEFINES = ['ARM_COMPUTE_DEBUG_ENABLED'])
else:
diff --git a/arm_compute/core/CL/kernels/CLPoolingLayerKernel.h b/arm_compute/core/CL/kernels/CLPoolingLayerKernel.h
index 9251a8ed98..29190e2dd1 100644
--- a/arm_compute/core/CL/kernels/CLPoolingLayerKernel.h
+++ b/arm_compute/core/CL/kernels/CLPoolingLayerKernel.h
@@ -26,6 +26,8 @@
#include "arm_compute/core/CL/ICLKernel.h"
+#include "arm_compute/core/Error.h"
+
namespace arm_compute
{
class ICLTensor;
@@ -56,6 +58,15 @@ public:
* @param[in] pool_info Contains pooling operation information described in @ref PoolingLayerInfo.
*/
void configure(const ICLTensor *input, ICLTensor *output, const PoolingLayerInfo &pool_info);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLPoolingLayerKernel
+ *
+ * @param[in] input Input's tensor info
+ * @param[in] output Output's tensor info
+ * @param[in] pool_info Contains pooling operation information described in @ref PoolingLayerInfo.
+ *
+ * @return an error
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *output, const PoolingLayerInfo &pool_info);
// Inherited methods overridden:
void run(const Window &window, cl::CommandQueue &queue) override;
diff --git a/arm_compute/core/Error.h b/arm_compute/core/Error.h
index c4c452bacf..6e4aa6a4f8 100644
--- a/arm_compute/core/Error.h
+++ b/arm_compute/core/Error.h
@@ -24,55 +24,225 @@
#ifndef __ARM_COMPUTE_ERROR_H__
#define __ARM_COMPUTE_ERROR_H__
-/** Print the given message then throw an std::runtime_error.
+#include <stdexcept>
+#include <string>
+
+namespace arm_compute
+{
+enum class ErrorCode
+{
+ OK, /**< No error */
+ RUNTIME_ERROR /**< Generic runtime error */
+};
+
+/** Error class */
+class Error
+{
+public:
+ /** Default Constructor **/
+ Error()
+ : _code(ErrorCode::OK), _description(" ")
+ {
+ }
+ /** Default Constructor
+ *
+ * @param error_status Error status.
+ * @param error_description Error description if error_status is not valid.
+ */
+ explicit Error(ErrorCode error_status, std::string error_description = " ")
+ : _code(error_status), _description(error_description)
+ {
+ }
+ /** Allow instances of this class to be copy constructed */
+ Error(const Error &) = default;
+ /** Allow instances of this class to be move constructed */
+ Error(Error &&) = default;
+ /** Allow instances of this class to be copy assigned */
+ Error &operator=(const Error &) = default;
+ /** Allow instances of this class to be move assigned */
+ Error &operator=(Error &&) = default;
+ /** Explicit bool conversion operator
+ *
+ * @return True if there is a valid error else false if status is OK.
+ */
+ explicit operator bool() const noexcept
+ {
+ return _code != ErrorCode::OK;
+ }
+ /** Gets error code
+ *
+ * @return Error code.
+ */
+ ErrorCode error_code() const
+ {
+ return _code;
+ }
+ /** Gets error description if any
+ *
+ * @return Error description.
+ */
+ std::string description() const
+ {
+ return _description;
+ }
+ /** Throws a runtime exception in case it contains a valid error status */
+ void throw_if_error()
+ {
+ if(bool(*this))
+ {
+ internal_throw_on_error();
+ }
+ }
+
+private:
+ /** Internal throwing function */
+ [[noreturn]] void internal_throw_on_error()
+ {
+ throw std::runtime_error(_description);
+ }
+
+private:
+ ErrorCode _code;
+ std::string _description;
+};
+
+/** Creates an error containing the error message
*
- * @param[in] ... Message to display before aborting.
+ * @param[in] error_code Error code
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] msg Message to display before aborting.
+ * @param[in] ... Variable number of arguments of the message.
*/
-#define ARM_COMPUTE_ERROR(...) ::arm_compute::error(__func__, __FILE__, __LINE__, __VA_ARGS__) // NOLINT
-
-/** Print the given message then throw an std::runtime_error.
+Error create_error(ErrorCode error_code, const char *function, const char *file, const int line, const char *msg, ...);
+/** Print an error message then throw an std::runtime_error
*
- * @param[in] func Function in which the error occurred.
- * @param[in] file File in which the error occurred.
- * @param[in] line Line in which the error occurred.
- * @param[in] ... Message to display before aborting.
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] msg Message to display before aborting.
+ * @param[in] ... Variable number of arguments of the message.
*/
-#define ARM_COMPUTE_ERROR_LOC(func, file, line, ...) ::arm_compute::error(func, file, line, __VA_ARGS__) // NOLINT
-
+[[noreturn]] void error(const char *function, const char *file, const int line, const char *msg, ...);
+}
/** To avoid unused variables warnings
*
* This is useful if for example a variable is only used
* in debug builds and generates a warning in release builds.
*
- * @param[in] var Variable which is unused
+ * @param[in] var Variable which is unused.
*/
#define ARM_COMPUTE_UNUSED(var) (void)(var)
-#ifdef ARM_COMPUTE_DEBUG_ENABLED
-/** Print the given message
+/** Creates an error with a given message
*
- * @param[in] ... Message to display
+ * @param[in] error_code Error code.
+ * @param[in] ... Message to encapsulate.
*/
-#define ARM_COMPUTE_INFO(...) ::arm_compute::debug(__func__, __FILE__, __LINE__, __VA_ARGS__) // NOLINT
-/** If the condition is true, the given message is printed
+#define ARM_COMPUTE_CREATE_ERROR(error_code, ...) ::arm_compute::create_error(error_code, __func__, __FILE__, __LINE__, __VA_ARGS__) // NOLINT
+
+/** Creates an error on location with a given message
*
- * @param[in] cond Condition to evaluate.
- * @param[in] ... Message to print if cond is false.
+ * @param[in] error_code Error code.
+ * @param[in] func Function in which the error occurred.
+ * @param[in] file File in which the error occurred.
+ * @param[in] line Line in which the error occurred.
+ * @param[in] ... Message to display before aborting.
*/
-#define ARM_COMPUTE_INFO_ON_MSG(cond, ...) \
+#define ARM_COMPUTE_CREATE_ERROR_LOC(error_code, func, file, line, ...) ::arm_compute::create_error(error_code, func, file, line, __VA_ARGS__) // NOLINT
+
+/** Checks if an error value is valid if not returns
+ *
+ * @param[in] error Error value to check
+ */
+#define ARM_COMPUTE_RETURN_ON_ERROR(error) \
do \
{ \
- if(cond) \
+ if(bool(error)) \
{ \
- ARM_COMPUTE_INFO(__VA_ARGS__); \
+ return error; \
} \
- } while(0)
-#else /* ARM_COMPUTE_DEBUG_ENABLED */
-#define ARM_COMPUTE_INFO_ON_MSG(cond, ...)
-#define ARM_COMPUTE_INFO(...)
-#endif /* ARM_COMPUTE_DEBUG_ENABLED */
+ } while(false)
+
+/** Checks if an error value is valid if not throws an exception with the error
+ *
+ * @param[in] error Error value to check.
+ */
+#define ARM_COMPUTE_THROW_ON_ERROR(error) \
+ error.throw_if_error();
+
+/** If the condition is true, an error is returned
+ *
+ * @param[in] cond Condition to evaluate.
+ * @param[in] ... Error description message
+ */
+#define ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, ...) \
+ do \
+ { \
+ if(cond) \
+ { \
+ return ARM_COMPUTE_CREATE_ERROR(arm_compute::ErrorCode::RUNTIME_ERROR, __VA_ARGS__); \
+ } \
+ } while(false)
+
+/** If the condition is true, an error is thrown
+ *
+ * @param[in] cond Condition to evaluate.
+ * @param[in] func Function in which the error occurred.
+ * @param[in] file File in which the error occurred.
+ * @param[in] line Line in which the error occurred.
+ * @param[in] ... Error description message.
+ */
+#define ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(cond, func, file, line, ...) \
+ do \
+ { \
+ if(cond) \
+ { \
+ return ARM_COMPUTE_CREATE_ERROR_LOC(arm_compute::ErrorCode::RUNTIME_ERROR, func, file, line, __VA_ARGS__); \
+ } \
+ } while(false)
+
+/** If the condition is true, an error is returned
+ *
+ * @param[in] cond Condition to evaluate
+ */
+#define ARM_COMPUTE_RETURN_ERROR_ON(cond) \
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, #cond)
+
+/** If the condition is true, an error is returned
+ *
+ * @param[in] cond Condition to evaluate.
+ * @param[in] func Function in which the error occurred.
+ * @param[in] file File in which the error occurred.
+ * @param[in] line Line in which the error occurred.
+ */
+#define ARM_COMPUTE_RETURN_ERROR_ON_LOC(cond, func, file, line) \
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(cond, func, file, line, #cond)
+
+/** Print the given message then throw an std::runtime_error.
+ *
+ * @param[in] ... Message to display before aborting.
+ */
+#define ARM_COMPUTE_ERROR(...) ::arm_compute::error(__func__, __FILE__, __LINE__, __VA_ARGS__) // NOLINT
+
+/** Print the given message then throw an std::runtime_error.
+ *
+ * @param[in] func Function in which the error occurred.
+ * @param[in] file File in which the error occurred.
+ * @param[in] line Line in which the error occurred.
+ * @param[in] ... Message to display before aborting.
+ */
+#define ARM_COMPUTE_ERROR_LOC(func, file, line, ...) ::arm_compute::error(func, file, line, __VA_ARGS__) // NOLINT
#ifdef ARM_COMPUTE_ASSERTS_ENABLED
+/** Checks if an error value is valid if not throws an exception with the error
+ *
+ * @param[in] error Error value to check.
+ */
+#define ARM_COMPUTE_ERROR_THROW(error) \
+ error.throw_if_error();
+
/** If the condition is true, the given message is printed and an exception is thrown
*
* @param[in] cond Condition to evaluate.
@@ -112,6 +282,7 @@
*/
#define ARM_COMPUTE_CONST_ON_ERROR(cond, val, msg) (cond) ? throw std::logic_error(msg) : val;
#else /* ARM_COMPUTE_ASSERTS_ENABLED */
+#define ARM_COMPUTE_ERROR_THROW(error)
#define ARM_COMPUTE_ERROR_ON_MSG(cond, ...)
#define ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, ...)
#define ARM_COMPUTE_CONST_ON_ERROR(cond, val, msg) val
@@ -119,14 +290,14 @@
/** If the condition is true then an error message is printed and an exception thrown
*
- * @param[in] cond Condition to evaluate
+ * @param[in] cond Condition to evaluate.
*/
#define ARM_COMPUTE_ERROR_ON(cond) \
ARM_COMPUTE_ERROR_ON_MSG(cond, #cond)
/** If the condition is true then an error message is printed and an exception thrown
*
- * @param[in] cond Condition to evaluate
+ * @param[in] cond Condition to evaluate.
* @param[in] func Function in which the error occurred.
* @param[in] file File in which the error occurred.
* @param[in] line Line in which the error occurred.
@@ -134,27 +305,4 @@
#define ARM_COMPUTE_ERROR_ON_LOC(cond, func, file, line) \
ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, #cond)
-namespace arm_compute
-{
-/** Print an error message then throw an std::runtime_error
- *
- * @param[in] function Function in which the error occurred.
- * @param[in] file Name of the file where the error occurred.
- * @param[in] line Line on which the error occurred.
- * @param[in] msg Message to display before aborting.
- * @param[in] ... Variable number of arguments of the message.
- */
-[[noreturn]] void error(const char *function, const char *file, const int line, const char *msg, ...);
-
-/** Print a debug message
- *
- * @param[in] function Function in which the error occurred.
- * @param[in] file Name of the file where the error occurred.
- * @param[in] line Line on which the error occurred.
- * @param[in] msg Message to display before aborting.
- * @param[in] ... Variable number of arguments of the message.
- */
-void debug(const char *function, const char *file, const int line, const char *msg, ...);
-}
-
#endif /* __ARM_COMPUTE_ERROR_H__ */
diff --git a/arm_compute/core/Log.h b/arm_compute/core/Log.h
new file mode 100644
index 0000000000..488c8e6190
--- /dev/null
+++ b/arm_compute/core/Log.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_LOG_H__
+#define __ARM_COMPUTE_LOG_H__
+
+#include "arm_compute/core/utils/logging/Macros.h"
+
+/** Create a default core logger
+ *
+ * @note It will eventually create all default loggers in don't exist
+ */
+#define ARM_COMPUTE_CREATE_DEFAULT_CORE_LOGGER() \
+ do \
+ { \
+ if(arm_compute::logging::LoggerRegistry::get().logger("CORE") == nullptr) \
+ { \
+ arm_compute::logging::LoggerRegistry::get().create_reserved_loggers(); \
+ } \
+ } while(false)
+
+/** Log a message to the core system logger
+ *
+ * @param[in] log_level Logging level
+ * @param[in] msg Message to log
+ */
+#define ARM_COMPUTE_LOG_MSG_CORE(log_level, msg) \
+ ARM_COMPUTE_CREATE_DEFAULT_CORE_LOGGER(); \
+ ARM_COMPUTE_LOG_MSG("CORE", log_level, msg)
+
+/** Log a message with format to the core system logger
+ *
+ * @param[in] log_level Logging level
+ * @param[in] fmt String format (printf style)
+ * @param[in] ... Message arguments
+ */
+#define ARM_COMPUTE_LOG_MSG_WITH_FORMAT_CORE(log_level, fmt, ...) \
+ ARM_COMPUTE_CREATE_DEFAULT_CORE_LOGGER(); \
+ ARM_COMPUTE_LOG_MSG_WITH_FORMAT("CORE", log_level, fmt, __VA_ARGS__)
+
+/** Log a stream to the core system logger
+ *
+ * @param[in] log_level Logging level
+ * @param[in] ss Stream to log
+ */
+#define ARM_COMPUTE_LOG_STREAM_CORE(log_level, ss) \
+ ARM_COMPUTE_CREATE_DEFAULT_CORE_LOGGER(); \
+ ARM_COMPUTE_LOG_STREAM("CORE", log_level, ss)
+
+/** Log information level message to the core system logger
+ *
+ * @param[in] msg Stream to log
+ */
+#define ARM_COMPUTE_LOG_INFO_MSG_CORE(msg) \
+ ARM_COMPUTE_CREATE_DEFAULT_CORE_LOGGER(); \
+ ARM_COMPUTE_LOG_MSG_CORE(arm_compute::logging::LogLevel::INFO, msg)
+
+/** Log information level formatted message to the core system logger
+ *
+ * @param[in] fmt String format (printf style)
+ * @param[in] ... Message arguments
+ */
+#define ARM_COMPUTE_LOG_INFO_MSG_WITH_FORMAT_CORE(fmt, ...) \
+ ARM_COMPUTE_CREATE_DEFAULT_CORE_LOGGER(); \
+ ARM_COMPUTE_LOG_MSG_WITH_FORMAT_CORE(arm_compute::logging::LogLevel::INFO, msg)
+
+/** Log information level stream to the core system logger
+ *
+ * @param[in] ss Message to log
+ */
+#define ARM_COMPUTE_LOG_INFO_STREAM_CORE(ss) \
+ ARM_COMPUTE_CREATE_DEFAULT_CORE_LOGGER(); \
+ ARM_COMPUTE_LOG_STREAM_CORE(arm_compute::logging::LogLevel::INFO, ss)
+
+#endif /* __ARM_COMPUTE_LOGGING_MACROS_H__ */
diff --git a/arm_compute/core/Validate.h b/arm_compute/core/Validate.h
index 34da339f03..1e2d262683 100644
--- a/arm_compute/core/Validate.h
+++ b/arm_compute/core/Validate.h
@@ -64,9 +64,9 @@ inline bool have_different_dimensions(const Dimensions<T> &dim1, const Dimension
/** Functor to compare two @ref Dimensions objects and throw an error on mismatch.
*
* @param[in] dim Object to compare against.
- * @param[in] function Function in which the error occured.
- * @param[in] file File in which the error occured.
- * @param[in] line Line in which the error occured.
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file File in which the error occurred.
+ * @param[in] line Line in which the error occurred.
*/
template <typename T>
class compare_dimension
@@ -81,10 +81,11 @@ public:
*
* @param[in] dim To be compared object.
*/
- void operator()(const Dimensions<T> &dim)
+ arm_compute::Error operator()(const Dimensions<T> &dim)
{
- ARM_COMPUTE_ERROR_ON_LOC_MSG(have_different_dimensions(_dim, dim, 0), _function, _file, _line,
- "Objects have different dimensions");
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(have_different_dimensions(_dim, dim, 0), _function, _file, _line,
+ "Objects have different dimensions");
+ return arm_compute::Error{};
}
private:
@@ -93,27 +94,59 @@ private:
const char *const _file;
const int _line;
};
+
+template <typename F>
+inline arm_compute::Error for_each_error(F &&)
+{
+ return arm_compute::Error{};
+}
+
+template <typename F, typename T, typename... Ts>
+inline arm_compute::Error for_each_error(F &&func, T &&arg, Ts &&... args)
+{
+ ARM_COMPUTE_RETURN_ON_ERROR(func(arg));
+ ARM_COMPUTE_RETURN_ON_ERROR(for_each_error(func, args...));
+ return arm_compute::Error{};
+}
+
+template <typename T>
+struct get_tensor_info_t;
+template <>
+struct get_tensor_info_t<ITensorInfo *>
+{
+ ITensorInfo *operator()(const ITensor *tensor)
+ {
+ return tensor->info();
+ }
+};
} // namespace detail
-/** Throw an error if one of the pointers is a nullptr.
+
+/** Create an error if one of the pointers is a nullptr.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
* @param[in] line Line on which the error occurred.
* @param[in] pointers Pointers to check against nullptr.
+ *
+ * @return Error
*/
template <typename... Ts>
-void error_on_nullptr(const char *function, const char *file, const int line, Ts &&... pointers)
+inline arm_compute::Error error_on_nullptr(const char *function, const char *file, const int line, Ts &&... pointers)
{
- auto is_nullptr = [&](const void *ptr)
+ const std::array<const void *, sizeof...(Ts)> pointers_array{ { std::forward<Ts>(pointers)... } };
+ bool has_nullptr = std::any_of(pointers_array.begin(), pointers_array.end(), [&](const void *ptr)
{
- ARM_COMPUTE_ERROR_ON_LOC(ptr == nullptr, function, file, line);
- };
-
- for_each(is_nullptr, std::forward<Ts>(pointers)...);
+ return (ptr == nullptr);
+ });
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(has_nullptr, function, file, line, "Nullptr object!");
+ return arm_compute::Error{};
}
-#define ARM_COMPUTE_ERROR_ON_NULLPTR(...) ::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__)
+#define ARM_COMPUTE_ERROR_ON_NULLPTR(...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(__func__, __FILE__, __LINE__, __VA_ARGS__))
-/** Throw an error if the passed window is invalid.
+/** Return an error if the passed window is invalid.
*
* The subwindow is invalid if:
* - It is not a valid window.
@@ -125,12 +158,17 @@ void error_on_nullptr(const char *function, const char *file, const int line, Ts
* @param[in] line Line on which the error occurred.
* @param[in] full Full size window
* @param[in] win Window to validate.
+ *
+ * @return Error
*/
-void error_on_mismatching_windows(const char *function, const char *file, const int line,
- const Window &full, const Window &win);
-#define ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(f, w) ::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w)
+arm_compute::Error error_on_mismatching_windows(const char *function, const char *file, const int line,
+ const Window &full, const Window &win);
+#define ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
+#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_WINDOWS(f, w) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_windows(__func__, __FILE__, __LINE__, f, w))
-/** Throw an error if the passed subwindow is invalid.
+/** Return an error if the passed subwindow is invalid.
*
* The subwindow is invalid if:
* - It is not a valid window.
@@ -142,12 +180,17 @@ void error_on_mismatching_windows(const char *function, const char *file, const
* @param[in] line Line on which the error occurred.
* @param[in] full Full size window
* @param[in] sub Sub-window to validate.
+ *
+ * @return Error
*/
-void error_on_invalid_subwindow(const char *function, const char *file, const int line,
- const Window &full, const Window &sub);
-#define ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(f, s) ::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s)
+arm_compute::Error error_on_invalid_subwindow(const char *function, const char *file, const int line,
+ const Window &full, const Window &sub);
+#define ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(f, s) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
+#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBWINDOW(f, s) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subwindow(__func__, __FILE__, __LINE__, f, s))
-/** Throw an error if the window can't be collapsed at the given dimension.
+/** Return an error if the window can't be collapsed at the given dimension.
*
* The window cannot be collapsed if the given dimension not equal to the full window's dimension or not start from 0.
*
@@ -157,12 +200,17 @@ void error_on_invalid_subwindow(const char *function, const char *file, const in
* @param[in] full Full size window
* @param[in] window Window to be collapsed.
* @param[in] dim Dimension need to be checked.
+ *
+ * @return Error
*/
-void error_on_window_not_collapsable_at_dimension(const char *function, const char *file, const int line,
- const Window &full, const Window &window, const int dim);
-#define ARM_COMPUTE_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) ::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d)
+arm_compute::Error error_on_window_not_collapsable_at_dimension(const char *function, const char *file, const int line,
+ const Window &full, const Window &window, const int dim);
+#define ARM_COMPUTE_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
+#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_NOT_COLLAPSABLE_AT_DIMENSION(f, w, d) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_not_collapsable_at_dimension(__func__, __FILE__, __LINE__, f, w, d))
-/** Throw an error if the passed coordinates have too many dimensions.
+/** Return an error if the passed coordinates have too many dimensions.
*
* The coordinates have too many dimensions if any of the dimensions greater or equal to max_dim is different from 0.
*
@@ -171,12 +219,17 @@ void error_on_window_not_collapsable_at_dimension(const char *function, const ch
* @param[in] line Line on which the error occurred.
* @param[in] pos Coordinates to validate
* @param[in] max_dim Maximum number of dimensions allowed.
+ *
+ * @return Error
*/
-void error_on_coordinates_dimensions_gte(const char *function, const char *file, const int line,
- const Coordinates &pos, unsigned int max_dim);
-#define ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) ::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md)
+arm_compute::Error error_on_coordinates_dimensions_gte(const char *function, const char *file, const int line,
+ const Coordinates &pos, unsigned int max_dim);
+#define ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
+#define ARM_COMPUTE_RETURN_ERROR_ON_COORDINATES_DIMENSIONS_GTE(p, md) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_coordinates_dimensions_gte(__func__, __FILE__, __LINE__, p, md))
-/** Throw an error if the passed window has too many dimensions.
+/** Return an error if the passed window has too many dimensions.
*
* The window has too many dimensions if any of the dimension greater or equal to max_dim is different from 0.
*
@@ -185,12 +238,17 @@ void error_on_coordinates_dimensions_gte(const char *function, const char *file,
* @param[in] line Line on which the error occurred.
* @param[in] win Window to validate
* @param[in] max_dim Maximum number of dimensions allowed.
+ *
+ * @return Error
*/
-void error_on_window_dimensions_gte(const char *function, const char *file, const int line,
- const Window &win, unsigned int max_dim);
-#define ARM_COMPUTE_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) ::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md)
+arm_compute::Error error_on_window_dimensions_gte(const char *function, const char *file, const int line,
+ const Window &win, unsigned int max_dim);
+#define ARM_COMPUTE_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
+#define ARM_COMPUTE_RETURN_ERROR_ON_WINDOW_DIMENSIONS_GTE(w, md) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_window_dimensions_gte(__func__, __FILE__, __LINE__, w, md))
-/** Throw an error if the passed dimension objects differ.
+/** Return an error if the passed dimension objects differ.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
@@ -198,20 +256,39 @@ void error_on_window_dimensions_gte(const char *function, const char *file, cons
* @param[in] dim1 The first object to be compared.
* @param[in] dim2 The second object to be compared.
* @param[in] dims (Optional) Further allowed objects.
+ *
+ * @return Error
*/
template <typename T, typename... Ts>
-void error_on_mismatching_dimensions(const char *function, const char *file, int line,
- const Dimensions<T> &dim1, const Dimensions<T> &dim2, Ts &&... dims)
+arm_compute::Error error_on_mismatching_dimensions(const char *function, const char *file, int line,
+ const Dimensions<T> &dim1, const Dimensions<T> &dim2, Ts &&... dims)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
-
- for_each(detail::compare_dimension<T>(dim1, function, file, line), dim2, std::forward<Ts>(dims)...);
+ ARM_COMPUTE_RETURN_ON_ERROR(detail::for_each_error(detail::compare_dimension<T>(dim1, function, file, line), dim2, std::forward<Ts>(dims)...));
+ return arm_compute::Error{};
}
-#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(...) ::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__)
+#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_dimensions(__func__, __FILE__, __LINE__, __VA_ARGS__))
-/** Throw an error if the passed two tensors have different shapes from the given dimension
+/** Return an error if the passed two tensor infos have different shapes from the given dimension
+ *
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] tensor_info_1 The first tensor info to be compared.
+ * @param[in] tensor_info_2 The second tensor info to be compared.
+ * @param[in] tensor_infos (Optional) Further allowed tensor infos.
+ *
+ * @return Error
+ */
+template <typename... Ts>
+inline arm_compute::Error error_on_mismatching_shapes(const char *function, const char *file, const int line,
+ const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
+{
+ return error_on_mismatching_shapes(function, file, line, 0U, tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)...);
+}
+/** Return an error if the passed two tensors have different shapes from the given dimension
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
@@ -219,15 +296,44 @@ void error_on_mismatching_dimensions(const char *function, const char *file, int
* @param[in] tensor_1 The first tensor to be compared.
* @param[in] tensor_2 The second tensor to be compared.
* @param[in] tensors (Optional) Further allowed tensors.
+ *
+ * @return Error
*/
template <typename... Ts>
-void error_on_mismatching_shapes(const char *function, const char *file, const int line,
- const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
+inline arm_compute::Error error_on_mismatching_shapes(const char *function, const char *file, const int line,
+ const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
{
- error_on_mismatching_shapes(function, file, line, 0U, tensor_1, tensor_2, std::forward<Ts>(tensors)...);
+ return error_on_mismatching_shapes(function, file, line, 0U, tensor_1, tensor_2, std::forward<Ts>(tensors)...);
}
+/** Return an error if the passed two tensors have different shapes from the given dimension
+ *
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] upper_dim The dimension from which to check.
+ * @param[in] tensor_info_1 The first tensor info to be compared.
+ * @param[in] tensor_info_2 The second tensor info to be compared.
+ * @param[in] tensor_infos (Optional) Further allowed tensor infos.
+ *
+ * @return Error
+ */
+template <typename... Ts>
+inline arm_compute::Error error_on_mismatching_shapes(const char *function, const char *file, const int line,
+ unsigned int upper_dim, const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_1 == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info_2 == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
-/** Throw an error if the passed two tensors have different shapes from the given dimension
+ const std::array < const ITensorInfo *, 2 + sizeof...(Ts) > tensors_info_array{ { tensor_info_1, tensor_info_2, std::forward<Ts>(tensor_infos)... } };
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(std::next(tensors_info_array.cbegin()), tensors_info_array.cend(), [&](const ITensorInfo * tensor_info)
+ {
+ return detail::have_different_dimensions((*tensors_info_array.cbegin())->tensor_shape(), tensor_info->tensor_shape(), upper_dim);
+ }),
+ function, file, line, "Tensors have different shapes");
+ return arm_compute::Error{};
+}
+/** Return an error if the passed two tensors have different shapes from the given dimension
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
@@ -236,112 +342,140 @@ void error_on_mismatching_shapes(const char *function, const char *file, const i
* @param[in] tensor_1 The first tensor to be compared.
* @param[in] tensor_2 The second tensor to be compared.
* @param[in] tensors (Optional) Further allowed tensors.
+ *
+ * @return Error
*/
template <typename... Ts>
-void error_on_mismatching_shapes(const char *function, const char *file, const int line,
- unsigned int upper_dim, const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
+inline arm_compute::Error error_on_mismatching_shapes(const char *function, const char *file, const int line,
+ unsigned int upper_dim, const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
-
- const std::array < const ITensor *, 2 + sizeof...(Ts) > tensors_array{ { tensor_1, tensor_2, std::forward<Ts>(tensors)... } };
- ARM_COMPUTE_UNUSED(tensors_array);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_1 == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_2 == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(function, file, line, upper_dim, tensor_1->info(), tensor_2->info(),
+ detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
+ return arm_compute::Error{};
+}
+#define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__))
- ARM_COMPUTE_ERROR_ON_LOC(tensors_array.cbegin() == nullptr, function, file, line);
+/** Return an error if the passed two tensor infos have different data types
+ *
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] tensor_info The first tensor info to be compared.
+ * @param[in] tensor_infos (Optional) Further allowed tensor infos.
+ *
+ * @return Error
+ */
+template <typename... Ts>
+inline arm_compute::Error error_on_mismatching_data_types(const char *function, const char *file, const int line,
+ const ITensorInfo *tensor_info, Ts... tensor_infos)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensor_infos)...));
- ARM_COMPUTE_ERROR_ON_LOC_MSG(std::any_of(std::next(tensors_array.cbegin()), tensors_array.cend(), [&](const ITensor * tensor)
+ DataType &&tensor_data_type = tensor_info->data_type();
+ const std::array<const ITensorInfo *, sizeof...(Ts)> tensors_infos_array{ { std::forward<Ts>(tensor_infos)... } };
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensors_infos_array.begin(), tensors_infos_array.end(), [&](const ITensorInfo * tensor_info_obj)
{
- ARM_COMPUTE_ERROR_ON_LOC(tensor == nullptr, function, file, line);
- return detail::have_different_dimensions((*tensors_array.cbegin())->info()->tensor_shape(), tensor->info()->tensor_shape(), upper_dim);
+ return tensor_info_obj->data_type() != tensor_data_type;
}),
- function, file, line, "Tensors have different shapes");
+ function, file, line, "Tensors have different data types");
+ return arm_compute::Error{};
}
-#define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...) ::arm_compute::error_on_mismatching_shapes(__func__, __FILE__, __LINE__, __VA_ARGS__)
-
-/** Throw an error if the passed two tensors have different data types
+/** Return an error if the passed two tensors have different data types
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
* @param[in] line Line on which the error occurred.
* @param[in] tensor The first tensor to be compared.
* @param[in] tensors (Optional) Further allowed tensors.
+ *
+ * @return Error
*/
template <typename... Ts>
-void error_on_mismatching_data_types(const char *function, const char *file, const int line,
- const ITensor *tensor, Ts... tensors)
+inline arm_compute::Error error_on_mismatching_data_types(const char *function, const char *file, const int line,
+ const ITensor *tensor, Ts... tensors)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
- ARM_COMPUTE_UNUSED(tensor);
-
- ARM_COMPUTE_ERROR_ON_LOC(tensor == nullptr, function, file, line);
-
- DataType &&tensor_data_type = tensor->info()->data_type();
- ARM_COMPUTE_UNUSED(tensor_data_type);
-
- const std::array<const ITensor *, sizeof...(Ts)> tensors_array{ { std::forward<Ts>(tensors)... } };
- ARM_COMPUTE_UNUSED(tensors_array);
-
- ARM_COMPUTE_ERROR_ON_LOC_MSG(std::any_of(tensors_array.begin(), tensors_array.end(), [&](const ITensor * tensor_obj)
- {
- ARM_COMPUTE_ERROR_ON_LOC(tensor_obj == nullptr, function, file, line);
- return tensor_obj->info()->data_type() != tensor_data_type;
- }),
- function, file, line, "Tensors have different data types");
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_nullptr(function, file, line, std::forward<Ts>(tensors)...));
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(function, file, line, tensor->info(),
+ detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
+ return arm_compute::Error{};
}
+#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__))
-#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...) ::arm_compute::error_on_mismatching_data_types(__func__, __FILE__, __LINE__, __VA_ARGS__)
-
-/** Throw an error if the passed tensors have different fixed point data types or different fixed point positions
+/** Return an error if the passed tensor infos have different fixed point data types or different fixed point positions
*
* @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
*
- * @param[in] function Function in which the error occurred.
- * @param[in] file Name of the file where the error occurred.
- * @param[in] line Line on which the error occurred.
- * @param[in] tensor_1 The first tensor to be compared.
- * @param[in] tensor_2 The second tensor to be compared.
- * @param[in] tensors (Optional) Further allowed tensors.
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] tensor_info_1 The first tensor info to be compared.
+ * @param[in] tensor_info_2 The second tensor info to be compared.
+ * @param[in] tensor_infos (Optional) Further allowed tensor infos.
+ *
+ * @return Error
*/
template <typename... Ts>
-void error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
- const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
+inline arm_compute::Error error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
+ const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
- ARM_COMPUTE_UNUSED(tensor_1);
- ARM_COMPUTE_UNUSED(tensor_2);
-
- DataType &&first_data_type = tensor_1->info()->data_type();
- const int first_fixed_point_position = tensor_1->info()->fixed_point_position();
- ARM_COMPUTE_UNUSED(first_data_type);
- ARM_COMPUTE_UNUSED(first_fixed_point_position);
+ DataType &&first_data_type = tensor_info_1->data_type();
+ const int first_fixed_point_position = tensor_info_1->fixed_point_position();
if((first_data_type != DataType::QS8) && (first_data_type != DataType::QS16))
{
- return;
+ return arm_compute::Error{};
}
- const std::array < const ITensor *, 1 + sizeof...(Ts) > tensors_array{ { tensor_2, std::forward<Ts>(tensors)... } };
- ARM_COMPUTE_UNUSED(tensors_array);
-
- ARM_COMPUTE_ERROR_ON_LOC_MSG(std::any_of(tensors_array.begin(), tensors_array.end(), [&](const ITensor * tensor)
+ const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_infos_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
{
- return tensor->info()->data_type() != first_data_type;
+ return tensor_info->data_type() != first_data_type;
}),
function, file, line, "Tensors have different fixed point data types");
-
- ARM_COMPUTE_ERROR_ON_LOC_MSG(std::any_of(tensors_array.begin(), tensors_array.end(), [&](const ITensor * tensor)
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_infos_array.begin(), tensor_infos_array.end(), [&](const ITensorInfo * tensor_info)
{
- return tensor->info()->fixed_point_position() != first_fixed_point_position;
+ return tensor_info->fixed_point_position() != first_fixed_point_position;
}),
function, file, line, "Tensors have different fixed point positions");
-}
-#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(...) ::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__)
+ return arm_compute::Error{};
+}
+/** Return an error if the passed tensor have different fixed point data types or different fixed point positions
+ *
+ * @note: If the first tensor doesn't have fixed point data type, the function returns without throwing an error
+ *
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] tensor_1 The first tensor to be compared.
+ * @param[in] tensor_2 The second tensor to be compared.
+ * @param[in] tensors (Optional) Further allowed tensors.
+ *
+ * @return Error
+ */
+template <typename... Ts>
+inline arm_compute::Error error_on_mismatching_fixed_point(const char *function, const char *file, const int line,
+ const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
+{
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(function, file, line, tensor_1->info(), tensor_2->info(),
+ detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
+ return arm_compute::Error{};
+}
+#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
/** Throw an error if the format of the passed tensor/multi-image does not match any of the formats provided.
*
@@ -374,38 +508,80 @@ void error_on_format_not_in(const char *function, const char *file, const int li
}
#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t, ...) ::arm_compute::error_on_format_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
-/** Throw an error if the data type of the passed tensor does not match any of the data types provided.
+/** Return an error if the data type of the passed tensor info does not match any of the data types provided.
*
- * @param[in] function Function in which the error occurred.
- * @param[in] file Name of the file where the error occurred.
- * @param[in] line Line on which the error occurred.
- * @param[in] tensor Tensor to validate.
- * @param[in] dt First data type allowed.
- * @param[in] dts (Optional) Further allowed data types.
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] tensor_info Tensor info to validate.
+ * @param[in] dt First data type allowed.
+ * @param[in] dts (Optional) Further allowed data types.
+ *
+ * @return Error
*/
template <typename T, typename... Ts>
-void error_on_data_type_not_in(const char *function, const char *file, const int line,
- const ITensor *tensor, T &&dt, Ts &&... dts)
+inline arm_compute::Error error_on_data_type_not_in(const char *function, const char *file, const int line,
+ const ITensorInfo *tensor_info, T &&dt, Ts &&... dts)
{
- ARM_COMPUTE_ERROR_ON_LOC(tensor == nullptr, function, file, line);
-
- const DataType &tensor_dt = tensor->info()->data_type(); //NOLINT
- ARM_COMPUTE_UNUSED(tensor_dt);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_info == nullptr, function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
+ const DataType &tensor_dt = tensor_info->data_type(); //NOLINT
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor_dt == DataType::UNKNOWN, function, file, line);
const std::array<T, sizeof...(Ts)> dts_array{ { std::forward<Ts>(dts)... } };
- ARM_COMPUTE_UNUSED(dts_array);
-
- ARM_COMPUTE_ERROR_ON_LOC_MSG(tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T & d)
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(tensor_dt != dt && std::none_of(dts_array.begin(), dts_array.end(), [&](const T & d)
{
return d == tensor_dt;
}),
function, file, line, "ITensor data type %s not supported by this kernel", string_from_data_type(tensor_dt).c_str());
+ return arm_compute::Error{};
}
-#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) ::arm_compute::error_on_data_type_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__)
+/** Return an error if the data type of the passed tensor does not match any of the data types provided.
+ *
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] tensor Tensor to validate.
+ * @param[in] dt First data type allowed.
+ * @param[in] dts (Optional) Further allowed data types.
+ *
+ * @return Error
+ */
+template <typename T, typename... Ts>
+inline arm_compute::Error error_on_data_type_not_in(const char *function, const char *file, const int line,
+ const ITensor *tensor, T &&dt, Ts &&... dts)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
+ 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)...));
+ return arm_compute::Error{};
+}
+#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_data_type_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t, ...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_not_in(__func__, __FILE__, __LINE__, t, __VA_ARGS__))
-/** Throw 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.
+/** 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.
+ *
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] tensor_info Tensor info to validate.
+ * @param[in] num_channels Number of channels to check
+ * @param[in] dt First data type allowed.
+ * @param[in] dts (Optional) Further allowed data types.
+ *
+ * @return Error
+ */
+template <typename T, typename... Ts>
+inline arm_compute::Error error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
+ const ITensorInfo *tensor_info, size_t num_channels, T &&dt, Ts &&... dts)
+{
+ 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)...));
+ const size_t tensor_nc = tensor_info->num_channels();
+ 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);
+ return arm_compute::Error{};
+}
+/** 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.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
@@ -414,32 +590,39 @@ void error_on_data_type_not_in(const char *function, const char *file, const int
* @param[in] num_channels Number of channels to check
* @param[in] dt First data type allowed.
* @param[in] dts (Optional) Further allowed data types.
+ *
+ * @return Error
*/
template <typename T, typename... Ts>
-void error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
- const ITensor *tensor, size_t num_channels, T &&dt, Ts &&... dts)
+inline arm_compute::Error error_on_data_type_channel_not_in(const char *function, const char *file, const int line,
+ const ITensor *tensor, size_t num_channels, T &&dt, Ts &&... dts)
{
- error_on_data_type_not_in(function, file, line, tensor, std::forward<T>(dt), std::forward<Ts>(dts)...);
-
- const size_t tensor_nc = tensor->info()->num_channels();
- ARM_COMPUTE_UNUSED(tensor_nc);
-
- ARM_COMPUTE_ERROR_ON_LOC_MSG(tensor_nc != num_channels, function, file, line, "Number of channels %d. Required number of channels %d", tensor_nc, num_channels);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
+ 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)...));
+ return arm_compute::Error{};
}
-#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) ::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__)
+#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c, ...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_data_type_channel_not_in(__func__, __FILE__, __LINE__, t, c, __VA_ARGS__))
-/** Throw an error if the tensor is not 2D.
+/** Return an error if the tensor is not 2D.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
* @param[in] line Line on which the error occurred.
* @param[in] tensor Tensor to validate.
+ *
+ * @return Error
*/
-void error_on_tensor_not_2d(const char *function, const char *file, const int line,
- const ITensor *tensor);
-#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) ::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t)
+arm_compute::Error error_on_tensor_not_2d(const char *function, const char *file, const int line,
+ const ITensor *tensor);
+#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
+#define ARM_COMPUTE_RETURN_ERROR_ON_TENSOR_NOT_2D(t) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_tensor_not_2d(__func__, __FILE__, __LINE__, t))
-/** Throw an error if the channel is not in channels.
+/** Return an error if the channel is not in channels.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
@@ -447,36 +630,46 @@ void error_on_tensor_not_2d(const char *function, const char *file, const int li
* @param[in] cn Input channel
* @param[in] channel First channel allowed.
* @param[in] channels (Optional) Further allowed channels.
+ *
+ * @return Error
*/
template <typename T, typename... Ts>
-void error_on_channel_not_in(const char *function, const char *file, const int line,
- T cn, T &&channel, Ts &&... channels)
+inline arm_compute::Error error_on_channel_not_in(const char *function, const char *file, const int line,
+ T cn, T &&channel, Ts &&... channels)
{
- ARM_COMPUTE_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == Channel::UNKNOWN, function, file, line);
const std::array<T, sizeof...(Ts)> channels_array{ { std::forward<Ts>(channels)... } };
- ARM_COMPUTE_UNUSED(channels_array);
- ARM_COMPUTE_ERROR_ON_LOC(channel != cn && std::none_of(channels_array.begin(), channels_array.end(), [&](const T & f)
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(channel != cn && std::none_of(channels_array.begin(), channels_array.end(), [&](const T & f)
{
return f == cn;
}),
function, file, line);
+ return arm_compute::Error{};
}
-#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) ::arm_compute::error_on_channel_not_in(__func__, __FILE__, __LINE__, c, __VA_ARGS__)
+#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_channel_not_in(__func__, __FILE__, __LINE__, c, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN(c, ...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_channel_not_in(__func__, __FILE__, __LINE__, c, __VA_ARGS__))
-/** Throw an error if the channel is not in format.
+/** Return an error if the channel is not in format.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
* @param[in] line Line on which the error occurred.
* @param[in] fmt Input channel
* @param[in] cn First channel allowed.
+ *
+ * @return Error
*/
-void error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
- Format fmt, Channel cn);
-#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) ::arm_compute::error_on_channel_not_in_known_format(__func__, __FILE__, __LINE__, f, c)
+arm_compute::Error error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
+ Format fmt, Channel cn);
+#define ARM_COMPUTE_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_channel_not_in_known_format(__func__, __FILE__, __LINE__, f, c))
+#define ARM_COMPUTE_RETURN_ERROR_ON_CHANNEL_NOT_IN_KNOWN_FORMAT(f, c) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_channel_not_in_known_format(__func__, __FILE__, __LINE__, f, c))
-/** Throw an error if the @ref IMultiHOG container is invalid
+/** Return an error if the @ref IMultiHOG container is invalid
*
* An @ref IMultiHOG container is invalid if:
*
@@ -488,23 +681,31 @@ void error_on_channel_not_in_known_format(const char *function, const char *file
* @param[in] file Name of the file where the error occurred.
* @param[in] line Line on which the error occurred.
* @param[in] multi_hog IMultiHOG container to validate
+ *
+ * @return Error
*/
-void error_on_invalid_multi_hog(const char *function, const char *file, const int line,
- const IMultiHOG *multi_hog);
-#define ARM_COMPUTE_ERROR_ON_INVALID_MULTI_HOG(m) ::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m)
+arm_compute::Error error_on_invalid_multi_hog(const char *function, const char *file, const int line,
+ const IMultiHOG *multi_hog);
+#define ARM_COMPUTE_ERROR_ON_INVALID_MULTI_HOG(m) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
+#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_MULTI_HOG(m) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_multi_hog(__func__, __FILE__, __LINE__, m))
-/** Throw an error if the kernel is not configured.
+/** Return an error if the kernel is not configured.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
* @param[in] line Line on which the error occurred.
* @param[in] kernel Kernel to validate.
*/
-void error_on_unconfigured_kernel(const char *function, const char *file, const int line,
- const IKernel *kernel);
-#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) ::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k)
+arm_compute::Error error_on_unconfigured_kernel(const char *function, const char *file, const int line,
+ const IKernel *kernel);
+#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
+#define ARM_COMPUTE_RETURN_ERROR_ON_UNCONFIGURED_KERNEL(k) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_unconfigured_kernel(__func__, __FILE__, __LINE__, k))
-/** Throw an error if if the coordinates and shape of the subtensor are within the parent tensor.
+/** Return an error if if the coordinates and shape of the subtensor are within the parent tensor.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
@@ -512,24 +713,57 @@ void error_on_unconfigured_kernel(const char *function, const char *file, const
* @param[in] parent_shape Parent tensor shape
* @param[in] coords Coordinates inside the parent tensor where the first element of the subtensor is
* @param[in] shape Shape of the subtensor
+ *
+ * @return Error
*/
-void error_on_invalid_subtensor(const char *function, const char *file, const int line,
- const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape);
-#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) ::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s)
+arm_compute::Error error_on_invalid_subtensor(const char *function, const char *file, const int line,
+ const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape);
+#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
+#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR(p, c, s) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, p, c, s))
-/** Throw an error if the valid region of a subtensor is not inside the valid region of the parent tensor.
+/** Return an error if the valid region of a subtensor is not inside the valid region of the parent tensor.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
* @param[in] line Line on which the error occurred.
* @param[in] parent_valid_region Parent valid region.
* @param[in] valid_region Valid region of subtensor.
+ *
+ * @return Error
*/
-void error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
- const ValidRegion &parent_valid_region, const ValidRegion &valid_region);
-#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) ::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv)
-
-/** Throw an error if the input fixed-point positions are different.
+arm_compute::Error error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
+ const ValidRegion &parent_valid_region, const ValidRegion &valid_region);
+#define ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
+#define ARM_COMPUTE_RETURN_ERROR_ON_INVALID_SUBTENSOR_VALID_REGION(pv, sv) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_invalid_subtensor_valid_region(__func__, __FILE__, __LINE__, pv, sv))
+
+/** Return an error if the input fixed-point positions are different.
+ *
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] tensor_info_1 The first tensor info to be compared.
+ * @param[in] tensor_info_2 The second tensor info to be compared.
+ * @param[in] tensor_infos (Optional) Further allowed tensor infos.
+ *
+ * @return Error
+ */
+template <typename... Ts>
+inline arm_compute::Error error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
+ const ITensorInfo *tensor_info_1, const ITensorInfo *tensor_info_2, Ts... tensor_infos)
+{
+ const std::array < const ITensorInfo *, 1 + sizeof...(Ts) > tensor_info_array{ { tensor_info_2, std::forward<Ts>(tensor_infos)... } };
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(std::any_of(tensor_info_array.begin(), tensor_info_array.end(), [&](const ITensorInfo * tensor_info)
+ {
+ return tensor_info->fixed_point_position() != tensor_info_1->fixed_point_position();
+ }),
+ function, file, line, "Tensors have different fixed-point positions");
+ return arm_compute::Error{};
+}
+/** Return an error if the input fixed-point positions are different.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
@@ -537,43 +771,64 @@ void error_on_invalid_subtensor_valid_region(const char *function, const char *f
* @param[in] tensor_1 The first tensor to be compared.
* @param[in] tensor_2 The second tensor to be compared.
* @param[in] tensors (Optional) Further allowed tensors.
+ *
+ * @return Error
*/
template <typename... Ts>
-void error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
- const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
+inline arm_compute::Error error_on_mismatching_fixed_point_position(const char *function, const char *file, const int line,
+ const ITensor *tensor_1, const ITensor *tensor_2, Ts... tensors)
{
- const std::array < const ITensor *, 1 + sizeof...(Ts) > tensors_array{ { tensor_2, std::forward<Ts>(tensors)... } };
- ARM_COMPUTE_UNUSED(tensors_array);
-
- ARM_COMPUTE_ERROR_ON_LOC_MSG(std::any_of(tensors_array.begin(), tensors_array.end(), [&](const ITensor * tensor)
- {
- return tensor->info()->fixed_point_position() != tensor_1->info()->fixed_point_position();
- }),
- function, file, line, "Tensors have different fixed-point positions");
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point_position(function, file, line, tensor_1->info(), tensor_2->info(),
+ detail::get_tensor_info_t<ITensorInfo *>()(tensors)...));
+ return arm_compute::Error{};
}
-#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) ::arm_compute::error_on_mismatching_fixed_point_position(__func__, __FILE__, __LINE__, __VA_ARGS__)
+#define ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_mismatching_fixed_point_position(__func__, __FILE__, __LINE__, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_mismatching_fixed_point_position(__func__, __FILE__, __LINE__, __VA_ARGS__))
-/** Throw an error if the fixed-point value is not representable in the specified Q format.
+/** Return an error if the fixed-point value is not representable in the specified Q format.
+ *
+ * @param[in] function Function in which the error occurred.
+ * @param[in] file Name of the file where the error occurred.
+ * @param[in] line Line on which the error occurred.
+ * @param[in] value The floating point value to be checked.
+ * @param[in] tensor_info Input tensor info that has information on data type and fixed-point position.
+ *
+ * @return Error
+ */
+inline arm_compute::Error error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
+ float value, const ITensorInfo *tensor_info)
+{
+ const int fixed_point_position = tensor_info->fixed_point_position();
+ const DataType dt = tensor_info->data_type();
+ const unsigned int q_max_range = 0xFFFFFFFFu >> (((sizeof(unsigned int) - element_size_from_data_type(dt)) * 8) + 1);
+ const float max_range = q_max_range / (static_cast<float>(1 << fixed_point_position));
+
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(value > max_range, function, file, line,
+ "Value %f is not representable in %s with fixed-point position %d", value, string_from_data_type(dt).c_str(), fixed_point_position);
+ return arm_compute::Error{};
+}
+/** Return an error an error if the fixed-point value is not representable in the specified Q format.
*
* @param[in] function Function in which the error occurred.
* @param[in] file Name of the file where the error occurred.
* @param[in] line Line on which the error occurred.
* @param[in] value The floating point value to be checked.
* @param[in] tensor Input tensor that has information on data type and fixed-point position.
+ *
+ * @return Error
*/
-template <typename... Ts>
-void error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
- float value, const ITensor *tensor)
+inline arm_compute::Error error_on_value_not_representable_in_fixed_point(const char *function, const char *file, int line,
+ float value, const ITensor *tensor)
{
- const int fixed_point_position = tensor->info()->fixed_point_position();
- const DataType dt = tensor->info()->data_type();
- const unsigned int q_max_range = 0xFFFFFFFFu >> (((sizeof(unsigned int) - element_size_from_data_type(dt)) * 8) + 1);
- const float max_range = q_max_range / (static_cast<float>(1 << fixed_point_position));
- ARM_COMPUTE_UNUSED(max_range);
-
- ARM_COMPUTE_ERROR_ON_LOC_MSG(value > max_range, function, file, line,
- "Value %f is not representable in %s with fixed-point position %d", value, string_from_data_type(dt).c_str(), fixed_point_position);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_value_not_representable_in_fixed_point(function, file, line, value, tensor->info()));
+ return arm_compute::Error{};
}
-#define ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) ::arm_compute::error_on_value_not_representable_in_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__)
+#define ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
+ ARM_COMPUTE_ERROR_THROW(::arm_compute::error_on_value_not_representable_in_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
+#define ARM_COMPUTE_RETURN_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(...) \
+ ARM_COMPUTE_RETURN_ON_ERROR(::arm_compute::error_on_value_not_representable_in_fixed_point(__func__, __FILE__, __LINE__, __VA_ARGS__))
}
#endif /* __ARM_COMPUTE_VALIDATE_H__*/
diff --git a/arm_compute/core/utils/logging/LoggerRegistry.h b/arm_compute/core/utils/logging/LoggerRegistry.h
index d861476fea..d3c691139e 100644
--- a/arm_compute/core/utils/logging/LoggerRegistry.h
+++ b/arm_compute/core/utils/logging/LoggerRegistry.h
@@ -51,10 +51,11 @@ public:
* @note Some names are reserved e.g. [CORE, RUNTIME, GRAPH]
*
* @param[in] name Logger's name
- * @param[in] log_level Logger's log level
- * @param[in] printers Printers to attach to the system loggers
+ * @param[in] log_level Logger's log level. Defaults to @ref LogLevel::INFO
+ * @param[in] printers Printers to attach to the system loggers. Defaults with a @ref StdPrinter.
*/
- void create_logger(const std::string &name, LogLevel log_level, std::vector<std::shared_ptr<Printer>> printers = {});
+ void create_logger(const std::string &name, LogLevel log_level = LogLevel::INFO,
+ std::vector<std::shared_ptr<Printer>> printers = { std::make_shared<StdPrinter>() });
/** Remove a logger
*
* @param name Logger's name
@@ -69,10 +70,11 @@ public:
std::shared_ptr<Logger> logger(const std::string &name);
/** Creates reserved library loggers
*
- * @param[in] log_level Logger's log level
- * @param[in] printers Printers to attach to the system loggers
+ * @param[in] log_level (Optional) Logger's log level. Defaults to @ref LogLevel::INFO
+ * @param[in] printers (Optional) Printers to attach to the system loggers. Defaults with a @ref StdPrinter.
*/
- void create_reserved_loggers(LogLevel log_level, std::vector<std::shared_ptr<Printer>> printers = {});
+ void create_reserved_loggers(LogLevel log_level = LogLevel::INFO,
+ std::vector<std::shared_ptr<Printer>> printers = { std::make_shared<StdPrinter>() });
private:
/** Default constructor */
diff --git a/arm_compute/core/utils/logging/Macros.h b/arm_compute/core/utils/logging/Macros.h
index b17354bed7..bc121e25eb 100644
--- a/arm_compute/core/utils/logging/Macros.h
+++ b/arm_compute/core/utils/logging/Macros.h
@@ -30,32 +30,35 @@
#ifdef ARM_COMPUTE_LOGGING_ENABLED
-#define ARM_COMPUTE_LOG_MSG(logger_name, log_level, msg) \
- { \
- auto logger = arm_compute::logging::LoggerRegistry::get().logger(logger_name); \
- if(logger != nullptr) \
- { \
- logger->log(log_level, msg); \
- } \
- }
+#define ARM_COMPUTE_LOG_MSG(logger_name, log_level, msg) \
+ do \
+ { \
+ auto __logger = arm_compute::logging::LoggerRegistry::get().logger(logger_name); \
+ if(__logger != nullptr) \
+ { \
+ __logger->log(log_level, msg); \
+ } \
+ } while(false)
-#define ARM_COMPUTE_LOG_MSG_WITH_FORMAT(logger_name, log_level, fmt, ...) \
- { \
- auto logger = arm_compute::logging::LoggerRegistry::get().logger(logger_name); \
- if(logger != nullptr) \
- { \
- logger->log(log_level, fmt, __VA_ARGS__); \
- } \
- }
+#define ARM_COMPUTE_LOG_MSG_WITH_FORMAT(logger_name, log_level, fmt, ...) \
+ do \
+ { \
+ auto __logger = arm_compute::logging::LoggerRegistry::get().logger(logger_name); \
+ if(__logger != nullptr) \
+ { \
+ __logger->log(log_level, fmt, __VA_ARGS__); \
+ } \
+ } while(false)
-#define ARM_COMPUTE_LOG_STREAM(logger_name, log_level, stream) \
- { \
- auto logger = arm_compute::logging::LoggerRegistry::get().logger(logger_name); \
- if(logger != nullptr) \
- { \
- logger->log(log_level, static_cast<std::ostringstream &>(std::ostringstream() << stream).str()); \
- } \
- }
+#define ARM_COMPUTE_LOG_STREAM(logger_name, log_level, stream) \
+ do \
+ { \
+ auto __logger = arm_compute::logging::LoggerRegistry::get().logger(logger_name); \
+ if(__logger != nullptr) \
+ { \
+ __logger->log(log_level, static_cast<std::ostringstream &>(std::ostringstream() << stream).str()); \
+ } \
+ } while(false)
#else /* ARM_COMPUTE_LOGGING_ENABLED */
diff --git a/arm_compute/graph/Types.h b/arm_compute/graph/Types.h
index b3aa034477..5b6c9bde0d 100644
--- a/arm_compute/graph/Types.h
+++ b/arm_compute/graph/Types.h
@@ -29,10 +29,25 @@
#include "arm_compute/core/TensorInfo.h"
#include "arm_compute/core/utils/logging/Macros.h"
-#define ARM_COMPUTE_LOG_GRAPH(log_level, x) \
+/** Create a default core logger
+ *
+ * @note It will eventually create all default loggers in don't exist
+ */
+#define ARM_COMPUTE_CREATE_DEFAULT_GRAPH_LOGGER() \
+ do \
+ { \
+ if(arm_compute::logging::LoggerRegistry::get().logger("GRAPH") == nullptr) \
+ { \
+ arm_compute::logging::LoggerRegistry::get().create_reserved_loggers(); \
+ } \
+ } while(false)
+
+#define ARM_COMPUTE_LOG_GRAPH(log_level, x) \
+ ARM_COMPUTE_CREATE_DEFAULT_GRAPH_LOGGER(); \
ARM_COMPUTE_LOG_STREAM("GRAPH", log_level, x)
-#define ARM_COMPUTE_LOG_GRAPH_INFO(x) \
+#define ARM_COMPUTE_LOG_GRAPH_INFO(x) \
+ ARM_COMPUTE_CREATE_DEFAULT_GRAPH_LOGGER(); \
ARM_COMPUTE_LOG_STREAM("GRAPH", arm_compute::logging::LogLevel::INFO, x)
namespace arm_compute
diff --git a/arm_compute/runtime/CL/functions/CLPoolingLayer.h b/arm_compute/runtime/CL/functions/CLPoolingLayer.h
index 80233d400e..f7fd114be1 100644
--- a/arm_compute/runtime/CL/functions/CLPoolingLayer.h
+++ b/arm_compute/runtime/CL/functions/CLPoolingLayer.h
@@ -26,6 +26,7 @@
#include "arm_compute/runtime/CL/ICLSimpleFunction.h"
+#include "arm_compute/core/Error.h"
#include "arm_compute/core/Types.h"
namespace arm_compute
@@ -47,6 +48,15 @@ public:
* @param[in] pool_info Contains pooling operation information described in @ref PoolingLayerInfo.
*/
void configure(ICLTensor *input, ICLTensor *output, const PoolingLayerInfo &pool_info);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLPoolingLayer
+ *
+ * @param[in] input Input's tensor info
+ * @param[in] output Output's tensor info
+ * @param[in] pool_info Contains pooling operation information described in @ref PoolingLayerInfo.
+ *
+ * @return an expected value
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *output, const PoolingLayerInfo &pool_info);
};
} // namespace arm_compute
#endif /* __ARM_COMPUTE_CLPOOLINGLAYER_H__ */
diff --git a/examples/graph_alexnet.cpp b/examples/graph_alexnet.cpp
index be852b94ff..1d041997e3 100644
--- a/examples/graph_alexnet.cpp
+++ b/examples/graph_alexnet.cpp
@@ -25,7 +25,6 @@
#error "This example needs to be built with -DARM_COMPUTE_CL"
#endif /* ARM_COMPUTE_CL */
-#include "arm_compute/core/utils/logging/LoggerRegistry.h"
#include "arm_compute/graph/Graph.h"
#include "arm_compute/graph/Nodes.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
@@ -160,7 +159,6 @@ void main_graph_alexnet(int argc, const char **argv)
}
Graph graph;
- LoggerRegistry::get().create_reserved_loggers(LogLevel::INFO, { std::make_shared<StdPrinter>() });
graph << hint
<< Tensor(TensorInfo(TensorShape(227U, 227U, 3U, 1U), 1, DataType::F32),
diff --git a/examples/graph_lenet.cpp b/examples/graph_lenet.cpp
index 82f4c5a4c1..53b32d9ab4 100644
--- a/examples/graph_lenet.cpp
+++ b/examples/graph_lenet.cpp
@@ -25,7 +25,6 @@
#error "This example needs to be built with -DARM_COMPUTE_CL"
#endif /* ARM_COMPUTE_CL */
-#include "arm_compute/core/utils/logging/LoggerRegistry.h"
#include "arm_compute/graph/Graph.h"
#include "arm_compute/graph/Nodes.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
@@ -103,7 +102,6 @@ void main_graph_lenet(int argc, const char **argv)
}
Graph graph;
- LoggerRegistry::get().create_reserved_loggers(LogLevel::INFO, { std::make_shared<StdPrinter>() });
//conv1 << pool1 << conv2 << pool2 << fc1 << act1 << fc2 << smx
graph << hint
diff --git a/examples/graph_squeezenet.cpp b/examples/graph_squeezenet.cpp
index 888dd5e5f1..a1a7b8619e 100644
--- a/examples/graph_squeezenet.cpp
+++ b/examples/graph_squeezenet.cpp
@@ -25,7 +25,6 @@
#error "This example needs to be built with -DARM_COMPUTE_CL"
#endif /* ARM_COMPUTE_CL */
-#include "arm_compute/core/utils/logging/LoggerRegistry.h"
#include "arm_compute/graph/Graph.h"
#include "arm_compute/graph/Nodes.h"
#include "arm_compute/graph/SubGraph.h"
@@ -125,7 +124,6 @@ void main_graph_squeezenet(int argc, const char **argv)
}
Graph graph;
- LoggerRegistry::get().create_reserved_loggers(LogLevel::INFO, { std::make_shared<StdPrinter>() });
graph << TargetHint::OPENCL
<< Tensor(TensorInfo(TensorShape(224U, 224U, 3U, batches), 1, DataType::F32), DummyAccessor())
diff --git a/scripts/clang_tidy_rules.py b/scripts/clang_tidy_rules.py
index b811847ba8..09dc2e1c70 100755
--- a/scripts/clang_tidy_rules.py
+++ b/scripts/clang_tidy_rules.py
@@ -60,10 +60,10 @@ def filter_clang_tidy_lines( lines ):
elif "warning:" in line:
if ("uninitialized record type: '__ret'" in line or
"local variable '__bound_functor' is still referred to by the global variable '__once_callable'" in line or
- ("Error.cpp" in line and "thrown exception type is not nothrow copy constructible" in line) or
- ("Error.cpp" in line and "uninitialized record type: 'args'" in line) or
- ("Error.cpp" in line and "do not call c-style vararg functions" in line) or
- ("Error.cpp" in line and "do not define a C-style variadic function" in line) or
+ (any(f in line for f in ["Error.cpp","Error.h"]) and "thrown exception type is not nothrow copy constructible" in line) or
+ (any(f in line for f in ["Error.cpp","Error.h"]) and "uninitialized record type: 'args'" in line) or
+ (any(f in line for f in ["Error.cpp","Error.h"]) and "do not call c-style vararg functions" in line) or
+ (any(f in line for f in ["Error.cpp","Error.h"]) and "do not define a C-style variadic function" in line) or
("NEMinMaxLocationKernel.cpp" in line and "move constructors should be marked noexcept" in line) or
("NEMinMaxLocationKernel.cpp" in line and "move assignment operators should be marked noexcept" in line) or
("CLMinMaxLocationKernel.cpp" in line and "Forming reference to null pointer" in line) or
@@ -105,6 +105,7 @@ def filter_clang_tidy_lines( lines ):
("BOOST_TEST" in lines[i + 1] or
"BOOST_FAIL" in lines[i + 1] or
"BOOST_CHECK_THROW" in lines[i + 1] or
+ "ARM_COMPUTE_RETURN_ON" in lines[i + 1] or
"syscall" in lines[i + 1])):
print_context=False
continue
diff --git a/src/core/CL/CLHelpers.cpp b/src/core/CL/CLHelpers.cpp
index 901ac3f39a..54e3e525b4 100644
--- a/src/core/CL/CLHelpers.cpp
+++ b/src/core/CL/CLHelpers.cpp
@@ -24,6 +24,7 @@
#include "arm_compute/core/CL/CLHelpers.h"
#include "arm_compute/core/CL/CLTypes.h"
#include "arm_compute/core/Error.h"
+#include "arm_compute/core/Log.h"
#include "arm_compute/core/Types.h"
#include <map>
@@ -187,7 +188,7 @@ GPUTarget get_target_from_device(cl::Device &device)
if(!found_mali)
{
- ARM_COMPUTE_INFO("Can't find valid Mali GPU. Target is set to MIDGARD.");
+ ARM_COMPUTE_LOG_INFO_MSG_CORE("Can't find valid Mali GPU. Target is set to MIDGARD.");
return GPUTarget::MIDGARD;
}
@@ -201,7 +202,7 @@ GPUTarget get_target_from_device(cl::Device &device)
case 'G':
return get_bifrost_target(version);
default:
- ARM_COMPUTE_INFO("Mali GPU unknown. Target is set to the default one.");
+ ARM_COMPUTE_LOG_INFO_MSG_CORE("Mali GPU unknown. Target is set to the default one.");
return GPUTarget::MIDGARD;
}
}
diff --git a/src/core/CL/kernels/CLPoolingLayerKernel.cpp b/src/core/CL/kernels/CLPoolingLayerKernel.cpp
index 8b8f61e621..19d36a6ac6 100644
--- a/src/core/CL/kernels/CLPoolingLayerKernel.cpp
+++ b/src/core/CL/kernels/CLPoolingLayerKernel.cpp
@@ -179,6 +179,38 @@ void CLPoolingLayerKernel::configure(const ICLTensor *input, ICLTensor *output,
ICLKernel::configure(win);
}
+Error CLPoolingLayerKernel::validate(const ITensorInfo *input, const ITensorInfo *output, const PoolingLayerInfo &pool_info)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QS16, DataType::F16, DataType::F32);
+
+ int pool_pad_x = 0;
+ int pool_pad_y = 0;
+ int pool_size = pool_info.pool_size();
+ std::tie(pool_pad_x, pool_pad_y) = pool_info.pad_stride_info().pad();
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(((pool_pad_x >= pool_size) || (pool_pad_y >= pool_size)),
+ "Invalid pool size and pool pad combination");
+
+ // Checks performed when output is configured
+ if(output->total_size() != 0)
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(input, output);
+
+ unsigned int pooled_w = 0;
+ unsigned int pooled_h = 0;
+ std::tie(pooled_w, pooled_h) = scaled_dimensions(input->dimension(0),
+ input->dimension(1),
+ pool_size,
+ pool_size,
+ pool_info.pad_stride_info());
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG((output->dimension(0) != pooled_w) != (output->dimension(1) != pooled_h),
+ "Invalid output pooling dimensions!");
+ }
+
+ return Error{};
+}
+
void CLPoolingLayerKernel::run(const Window &window, cl::CommandQueue &queue)
{
ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
diff --git a/src/core/Error.cpp b/src/core/Error.cpp
index 389e390736..2e699feeb9 100644
--- a/src/core/Error.cpp
+++ b/src/core/Error.cpp
@@ -28,7 +28,9 @@
#include <iostream>
#include <stdexcept>
-void arm_compute::error(const char *function, const char *file, const int line, const char *msg, ...)
+using namespace arm_compute;
+
+Error arm_compute::create_error(ErrorCode error_code, const char *function, const char *file, const int line, const char *msg, ...)
{
char out[512];
va_list args;
@@ -37,16 +39,14 @@ void arm_compute::error(const char *function, const char *file, const int line,
vsnprintf(out + offset, sizeof(out) - offset, msg, args);
va_end(args);
- throw std::runtime_error(std::string(out));
+ return Error(error_code, std::string(out));
}
-void arm_compute::debug(const char *function, const char *file, const int line, const char *msg, ...)
+void arm_compute::error(const char *function, const char *file, const int line, const char *msg, ...)
{
- char out[512];
va_list args;
va_start(args, msg);
- int offset = snprintf(out, sizeof(out), "in %s %s:%d: ", function, file, line);
- vsnprintf(out + offset, sizeof(out) - offset, msg, args);
+ auto err = create_error(ErrorCode::RUNTIME_ERROR, function, file, line, msg, args);
va_end(args);
- std::cout << std::string(out) << std::endl;
+ throw std::runtime_error(err.description());
}
diff --git a/src/core/Utils.cpp b/src/core/Utils.cpp
index 0a35e07430..bd6911fd2b 100644
--- a/src/core/Utils.cpp
+++ b/src/core/Utils.cpp
@@ -384,4 +384,5 @@ int arm_compute::max_consecutive_elements_display_width(std::ostream &s, DataTyp
default:
ARM_COMPUTE_ERROR("Undefined element size for given data type");
}
+ return 0;
}
diff --git a/src/core/Validate.cpp b/src/core/Validate.cpp
index 084a325711..b286d69454 100644
--- a/src/core/Validate.cpp
+++ b/src/core/Validate.cpp
@@ -23,108 +23,88 @@
*/
#include "arm_compute/core/Validate.h"
-void arm_compute::error_on_mismatching_windows(const char *function, const char *file, const int line,
- const arm_compute::Window &full, const arm_compute::Window &win)
+arm_compute::Error arm_compute::error_on_mismatching_windows(const char *function, const char *file, const int line,
+ const arm_compute::Window &full, const arm_compute::Window &win)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
-
full.validate();
win.validate();
for(size_t i = 0; i < arm_compute::Coordinates::num_max_dimensions; ++i)
{
- ARM_COMPUTE_ERROR_ON_LOC(full[i].start() != win[i].start(), function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC(full[i].end() != win[i].end(), function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC(full[i].step() != win[i].step(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(full[i].start() != win[i].start(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(full[i].end() != win[i].end(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(full[i].step() != win[i].step(), function, file, line);
}
+ return arm_compute::Error{};
}
-void arm_compute::error_on_invalid_subwindow(const char *function, const char *file, const int line,
- const arm_compute::Window &full, const arm_compute::Window &sub)
+arm_compute::Error arm_compute::error_on_invalid_subwindow(const char *function, const char *file, const int line,
+ const arm_compute::Window &full, const arm_compute::Window &sub)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
-
full.validate();
sub.validate();
for(size_t i = 0; i < arm_compute::Coordinates::num_max_dimensions; ++i)
{
- ARM_COMPUTE_ERROR_ON_LOC(full[i].start() > sub[i].start(), function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC(full[i].end() < sub[i].end(), function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC(full[i].step() != sub[i].step(), function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC((sub[i].start() - full[i].start()) % sub[i].step(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(full[i].start() > sub[i].start(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(full[i].end() < sub[i].end(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(full[i].step() != sub[i].step(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC((sub[i].start() - full[i].start()) % sub[i].step(), function, file, line);
}
+ return arm_compute::Error{};
}
-void arm_compute::error_on_window_not_collapsable_at_dimension(const char *function, const char *file, const int line,
- const arm_compute::Window &full, const arm_compute::Window &window, const int dim)
+arm_compute::Error arm_compute::error_on_window_not_collapsable_at_dimension(const char *function, const char *file, const int line,
+ const arm_compute::Window &full, const arm_compute::Window &window, const int dim)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
- ARM_COMPUTE_UNUSED(dim);
-
full.validate();
window.validate();
- ARM_COMPUTE_ERROR_ON_LOC(window[dim].start() != 0, function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC(window[dim].start() != full[dim].start(), function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC(full[dim].end() != window[dim].end(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(window[dim].start() != 0, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(window[dim].start() != full[dim].start(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(full[dim].end() != window[dim].end(), function, file, line);
+
+ return arm_compute::Error{};
}
-void arm_compute::error_on_coordinates_dimensions_gte(const char *function, const char *file, const int line,
- const arm_compute::Coordinates &pos, unsigned int max_dim)
+arm_compute::Error arm_compute::error_on_coordinates_dimensions_gte(const char *function, const char *file, const int line,
+ const arm_compute::Coordinates &pos, unsigned int max_dim)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
- ARM_COMPUTE_UNUSED(pos);
-
for(unsigned int i = max_dim; i < arm_compute::Coordinates::num_max_dimensions; ++i)
{
- ARM_COMPUTE_ERROR_ON_LOC(pos[i] != 0, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(pos[i] != 0, function, file, line);
}
+ return arm_compute::Error{};
}
-void arm_compute::error_on_window_dimensions_gte(const char *function, const char *file, const int line,
- const arm_compute::Window &win, unsigned int max_dim)
+arm_compute::Error arm_compute::error_on_window_dimensions_gte(const char *function, const char *file, const int line,
+ const arm_compute::Window &win, unsigned int max_dim)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
- ARM_COMPUTE_UNUSED(win);
-
for(unsigned int i = max_dim; i < arm_compute::Coordinates::num_max_dimensions; ++i)
{
- ARM_COMPUTE_ERROR_ON_LOC_MSG(win[i].start() != 0 || win[i].end() != win[i].step(),
- function, file, line,
- "Maximum number of dimensions expected %u but dimension %u is not empty", max_dim, i);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(win[i].start() != 0 || win[i].end() != win[i].step(),
+ function, file, line,
+ "Maximum number of dimensions expected %u but dimension %u is not empty", max_dim, i);
}
+ return arm_compute::Error{};
}
-void arm_compute::error_on_tensor_not_2d(const char *function, const char *file, const int line,
- const arm_compute::ITensor *tensor)
+arm_compute::Error arm_compute::error_on_tensor_not_2d(const char *function, const char *file, const int line,
+ const arm_compute::ITensor *tensor)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
- ARM_COMPUTE_UNUSED(tensor);
-
- ARM_COMPUTE_ERROR_ON_LOC(tensor == nullptr, function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC_MSG(tensor->info()->num_dimensions() != 2,
- function, file, line,
- "Only 2D Tensors are supported by this kernel (%d passed)", tensor->info()->num_dimensions());
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(tensor->info() == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(tensor->info()->num_dimensions() != 2,
+ function, file, line,
+ "Only 2D Tensors are supported by this kernel (%d passed)", tensor->info()->num_dimensions());
+ return arm_compute::Error{};
}
-void arm_compute::error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
- arm_compute::Format fmt, arm_compute::Channel cn)
+arm_compute::Error arm_compute::error_on_channel_not_in_known_format(const char *function, const char *file, const int line,
+ arm_compute::Format fmt, arm_compute::Channel cn)
{
- ARM_COMPUTE_ERROR_ON_LOC(fmt == arm_compute::Format::UNKNOWN, function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC(cn == arm_compute::Channel::UNKNOWN, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(fmt == arm_compute::Format::UNKNOWN, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(cn == arm_compute::Channel::UNKNOWN, function, file, line);
switch(fmt)
{
@@ -148,84 +128,68 @@ void arm_compute::error_on_channel_not_in_known_format(const char *function, con
default:
ARM_COMPUTE_ERROR_LOC(function, file, line, "Not supported format.");
}
+ return arm_compute::Error{};
}
-void arm_compute::error_on_invalid_multi_hog(const char *function, const char *file, const int line,
- const arm_compute::IMultiHOG *multi_hog)
+arm_compute::Error arm_compute::error_on_invalid_multi_hog(const char *function, const char *file, const int line,
+ const arm_compute::IMultiHOG *multi_hog)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
-
- ARM_COMPUTE_ERROR_ON_LOC(nullptr == multi_hog, function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC(0 == multi_hog->num_models(), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(nullptr == multi_hog, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(0 == multi_hog->num_models(), function, file, line);
for(size_t i = 1; i < multi_hog->num_models(); ++i)
{
- ARM_COMPUTE_ERROR_ON_LOC_MSG(multi_hog->model(0)->info()->phase_type() != multi_hog->model(i)->info()->phase_type(),
- function, file, line,
- "All HOG parameters must have the same phase type");
- ARM_COMPUTE_ERROR_ON_LOC_MSG(multi_hog->model(0)->info()->normalization_type() != multi_hog->model(i)->info()->normalization_type(),
- function, file, line,
- "All HOG parameters must have the same normalization type");
- ARM_COMPUTE_ERROR_ON_LOC_MSG((multi_hog->model(0)->info()->l2_hyst_threshold() != multi_hog->model(i)->info()->l2_hyst_threshold())
- && (multi_hog->model(0)->info()->normalization_type() == arm_compute::HOGNormType::L2HYS_NORM),
- function, file, line,
- "All HOG parameters must have the same l2 hysteresis threshold if you use L2 hysteresis normalization type");
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(multi_hog->model(0)->info()->phase_type() != multi_hog->model(i)->info()->phase_type(),
+ function, file, line,
+ "All HOG parameters must have the same phase type");
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(multi_hog->model(0)->info()->normalization_type() != multi_hog->model(i)->info()->normalization_type(),
+ function, file, line,
+ "All HOG parameters must have the same normalization type");
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG((multi_hog->model(0)->info()->l2_hyst_threshold() != multi_hog->model(i)->info()->l2_hyst_threshold())
+ && (multi_hog->model(0)->info()->normalization_type() == arm_compute::HOGNormType::L2HYS_NORM),
+ function, file, line,
+ "All HOG parameters must have the same l2 hysteresis threshold if you use L2 hysteresis normalization type");
}
+ return arm_compute::Error{};
}
-void arm_compute::error_on_unconfigured_kernel(const char *function, const char *file, const int line,
- const arm_compute::IKernel *kernel)
+arm_compute::Error arm_compute::error_on_unconfigured_kernel(const char *function, const char *file, const int line,
+ const arm_compute::IKernel *kernel)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
- ARM_COMPUTE_UNUSED(kernel);
-
- ARM_COMPUTE_ERROR_ON_LOC(kernel == nullptr, function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC_MSG((kernel->window().x().start() == kernel->window().x().end()) && (kernel->window().x().end() == 0) && (kernel->window().x().step() == 0),
- function, file, line,
- "This kernel hasn't been configured.");
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(kernel == nullptr, function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG((kernel->window().x().start() == kernel->window().x().end()) && (kernel->window().x().end() == 0) && (kernel->window().x().step() == 0),
+ function, file, line,
+ "This kernel hasn't been configured.");
+ return arm_compute::Error{};
}
-void arm_compute::error_on_invalid_subtensor(const char *function, const char *file, const int line,
- const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape)
+arm_compute::Error arm_compute::error_on_invalid_subtensor(const char *function, const char *file, const int line,
+ const TensorShape &parent_shape, const Coordinates &coords, const TensorShape &shape)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
- ARM_COMPUTE_UNUSED(parent_shape);
- ARM_COMPUTE_UNUSED(coords);
- ARM_COMPUTE_UNUSED(shape);
-
// Subtensor should not index in x, y dimensions.
- ARM_COMPUTE_ERROR_ON_LOC(((coords.x() != 0) && (coords.y() != 0)), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(((coords.x() != 0) && (coords.y() != 0)), function, file, line);
// Subtensor shape should match parent tensor in x, y dimensions.
- ARM_COMPUTE_ERROR_ON_LOC(((parent_shape.x() != shape.x()) && (parent_shape.y() != parent_shape.y())), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(((parent_shape.x() != shape.x()) && (parent_shape.y() != parent_shape.y())), function, file, line);
// Check dimensions
for(unsigned int i = 0; i < TensorShape::num_max_dimensions; ++i)
{
- ARM_COMPUTE_ERROR_ON_LOC(((coords[i] >= static_cast<int>(parent_shape[i])) || (coords[i] + static_cast<int>(shape[i]) > static_cast<int>(parent_shape[i]))),
- function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC(((coords[i] >= static_cast<int>(parent_shape[i])) || (coords[i] + static_cast<int>(shape[i]) > static_cast<int>(parent_shape[i]))),
+ function, file, line);
}
+ return arm_compute::Error{};
}
-void arm_compute::error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
- const ValidRegion &parent_valid_region, const ValidRegion &valid_region)
+arm_compute::Error arm_compute::error_on_invalid_subtensor_valid_region(const char *function, const char *file, const int line,
+ const ValidRegion &parent_valid_region, const ValidRegion &valid_region)
{
- ARM_COMPUTE_UNUSED(function);
- ARM_COMPUTE_UNUSED(file);
- ARM_COMPUTE_UNUSED(line);
- ARM_COMPUTE_UNUSED(parent_valid_region);
- ARM_COMPUTE_UNUSED(valid_region);
-
// Check valid regions
for(unsigned int d = 0; d < TensorShape::num_max_dimensions; ++d)
{
- ARM_COMPUTE_ERROR_ON_LOC((parent_valid_region.anchor[d] > valid_region.anchor[d]), function, file, line);
- ARM_COMPUTE_ERROR_ON_LOC((parent_valid_region.anchor[d] + static_cast<int>(parent_valid_region.shape[d])) < (valid_region.anchor[d] + static_cast<int>(valid_region.shape[d])),
- function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC((parent_valid_region.anchor[d] > valid_region.anchor[d]), function, file, line);
+ ARM_COMPUTE_RETURN_ERROR_ON_LOC((parent_valid_region.anchor[d] + static_cast<int>(parent_valid_region.shape[d])) < (valid_region.anchor[d] + static_cast<int>(valid_region.shape[d])),
+ function, file, line);
}
+
+ return arm_compute::Error{};
}
diff --git a/src/runtime/CL/functions/CLPoolingLayer.cpp b/src/runtime/CL/functions/CLPoolingLayer.cpp
index 2cb7d63aa8..6ca1a33b0c 100644
--- a/src/runtime/CL/functions/CLPoolingLayer.cpp
+++ b/src/runtime/CL/functions/CLPoolingLayer.cpp
@@ -39,3 +39,8 @@ void CLPoolingLayer::configure(ICLTensor *input, ICLTensor *output, const Poolin
BorderMode border_mode = (PoolingType::MAX == pool_info.pool_type()) ? BorderMode::REPLICATE : BorderMode::CONSTANT;
_border_handler.configure(input, _kernel->border_size(), border_mode, PixelValue(0));
}
+
+Error CLPoolingLayer::validate(const ITensorInfo *input, const ITensorInfo *output, const PoolingLayerInfo &pool_info)
+{
+ return CLPoolingLayerKernel::validate(input, output, pool_info);
+} \ No newline at end of file
diff --git a/tests/validation/CL/PoolingLayer.cpp b/tests/validation/CL/PoolingLayer.cpp
index 87b86fedf2..7038f2c34e 100644
--- a/tests/validation/CL/PoolingLayer.cpp
+++ b/tests/validation/CL/PoolingLayer.cpp
@@ -61,6 +61,38 @@ constexpr AbsoluteTolerance<float> tolerance_qs16(6); /**< Tolerance value f
TEST_SUITE(CL)
TEST_SUITE(PoolingLayer)
+// *INDENT-OFF*
+// clang-format off
+DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(
+ framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QS8, 4),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QS16, 11),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0),
+ }),
+ framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(25U, 11U, 2U), 1, DataType::F16, 0),
+ TensorInfo(TensorShape(25U, 11U, 2U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 11U, 2U), 1, DataType::QS8, 5),
+ TensorInfo(TensorShape(25U, 11U, 2U), 1, DataType::QS16, 11),
+ TensorInfo(TensorShape(30U, 11U, 2U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 16U, 2U), 1, DataType::F32, 0),
+ })),
+ framework::dataset::make("PoolInfo", { PoolingLayerInfo(PoolingType::AVG, 3, PadStrideInfo(1, 1, 0, 0)),
+ PoolingLayerInfo(PoolingType::AVG, 3, PadStrideInfo(1, 1, 0, 0)),
+ PoolingLayerInfo(PoolingType::AVG, 3, PadStrideInfo(1, 1, 0, 0)),
+ PoolingLayerInfo(PoolingType::AVG, 3, PadStrideInfo(1, 1, 0, 0)),
+ PoolingLayerInfo(PoolingType::AVG, 2, PadStrideInfo(1, 1, 2, 0)),
+ PoolingLayerInfo(PoolingType::AVG, 2, PadStrideInfo(1, 1, 0, 2)),
+ })),
+ framework::dataset::make("Expected", { true, false, true, false, true, true})),
+ input_info, output_info, pool_info, expected)
+{
+ ARM_COMPUTE_EXPECT(bool(CLPoolingLayer::validate(&input_info, &output_info, pool_info)) == expected, framework::LogLevel::ERRORS);
+}
+// clang-format on
+// *INDENT-ON*
+
template <typename T>
using CLPoolingLayerFixture = PoolingLayerValidationFixture<CLTensor, CLAccessor, CLPoolingLayer, T>;
diff --git a/utils/TypePrinter.h b/utils/TypePrinter.h
index 4fd3c0c027..d956d9ca01 100644
--- a/utils/TypePrinter.h
+++ b/utils/TypePrinter.h
@@ -27,6 +27,7 @@
#include "arm_compute/core/Dimensions.h"
#include "arm_compute/core/Error.h"
#include "arm_compute/core/Strides.h"
+#include "arm_compute/core/TensorInfo.h"
#include "arm_compute/core/Types.h"
#include "tests/Types.h"
@@ -553,6 +554,17 @@ inline ::std::ostream &operator<<(::std::ostream &os, const InterpolationPolicy
return os;
}
+/** Formatted output of the TensorInfo type. */
+inline std::string to_string(const TensorInfo &info)
+{
+ std::stringstream str;
+ str << "{Shape=" << info.tensor_shape() << ","
+ << "Type=" << info.data_type() << ","
+ << "Channels=" << info.num_channels() << ","
+ << "FixedPointPos=" << info.fixed_point_position() << "}";
+ return str.str();
+}
+
//FIXME: Check why this doesn't work and the TensorShape and Coordinates overload are needed
template <typename T>
inline std::string to_string(const Dimensions<T> &dimensions)