Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 20 additions & 36 deletions include/xsimd/arch/common/xsimd_common_math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,62 +46,46 @@ namespace xsimd
}

// avg
namespace detail
template <class A, class T>
XSIMD_INLINE batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, requires_arch<common>) noexcept
{
template <class A, class T>
XSIMD_INLINE batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, std::true_type, std::false_type) noexcept
if constexpr (std::is_integral_v<T>)
{
return (x & y) + ((x ^ y) >> 1);
}

template <class A, class T>
XSIMD_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<std::make_unsigned_t<T>>(t);
auto avg = t + (bitwise_cast<T>(t_u >> (8 * sizeof(T) - 1)) & (x ^ y));
return avg;
if constexpr (std::is_signed_v<T>)
{
// 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<std::make_unsigned_t<T>>(t);
return t + (bitwise_cast<T>(t_u >> (8 * sizeof(T) - 1)) & (x ^ y));
}
else
{
return (x & y) + ((x ^ y) >> 1);
}
}

template <class A, class T>
XSIMD_INLINE batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, std::false_type, std::true_type) noexcept
else
{
return (x + y) / 2;
}
}

template <class A, class T>
XSIMD_INLINE batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, requires_arch<common>) 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>
XSIMD_INLINE batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, requires_arch<common>) noexcept
{
template <class A, class T>
XSIMD_INLINE batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, std::true_type) noexcept
if constexpr (std::is_integral_v<T>)
{
constexpr unsigned shift = 8 * sizeof(T) - 1;
auto adj = std::is_signed_v<T> ? ((x ^ y) & 0x1) : (((x ^ y) << shift) >> shift);
return ::xsimd::kernel::avg(x, y, A {}) + adj;
}

template <class A, class T>
XSIMD_INLINE batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, std::false_type) noexcept
else
{
return ::xsimd::kernel::avg(x, y, A {});
}
}

template <class A, class T>
XSIMD_INLINE batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, requires_arch<common>) noexcept
{
return detail::avgr(x, y, typename std::is_integral<T>::type {});
}

// batch_cast
template <class A, class T>
XSIMD_INLINE batch<T, A> batch_cast(batch<T, A> const& self, batch<T, A> const&, requires_arch<common>) noexcept
Expand Down
2 changes: 1 addition & 1 deletion include/xsimd/arch/xsimd_rvv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ namespace xsimd
}

