summaryrefslogtreecommitdiffstats
path: root/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp')
-rw-r--r--third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp59
1 files changed, 58 insertions, 1 deletions
diff --git a/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp b/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp
index 8fa887dc57..7bcc4da241 100644
--- a/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp
+++ b/third_party/xsimd/include/xsimd/arch/generic/xsimd_generic_math.hpp
@@ -26,7 +26,7 @@ namespace xsimd
using namespace types;
// abs
- template <class A, class T, class /*=typename std::enable_if<std::is_integral<T>::value, void>::type*/>
+ template <class A, class T, class>
inline batch<T, A> abs(batch<T, A> const& self, requires_arch<generic>) noexcept
{
if (std::is_unsigned<T>::value)
@@ -45,6 +45,63 @@ namespace xsimd
return hypot(z.real(), z.imag());
}
+ // avg
+ namespace detail
+ {
+ template <class A, class T>
+ inline batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, std::true_type, std::false_type) noexcept
+ {
+ return (x & y) + ((x ^ y) >> 1);
+ }
+
+ template <class A, class T>
+ inline batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, std::true_type, std::true_type) noexcept
+ {
+ // Inspired by
+ // https://stackoverflow.com/questions/5697500/take-the-average-of-two-signed-numbers-in-c
+ auto t = (x & y) + ((x ^ y) >> 1);
+ auto t_u = bitwise_cast<typename std::make_unsigned<T>::type>(t);
+ auto avg = t + (bitwise_cast<T>(t_u >> (8 * sizeof(T) - 1)) & (x ^ y));
+ return avg;
+ }
+
+ template <class A, class T>
+ inline batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, std::false_type, std::true_type) noexcept
+ {
+ return (x + y) / 2;
+ }
+ }
+
+ template <class A, class T>
+ inline batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, requires_arch<generic>) noexcept
+ {
+ return detail::avg(x, y, typename std::is_integral<T>::type {}, typename std::is_signed<T>::type {});
+ }
+
+ // avgr
+ namespace detail
+ {
+ template <class A, class T>
+ inline batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, std::true_type) noexcept
+ {
+ constexpr unsigned shift = 8 * sizeof(T) - 1;
+ auto adj = std::is_signed<T>::value ? ((x ^ y) & 0x1) : (((x ^ y) << shift) >> shift);
+ return ::xsimd::kernel::avg(x, y, A {}) + adj;
+ }
+
+ template <class A, class T>
+ inline batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, std::false_type) noexcept
+ {
+ return ::xsimd::kernel::avg(x, y, A {});
+ }
+ }
+
+ template <class A, class T>
+ inline batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, requires_arch<generic>) noexcept
+ {
+ return detail::avgr(x, y, typename std::is_integral<T>::type {});
+ }
+
// batch_cast
template <class A, class T>
inline batch<T, A> batch_cast(batch<T, A> const& self, batch<T, A> const&, requires_arch<generic>) noexcept