diff options
Diffstat (limited to 'support')
-rw-r--r-- | support/AclRequires.h (renamed from support/Requires.h) | 11 | ||||
-rw-r--r-- | support/BUILD.bazel | 28 | ||||
-rw-r--r-- | support/Bfloat16.h | 47 | ||||
-rw-r--r-- | support/Cast.h | 4 | ||||
-rw-r--r-- | support/DeepCopy.h | 187 | ||||
-rw-r--r-- | support/Half.h | 9 | ||||
-rw-r--r-- | support/Iterable.h | 3 | ||||
-rw-r--r-- | support/Mutex.h | 20 | ||||
-rw-r--r-- | support/Random.h | 7 | ||||
-rw-r--r-- | support/Rounding.h | 11 | ||||
-rw-r--r-- | support/SaturateCast.h | 1 | ||||
-rw-r--r-- | support/Semaphore.h | 16 | ||||
-rw-r--r-- | support/StringSupport.h | 28 | ||||
-rw-r--r-- | support/ToolchainSupport.h | 76 |
14 files changed, 346 insertions, 102 deletions
diff --git a/support/Requires.h b/support/AclRequires.h index 21c98ca766..1c20f7fbc3 100644 --- a/support/Requires.h +++ b/support/AclRequires.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Arm Limited. + * Copyright (c) 2018-2021, 2023 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -21,15 +21,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef ARM_COMPUTE_UTILS_REQUIRES_H -#define ARM_COMPUTE_UTILS_REQUIRES_H +#ifndef ARM_COMPUTE_UTILS_ACLREQUIRES_H +#define ARM_COMPUTE_UTILS_ACLREQUIRES_H namespace arm_compute { namespace utils { -namespace requires -{ // *INDENT-OFF* // clang-format off namespace detail @@ -42,10 +40,9 @@ enum class enabler /** Requirements as template */ #define ARM_COMPUTE_REQUIRES_T(...) template <bool Cond = (__VA_ARGS__), typename std::enable_if<Cond, int>::type = 0> /** Requirements as template argument */ -#define ARM_COMPUTE_REQUIRES_TA(...) typename = typename std::enable_if<(__VA_ARGS__), arm_compute::utils::requires::detail::enabler>::type +#define ARM_COMPUTE_REQUIRES_TA(...) typename = typename std::enable_if<(__VA_ARGS__), arm_compute::utils::detail::enabler>::type // clang-format on // *INDENT-ON* -} // namespace requires } // namespace utils } // namespace arm_compute #endif /*ARM_COMPUTE_UTILS_REQUIRES_H */ diff --git a/support/BUILD.bazel b/support/BUILD.bazel new file mode 100644 index 0000000000..c2173d45b2 --- /dev/null +++ b/support/BUILD.bazel @@ -0,0 +1,28 @@ +# Copyright (c) 2023 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. + +cc_library( + name = "support", + hdrs = glob(["*.h"]), + visibility = ["//visibility:public"], + deps = ["//include"], +) diff --git a/support/Bfloat16.h b/support/Bfloat16.h index 173f2d16e2..02772898a8 100644 --- a/support/Bfloat16.h +++ b/support/Bfloat16.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 Arm Limited. + * Copyright (c) 2020-2022,2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -21,12 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef ARM_COMPUTE_BFLOAT16_H -#define ARM_COMPUTE_BFLOAT16_H +#ifndef ACL_SUPPORT_BFLOAT16_H +#define ACL_SUPPORT_BFLOAT16_H #include <cstdint> #include <cstring> - +#include <ostream> namespace arm_compute { namespace @@ -40,25 +40,24 @@ namespace inline uint16_t float_to_bf16(const float v) { const uint32_t *fromptr = reinterpret_cast<const uint32_t *>(&v); -#if defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16) +#if defined(ARM_COMPUTE_ENABLE_BF16) uint16_t res; - __asm __volatile( - "ldr s0, [%[fromptr]]\n" - ".inst 0x1e634000\n" // BFCVT h0, s0 - "str h0, [%[toptr]]\n" - : - : [fromptr] "r"(fromptr), [toptr] "r"(&res) - : "v0", "memory"); -#else /* defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16) */ + __asm __volatile("ldr s0, [%[fromptr]]\n" + ".inst 0x1e634000\n" // BFCVT h0, s0 + "str h0, [%[toptr]]\n" + : + : [fromptr] "r"(fromptr), [toptr] "r"(&res) + : "v0", "memory"); +#else /* defined(ARM_COMPUTE_ENABLE_BF16) */ uint16_t res = (*fromptr >> 16); const uint16_t error = (*fromptr & 0x0000ffff); uint16_t bf_l = res & 0x0001; - if((error > 0x8000) || ((error == 0x8000) && (bf_l != 0))) + if ((error > 0x8000) || ((error == 0x8000) && (bf_l != 0))) { res += 1; } -#endif /* defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16) */ +#endif /* defined(ARM_COMPUTE_ENABLE_BF16) */ return res; } @@ -75,23 +74,21 @@ inline float bf16_to_float(const uint16_t &v) memcpy(&fp, &lv, sizeof(lv)); return fp; } -} +} // namespace /** Brain floating point representation class */ class bfloat16 final { public: /** Default Constructor */ - bfloat16() - : value(0) + bfloat16() : value(0) { } /** Constructor * * @param[in] v Floating-point value */ - explicit bfloat16(float v) - : value(float_to_bf16(v)) + bfloat16(float v) : value(float_to_bf16(v)) { } /** Assignment operator @@ -134,8 +131,16 @@ public: return val; } + bfloat16 &operator+=(float v) + { + value = float_to_bf16(bf16_to_float(value) + v); + return *this; + } + + friend std::ostream &operator<<(std::ostream &os, const bfloat16 &arg); + private: uint16_t value; }; } // namespace arm_compute -#endif /* ARM_COMPUTE_BFLOAT16_H */ +#endif // ACL_SUPPORT_BFLOAT16_H diff --git a/support/Cast.h b/support/Cast.h index 53d5f68065..5fd763690b 100644 --- a/support/Cast.h +++ b/support/Cast.h @@ -46,7 +46,7 @@ namespace cast template <typename Target, typename Source> inline Target polymorphic_cast(Source *v) { - if(dynamic_cast<Target>(v) == nullptr) + if (dynamic_cast<Target>(v) == nullptr) { ARM_COMPUTE_THROW(std::bad_cast()); } @@ -86,7 +86,7 @@ inline Target polymorphic_downcast(Source *v) template <typename Target, typename Source, typename Deleter> std::unique_ptr<Target, Deleter> polymorphic_cast_unique_ptr(std::unique_ptr<Source, Deleter> &&v) { - if(dynamic_cast<Target *>(v.get()) == nullptr) + if (dynamic_cast<Target *>(v.get()) == nullptr) { ARM_COMPUTE_THROW(std::bad_cast()); } diff --git a/support/DeepCopy.h b/support/DeepCopy.h new file mode 100644 index 0000000000..c0279284c0 --- /dev/null +++ b/support/DeepCopy.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2022 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_MISC_ITERABLE_H +#define ARM_COMPUTE_MISC_ITERABLE_H +namespace arm_compute +{ +namespace utils +{ +namespace memory +{ +namespace +{ +/** Default polymorphic deep copy function, used by deep_unique_ptr + * + * @param ptr Potentially polymorphic object to be deep copied + * @return template <typename Base, typename Derived>* + */ +template <typename Base, typename Derived> +Base *default_polymorphic_copy(const Base *ptr) +{ + static_assert(std::is_base_of<Base, Derived>::value, "Derived is not a specialization of Base"); + if (ptr == nullptr) + { + return nullptr; + } + return new Derived(*static_cast<const Derived *>(ptr)); +} +} // namespace + +/** A deep-copying unique pointer that also supports polymorphic cloning behavior + * + * @note The == operator compares the dereferenced value instead of the pointer itself. + * + * @tparam Base Base type + */ +template <typename Base> +class deep_unique_ptr +{ +public: + using CopyFunc = std::function<Base *(const Base *)>; + + deep_unique_ptr(std::nullptr_t val = nullptr) noexcept : _val{val}, _copy{} + { + } + template <typename Derived, typename CopyFuncDerived> + deep_unique_ptr(Derived *value, const CopyFuncDerived ©) noexcept : _val{value}, _copy{std::move(copy)} + { + static_assert(std::is_base_of<Base, Derived>::value, "Derived is not a specialization of Base"); + static_assert(std::is_constructible<CopyFunc, CopyFuncDerived>::value, + "CopyFuncDerived is not valid for a copy functor"); + } + + deep_unique_ptr(const deep_unique_ptr<Base> &ptr) : deep_unique_ptr(ptr.clone()) + { + } + deep_unique_ptr &operator=(const deep_unique_ptr<Base> &ptr) + { + deep_unique_ptr<Base> tmp(ptr); + swap(*this, tmp); + return *this; + } + + deep_unique_ptr(deep_unique_ptr<Base> &&ptr) = default; + deep_unique_ptr &operator=(deep_unique_ptr<Base> &&ptr) = default; + ~deep_unique_ptr() = default; + friend void swap(deep_unique_ptr &ptr0, deep_unique_ptr<Base> &ptr1) noexcept + { + using std::swap; + swap(ptr0._val, ptr1._val); + swap(ptr0._copy, ptr1._copy); + } + Base &operator*() noexcept + { + return *_val; + } + + const Base &operator*() const noexcept + { + return *_val; + } + + Base *operator->() noexcept + { + return _val.operator->(); + } + + const Base *operator->() const noexcept + { + return _val.operator->(); + } + + Base *get() noexcept + { + return _val.get(); + } + const Base *get() const noexcept + { + return _val.get(); + } + + explicit operator bool() const noexcept + { + return static_cast<bool>(_val); + } + + bool operator==(const deep_unique_ptr<Base> &rhs) const + { + if (rhs.get() == nullptr && _val == nullptr) + { + return true; + } + else if (rhs.get() == nullptr || _val == nullptr) + { + return false; + } + else + { + return (*_val == *rhs); + } + } + +private: + deep_unique_ptr clone() const + { + return {_copy(_val.get()), CopyFunc(_copy)}; + } + std::unique_ptr<Base> _val{nullptr}; + CopyFunc _copy{}; +}; + +/** Utility function to create a polymorphic deep-copying unique pointer + * + * @tparam Base + * @tparam Derived + * @tparam CopyFunc + * @param temp + * @param copy + * @return deep_unique_ptr<Base> + */ +template <typename Base, typename Derived, typename CopyFunc> +deep_unique_ptr<Base> make_deep_unique(Derived &&temp, CopyFunc copy) +{ + return {new Derived(std::move(temp)), CopyFunc{std::move(copy)}}; +} + +template <typename Base, typename Derived> +deep_unique_ptr<Base> make_deep_unique(Derived &&temp) +{ + static_assert(std::is_base_of<Base, Derived>::value, "Derived is not a specialization of Base"); + + return make_deep_unique<Base, Derived>(std::move(temp), default_polymorphic_copy<Base, Derived>); +} + +template <typename Base, typename Derived, typename... Args> +deep_unique_ptr<Base> make_deep_unique(Args &&...args) +{ + static_assert(std::is_constructible<Derived, Args...>::value, "Cannot instantiate Derived from arguments"); + + return make_deep_unique<Base, Derived>(std::move(Derived{std::forward<Args>(args)...})); +} + +} // namespace memory +} // namespace utils +} // namespace arm_compute +#endif // ARM_COMPUTE_MISC_ITERABLE_H diff --git a/support/Half.h b/support/Half.h index 5bea26c6e8..f5c27da2d3 100644 --- a/support/Half.h +++ b/support/Half.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Arm Limited. + * Copyright (c) 2017, 2021 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -24,13 +24,12 @@ #ifndef __ARM_COMPUTE_HALF_H__ #define __ARM_COMPUTE_HALF_H__ -#if(__ANDROID__ || BARE_METAL) -// Android toolchain is broken and doesn't support all CPP11 math functions. +#if (BARE_METAL) #define HALF_ENABLE_CPP11_CMATH 0 -#endif /* __ANDROID__ || BARE_METAL */ +#endif /* BARE_METAL */ // Set style to round to nearest -#define HALF_ROUND_STYLE 1 +#define HALF_ROUND_STYLE 1 #define HALF_ROUND_TIES_TO_EVEN 1 #include "half/half.hpp" diff --git a/support/Iterable.h b/support/Iterable.h index a0bafaf4ce..8d99e70196 100644 --- a/support/Iterable.h +++ b/support/Iterable.h @@ -44,8 +44,7 @@ public: * * @param[in] it Value to reverse iterate on */ - explicit reverse_iterable(T &it) - : _it(it) + explicit reverse_iterable(T &it) : _it(it) { } diff --git a/support/Mutex.h b/support/Mutex.h index 6e68fa5248..9c2b55c3ac 100644 --- a/support/Mutex.h +++ b/support/Mutex.h @@ -50,10 +50,10 @@ public: ~Mutex() = default; /** Lock */ - void lock() {}; + void lock(){}; /** Unlock */ - void unlock() {}; + void unlock(){}; /** Try the lock. * @@ -73,8 +73,7 @@ public: typedef Mutex mutex_type; public: - explicit lock_guard(Mutex &m_) - : m(m_) + explicit lock_guard(Mutex &m_) : m(m_) { } ~lock_guard() @@ -97,15 +96,14 @@ public: unique_lock() noexcept : m(nullptr) { } - explicit unique_lock(mutex_type &m) - : m(&m) + explicit unique_lock(mutex_type &m) : m(&m) { } - unique_lock(const unique_lock &) = delete; - unique_lock(unique_lock &&) = default; + unique_lock(const unique_lock &) = delete; + unique_lock(unique_lock &&) = default; unique_lock &operator=(const unique_lock &) = delete; - unique_lock &operator=(unique_lock &&) = default; - ~unique_lock() = default; + unique_lock &operator=(unique_lock &&) = default; + ~unique_lock() = default; void lock() { } @@ -121,5 +119,5 @@ private: mutex_type *m; }; #endif /* NO_MULTI_THREADING */ -} +} // namespace arm_compute #endif /* __ARM_COMPUTE_MUTEX_H__ */ diff --git a/support/Random.h b/support/Random.h index 7658e6d529..1a804d3290 100644 --- a/support/Random.h +++ b/support/Random.h @@ -25,6 +25,7 @@ #define ARM_COMPUTE_MISC_RANDOM_H #include "arm_compute/core/Error.h" + #include "utils/Utils.h" #include <random> @@ -47,7 +48,9 @@ public: static constexpr bool is_fp_16bit = std::is_same<T, half>::value || std::is_same<T, bfloat16>::value; static constexpr bool is_integral = std::is_integral<T>::value && !is_fp_16bit; - using fp_dist = typename std::conditional<is_fp_16bit, arm_compute::utils::uniform_real_distribution_16bit<T>, std::uniform_real_distribution<T>>::type; + using fp_dist = typename std::conditional<is_fp_16bit, + arm_compute::utils::uniform_real_distribution_16bit<T>, + std::uniform_real_distribution<T>>::type; using DT = typename std::conditional<is_integral, std::uniform_int_distribution<T>, fp_dist>::type; using result_type = T; using range_pair = std::pair<result_type, result_type>; @@ -62,7 +65,7 @@ public: : _distributions(), _selector() { result_type clow = low; - for(const auto &erange : exclude_ranges) + for (const auto &erange : exclude_ranges) { result_type epsilon = is_integral ? result_type(1) : result_type(std::numeric_limits<T>::epsilon()); diff --git a/support/Rounding.h b/support/Rounding.h index 47c8f76834..5691a6680b 100644 --- a/support/Rounding.h +++ b/support/Rounding.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Arm Limited. + * Copyright (c) 2018-2021, 2023 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -26,7 +26,8 @@ #include "arm_compute/core/Error.h" #include "arm_compute/core/utils/misc/Traits.h" -#include "support/Requires.h" + +#include "support/AclRequires.h" #include "support/ToolchainSupport.h" #include <cmath> @@ -153,10 +154,10 @@ inline T round_half_even(T value, T epsilon = std::numeric_limits<T>::epsilon()) T ipart = 0; std::modf(positive_value, &ipart); // If 'value' is exactly halfway between two integers - if(std::abs(positive_value - (ipart + 0.5f)) < epsilon) + if (std::abs(positive_value - (ipart + 0.5f)) < epsilon) { // If 'ipart' is even then return 'ipart' - if(std::fmod(ipart, 2.f) < epsilon) + if (std::fmod(ipart, 2.f) < epsilon) { return support::cpp11::copysign(ipart, value); } @@ -179,7 +180,7 @@ inline T round_half_even(T value, T epsilon = std::numeric_limits<T>::epsilon()) template <typename T, ARM_COMPUTE_REQUIRES_TA(traits::is_floating_point<T>::value)> inline T round(T value, RoundingMode rounding_mode) { - switch(rounding_mode) + switch (rounding_mode) { case RoundingMode::TO_ZERO: return round_to_zero(value); diff --git a/support/SaturateCast.h b/support/SaturateCast.h index a9982d8e96..7af9f983ed 100644 --- a/support/SaturateCast.h +++ b/support/SaturateCast.h @@ -26,6 +26,7 @@ #include "arm_compute/core/utils/misc/Traits.h" #include "arm_compute/core/utils/misc/Utility.h" + #include "support/Rounding.h" namespace arm_compute diff --git a/support/Semaphore.h b/support/Semaphore.h index e182b53a2d..f44179332b 100644 --- a/support/Semaphore.h +++ b/support/Semaphore.h @@ -24,8 +24,9 @@ #ifndef __ARM_COMPUTE_UTILS_SEMAMPHORE_H__ #define __ARM_COMPUTE_UTILS_SEMAMPHORE_H__ -#include "Mutex.h" #include "support/Mutex.h" + +#include "Mutex.h" #include <condition_variable> namespace arm_compute @@ -39,8 +40,7 @@ public: * * @param[in] value Semaphore initial value */ - Semaphore(int value = 0) - : _value(value), _m(), _cv() + Semaphore(int value = 0) : _value(value), _m(), _cv() { } /** Signals a semaphore */ @@ -56,10 +56,7 @@ public: inline void wait() { std::unique_lock<std::mutex> lock(_m); - _cv.wait(lock, [this]() - { - return _value > 0; - }); + _cv.wait(lock, [this]() { return _value > 0; }); --_value; } @@ -73,8 +70,7 @@ private: class Semaphore { public: - Semaphore(int value = 0) - : _value(value) + Semaphore(int value = 0) : _value(value) { (void)_value; } @@ -93,5 +89,5 @@ private: int _value; }; #endif /* NO_MULTI_THREADING */ -} // arm_compute +} // namespace arm_compute #endif /* __ARM_COMPUTE_UTILS_SEMAMPHORE_H__ */ diff --git a/support/StringSupport.h b/support/StringSupport.h index 5e237c7dff..7d1b5e7778 100644 --- a/support/StringSupport.h +++ b/support/StringSupport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Arm Limited. + * Copyright (c) 2017-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -57,14 +57,14 @@ inline int stoi(const std::string &str, std::size_t *pos = 0, NumericBase base = assert(base == NumericBase::BASE_10 || base == NumericBase::BASE_16); unsigned int x; std::stringstream ss; - if(base == NumericBase::BASE_16) + if (base == NumericBase::BASE_16) { ss << std::hex; } ss << str; ss >> x; - if(pos) + if (pos) { std::string s; std::stringstream ss_p; @@ -93,14 +93,14 @@ inline unsigned long stoul(const std::string &str, std::size_t *pos = 0, Numeric assert(base == NumericBase::BASE_10 || base == NumericBase::BASE_16); std::stringstream stream; unsigned long value = 0; - if(base == NumericBase::BASE_16) + if (base == NumericBase::BASE_16) { stream << std::hex; } stream << str; stream >> value; - if(pos) + if (pos) { std::string s; std::stringstream ss_p; @@ -113,7 +113,7 @@ inline unsigned long stoul(const std::string &str, std::size_t *pos = 0, Numeric return value; } -#if(__ANDROID__ || BARE_METAL) +#if (__ANDROID__ || BARE_METAL) /** Convert integer and float values to string. * * @note This function implements the same behaviour as std::to_string. The @@ -124,13 +124,19 @@ inline unsigned long stoul(const std::string &str, std::size_t *pos = 0, Numeric * @return String representation of @p value. */ template <typename T, typename std::enable_if<std::is_arithmetic<typename std::decay<T>::type>::value, int>::type = 0> -inline std::string to_string(T && value) +inline std::string to_string(T &&value) { std::stringstream stream; stream << std::forward<T>(value); return stream.str(); } +// Specialization for const std::string& +inline std::string to_string(const std::string &value) +{ + return value; +} + /** Convert string values to float. * * @note This function implements the same behaviour as std::stof. The latter @@ -164,6 +170,12 @@ inline std::string to_string(T &&value) return ::std::to_string(std::forward<T>(value)); } +// Specialization for const std::string& +inline std::string to_string(const std::string &value) +{ + return value; +} + /** Convert string values to float. * * @note This function acts as a convenience wrapper around std::stof. The @@ -174,7 +186,7 @@ inline std::string to_string(T &&value) * @return Float representation of input string. */ template <typename... Ts> -int stof(Ts &&... args) +int stof(Ts &&...args) { return ::std::stof(std::forward<Ts>(args)...); } diff --git a/support/ToolchainSupport.h b/support/ToolchainSupport.h index d8c14411e8..accbb643c2 100644 --- a/support/ToolchainSupport.h +++ b/support/ToolchainSupport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2021 Arm Limited. + * Copyright (c) 2017-2023 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -21,8 +21,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef ARM_COMPUTE_SUPPORT_TOOLCHAINSUPPORT -#define ARM_COMPUTE_SUPPORT_TOOLCHAINSUPPORT +#ifndef ACL_SUPPORT_TOOLCHAINSUPPORT_H +#define ACL_SUPPORT_TOOLCHAINSUPPORT_H + +#include "support/Bfloat16.h" +#include "support/Half.h" #include <cassert> #include <cmath> @@ -33,24 +36,21 @@ #include <string> #include <type_traits> -#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC -#include <arm_neon.h> -#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC - -#include "support/Bfloat16.h" -#include "support/Half.h" - #ifndef M_PI #define M_PI (3.14159265358979323846) #endif // M_PI namespace arm_compute { +#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC +typedef __fp16 float16_t; +#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC + namespace support { namespace cpp11 { -#if(__ANDROID__ || BARE_METAL) +#if (__ANDROID__ || BARE_METAL) template <typename T> inline T nearbyint(T value) { @@ -129,11 +129,12 @@ inline T copysign(T x, T y) * * @return Result floating point value equal to (x*y) + z.c */ -template < typename T, typename = typename std::enable_if < std::is_floating_point<T>::value +template <typename T, + typename = typename std::enable_if<std::is_floating_point<T>::value #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC - || std::is_same<T, float16_t>::value + || std::is_same<T, float16_t>::value #endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC - >::type > + >::type> inline T fma(T x, T y, T z) { return ::fma(x, y, z); @@ -143,15 +144,15 @@ inline T fma(T x, T y, T z) * and writes the result to a character string buffer. * * @param[in] s Pointer to a character string to write to - * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator - * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data. + * @param[in] n Up to buf_size - 1 characters may be written, plus the null ending character + * @param[in] fmt Pointer to a null-ended multibyte string specifying how to interpret the data. * @param[in] args Arguments forwarded to snprintf. * * @return Number of characters that would have been written for a sufficiently large buffer - * if successful (not including the terminating null character), or a negative value if an error occurred. + * if successful (not including the ending null character), or a negative value if an error occurred. */ template <typename... Ts> -inline int snprintf(char *s, size_t n, const char *fmt, Ts &&... args) +inline int snprintf(char *s, size_t n, const char *fmt, Ts &&...args) { return ::snprintf(s, n, fmt, std::forward<Ts>(args)...); } @@ -183,8 +184,7 @@ inline T nearbyint(T value) template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type> inline T round(T value) { - //Workaround Valgrind's mismatches: when running from Valgrind the call to std::round(-4.500000) == -4.000000 instead of 5.00000 - return (value < 0.f) ? static_cast<int>(value - 0.5f) : static_cast<int>(value + 0.5f); + return std::round(value); } /** Round floating-point value with half value rounding away from zero and cast to long @@ -244,11 +244,12 @@ inline T copysign(T x, T y) * * @return Result floating point value equal to (x*y) + z. */ -template < typename T, typename = typename std::enable_if < std::is_floating_point<T>::value +template <typename T, + typename = typename std::enable_if<std::is_floating_point<T>::value #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC - || std::is_same<T, float16_t>::value + || std::is_same<T, float16_t>::value #endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC - >::type > + >::type> inline T fma(T x, T y, T z) { return std::fma(x, y, z); @@ -258,15 +259,15 @@ inline T fma(T x, T y, T z) * and writes the result to a character string buffer. * * @param[in] s Pointer to a character string to write to - * @param[in] n Up to buf_size - 1 characters may be written, plus the null terminator - * @param[in] fmt Pointer to a null-terminated multibyte string specifying how to interpret the data. + * @param[in] n Up to buf_size - 1 characters may be written, plus the null ending character + * @param[in] fmt Pointer to a null-ended multibyte string specifying how to interpret the data. * @param[in] args Arguments forwarded to std::snprintf. * * @return Number of characters that would have been written for a sufficiently large buffer - * if successful (not including the terminating null character), or a negative value if an error occurred. + * if successful (not including the ending null character), or a negative value if an error occurred. */ template <typename... Ts> -inline int snprintf(char *s, std::size_t n, const char *fmt, Ts &&... args) +inline int snprintf(char *s, std::size_t n, const char *fmt, Ts &&...args) { return std::snprintf(s, n, fmt, std::forward<Ts>(args)...); } @@ -297,7 +298,7 @@ inline bfloat16 lowest<bfloat16>() template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type> inline bool isfinite(T value) { - return std::isfinite(value); + return std::isfinite(static_cast<double>(value)); } inline bool isfinite(half_float::half value) @@ -309,7 +310,24 @@ inline bool isfinite(bfloat16 value) { return std::isfinite(float(value)); } + +// std::signbit +template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type> +inline bool signbit(T value) +{ + return std::signbit(static_cast<double>(value)); +} + +inline bool signbit(half_float::half value) +{ + return half_float::signbit(value); +} + +inline bool signbit(bfloat16 value) +{ + return std::signbit(float(value)); +} } // namespace cpp11 } // namespace support } // namespace arm_compute -#endif /* ARM_COMPUTE_SUPPORT_TOOLCHAINSUPPORT */ +#endif // ACL_SUPPORT_TOOLCHAINSUPPORT_H |