// mul_hi
template <class A, class T, typename std::enable_if<std::is_integral_v<T>, int>::type = 0>
template <class A, class T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
XSIMD_INLINE batch<T, A> mul_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<rvv>) noexcept
{
return detail_rvv::rvvmulh(lhs, rhs);
Expand Down
18 changes: 10 additions & 8 deletions include/xsimd/arch/xsimd_scalar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1081,14 +1081,16 @@ namespace xsimd

namespace detail
{
#define XSIMD_HASSINCOS_TRAIT(func) \
template <class S> \
struct has##func \
{ \
template <class T> \
static XSIMD_INLINE auto get(T* ptr) -> decltype(func(std::declval<T>(), std::declval<T*>(), std::declval<T*>()), std::true_type {}); \
static XSIMD_INLINE std::false_type get(...); \
static constexpr bool value = decltype(get((S*)nullptr))::value; \
#define XSIMD_HASSINCOS_TRAIT(func) \
template <class T, class = void> \
struct has##func : std::false_type \
{ \
}; \
\
template <class T> \
struct has##func<T, std::void_t<decltype(func(std::declval<T>(), std::declval<T*>(), std::declval<T*>()))>> \
: std::true_type \
{ \
}

#define XSIMD_HASSINCOS(func, T) has##func<T>::value
Expand Down
2 changes: 1 addition & 1 deletion include/xsimd/arch/xsimd_sve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ namespace xsimd
}

// mul_hi
template <class A, class T, typename std::enable_if<std::is_integral_v<T>, int>::type = 0>
template <class A, class T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
XSIMD_INLINE batch<T, A> mul_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<sve>) noexcept
{
return svmulh_x(detail_sve::ptrue<T>(), lhs, rhs);
Expand Down
2 changes: 1 addition & 1 deletion include/xsimd/arch/xsimd_vsx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ namespace xsimd
template <>
struct builtin_scalar<char>
{
using type = typename std::conditional<std::is_signed_v<char>, signed char, unsigned char>::type;
using type = std::conditional_t<std::is_signed_v<char>, signed char, unsigned char>;
};

template <typename T>
Expand Down
10 changes: 5 additions & 5 deletions include/xsimd/arch/xsimd_vxe.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ namespace xsimd
template <>
struct builtin_scalar<char>
{
using type = typename std::conditional<std::is_signed_v<char>, signed char, unsigned char>::type;
using type = std::conditional_t<std::is_signed_v<char>, signed char, unsigned char>;
};

template <typename T>
Expand Down Expand Up @@ -249,7 +249,7 @@ namespace xsimd
}

// abs
template <class A, class T, class = typename std::enable_if<std::is_signed_v<T>, void>::type>
template <class A, class T, class = std::enable_if_t<std::is_signed_v<T>, void>>
XSIMD_INLINE batch<T, A> abs(batch<T, A> const& self, requires_arch<vxe>) noexcept
{
return vec_abs(self.data);
Expand Down Expand Up @@ -438,7 +438,7 @@ namespace xsimd
v2di sum = (v2di)self.data + shifted;
return (int64_t)sum[0];
}
template <class A, class T, class = typename std::enable_if<std::is_integral_v<T>, void>::type>
template <class A, class T, class = std::enable_if_t<std::is_integral_v<T>, void>>
XSIMD_INLINE T reduce_add(batch<T, A> const& self, requires_arch<vxe>) noexcept
{
if constexpr (sizeof(T) == 4)
Expand Down Expand Up @@ -735,13 +735,13 @@ namespace xsimd
return vec_mergeh(self.data, other.data);
}
// bitwise_rshift
template <class A, class T, class = typename std::enable_if<std::is_integral_v<T>, void>::type>
template <class A, class T, class = std::enable_if_t<std::is_integral_v<T>, void>>
XSIMD_INLINE batch<T, A> bitwise_rshift(batch<T, A> const& self, int32_t other, requires_arch<vxe>) noexcept
{
return self.data >> other;
}
// bitwise_lshift
template <class A, class T, class = typename std::enable_if<std::is_integral_v<T>, void>::type>
template <class A, class T, class = std::enable_if_t<std::is_integral_v<T>, void>>
XSIMD_INLINE batch<T, A> bitwise_lshift(batch<T, A> const& self, int32_t other, requires_arch<vxe>) noexcept
{
return self.data << other;
Expand Down
16 changes: 3 additions & 13 deletions include/xsimd/types/xsimd_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,24 +329,14 @@ namespace xsimd

namespace detail
{
template <bool...>
struct bool_pack;

template <bool... bs>
using all_true = std::is_same<
bool_pack<bs..., true>, bool_pack<true, bs...>>;

template <typename T, typename... Args>
using is_all_convertible = all_true<std::is_convertible_v<Args, T>...>;

template <typename T, std::size_t N, typename... Args>
using is_array_initializer = std::enable_if<
(sizeof...(Args) == N) && is_all_convertible<T, Args...>::value>;
inline constexpr bool is_all_convertible_v = std::conjunction_v<std::is_convertible<Args, T>...>;

// Check that a variadic argument pack is a list of N values of type T,
// as usable for instantiating a value of type std::array<T, N>.
template <typename T, std::size_t N, typename... Args>
using is_array_initializer_t = typename is_array_initializer<T, N, Args...>::type;
using is_array_initializer_t = std::enable_if_t<
(sizeof...(Args) == N) && is_all_convertible_v<T, Args...>>;
}

/**************
Expand Down
Loading