Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move self_leq to the is_less_equal callable #2054

Merged
merged 4 commits into from
Feb 3, 2025
Merged
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
14 changes: 8 additions & 6 deletions include/eve/arch/cpu/wide.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#include <eve/module/core/regular/shl.hpp>
#include <eve/module/core/regular/shr.hpp>
#include <eve/module/core/regular/is_greater.hpp>
#include <eve/module/core/regular/is_less.hpp>
#include <eve/module/core/regular/is_less_equal.hpp>
#include <eve/memory/soa_ptr.hpp>
#include <eve/traits/product_type.hpp>

Expand Down Expand Up @@ -953,32 +955,32 @@ namespace eve
}

//! @brief Element-wise less-or-equal comparison between eve::wide
friend EVE_FORCEINLINE auto operator<=(wide v, wide w) noexcept
friend EVE_FORCEINLINE auto operator<=(wide a, wide b) noexcept
#if !defined(EVE_DOXYGEN_INVOKED)
requires(supports_ordering_v<Type>)
#endif
{
return detail::self_leq(v, w);
return is_less_equal(a, b);
}

//! @brief Element-wise less-or-equal comparison between a eve::wide and a scalar
template<scalar_value S>
friend EVE_FORCEINLINE auto operator<=(wide v, S w) noexcept
friend EVE_FORCEINLINE auto operator<=(wide w, S s) noexcept
#if !defined(EVE_DOXYGEN_INVOKED)
requires(supports_ordering_v<Type>)
#endif
{
return v <= wide {w};
return is_less_equal(w, s);
}

//! @brief Element-wise less-or-equal comparison between a scalar and a eve::wide
template<scalar_value S>
friend EVE_FORCEINLINE auto operator<=(S v, wide w) noexcept
friend EVE_FORCEINLINE auto operator<=(S s, wide w) noexcept
#if !defined(EVE_DOXYGEN_INVOKED)
requires(supports_ordering_v<Type>)
#endif
{
return wide {v} <= w;
return is_less_equal(s, w);
}

//! Computes the logical negation of its parameter
Expand Down
33 changes: 0 additions & 33 deletions include/eve/detail/function/simd/arm/neon/friends.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,37 +94,4 @@ namespace eve::detail
else if constexpr( sizeof(T) == 8 )
return map([]<typename E>(E const& e, E const& f){ return as_logical_t<E>(e >= f); }, v, w);
}

template<typename T, typename N>
EVE_FORCEINLINE logical<wide<T,N>> self_leq(wide<T, N> v,wide<T, N> w) noexcept
requires arm_abi<abi_t<T, N>>
{
constexpr auto cat = categorize<wide<T, N>>();

if constexpr( cat == category::int32x4 ) return vcleq_s32(v, w);
else if constexpr( cat == category::int16x8 ) return vcleq_s16(v, w);
else if constexpr( cat == category::int8x16 ) return vcleq_s8(v, w);
else if constexpr( cat == category::uint32x4 ) return vcleq_u32(v, w);
else if constexpr( cat == category::uint16x8 ) return vcleq_u16(v, w);
else if constexpr( cat == category::uint8x16 ) return vcleq_u8(v, w);
else if constexpr( cat == category::float32x4) return vcleq_f32(v, w);
else if constexpr( cat == category::int32x2 ) return vcle_s32(v, w);
else if constexpr( cat == category::int16x4 ) return vcle_s16(v, w);
else if constexpr( cat == category::int8x8 ) return vcle_s8(v, w);
else if constexpr( cat == category::uint32x2 ) return vcle_u32(v, w);
else if constexpr( cat == category::uint16x4 ) return vcle_u16(v, w);
else if constexpr( cat == category::uint8x8 ) return vcle_u8(v, w);
else if constexpr( cat == category::float32x2) return vcle_f32(v, w);
else if constexpr( current_api >= asimd)
{
if constexpr( cat == category::float64x1) return vcle_f64(v, w);
else if constexpr( cat == category::int64x1) return vcle_s64(v, w);
else if constexpr( cat == category::uint64x1) return vcle_u64(v, w);
else if constexpr( cat == category::float64x2) return vcleq_f64(v, w);
else if constexpr( cat == category::int64x2) return vcleq_s64(v, w);
else if constexpr( cat == category::uint64x2) return vcleq_u64(v, w);
}
else if constexpr( sizeof(T) == 8 )
return map([]<typename E>(E const& e, E const& f){ return as_logical_t<E>(e <= f); }, v, w);
}
}
5 changes: 0 additions & 5 deletions include/eve/detail/function/simd/arm/sve/friends.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ EVE_FORCEINLINE auto
self_neq(wide<T, N> v, wide<T, N> w) noexcept -> as_logical_t<wide<T, N>>
requires sve_abi<abi_t<T, N>> { return svcmpne(sve_true<T>(), v, w); }

template<arithmetic_scalar_value T, typename N>
EVE_FORCEINLINE auto
self_leq(wide<T, N> v, wide<T, N> w) noexcept -> as_logical_t<wide<T, N>>
requires sve_abi<abi_t<T, N>> { return svcmple(sve_true<T>(), v, w); }

template<arithmetic_scalar_value T, typename N>
EVE_FORCEINLINE auto
self_geq(wide<T, N> v, wide<T, N> w) noexcept -> as_logical_t<wide<T, N>>
Expand Down
13 changes: 0 additions & 13 deletions include/eve/detail/function/simd/common/friends.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,6 @@ namespace eve::detail

//================================================================================================
// Ordering operators
template<simd_value Wide>
EVE_FORCEINLINE auto self_leq(Wide const& v,Wide const& w) noexcept
{
if constexpr( product_type<Wide> )
{
return convert(kumi::to_tuple(v) <= kumi::to_tuple(w), as_element<as_logical_t<Wide>>());
}
else
{
constexpr auto ge = []<typename E>(E const& e, E const& f) { return as_logical_t<E>(e <= f); };
return apply_over(ge, v, w);
}
}

template<simd_value Wide>
EVE_FORCEINLINE auto self_geq(Wide const& v,Wide const& w) noexcept
Expand Down
10 changes: 0 additions & 10 deletions include/eve/detail/function/simd/ppc/friends.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,4 @@ namespace eve::detail
else
return !(v < w);
}

template<arithmetic_scalar_value T, typename N>
EVE_FORCEINLINE auto self_leq(wide<T, N> const &v, wide<T, N> const &w) noexcept
requires ppc_abi<abi_t<T, N>>
{
if constexpr(std::is_floating_point_v<T>)
return logical<wide<T, N>>(vec_cmple(v.storage(), w.storage()));
else
return !(v > w);
}
}
31 changes: 0 additions & 31 deletions include/eve/detail/function/simd/riscv/friends.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,37 +44,6 @@ requires rvv_abi<abi_t<T, N>>
return self_geq_impl(lhs, rhs);
}

template<plain_scalar_value T, typename N, value U>
EVE_FORCEINLINE auto
self_leq_impl(wide<T, N> lhs, U rhs) noexcept -> logical<wide<T, N>>
requires rvv_abi<abi_t<T, N>> && (std::same_as<wide<T, N>, U> || scalar_value<U>)
{
if constexpr( scalar_value<U> && !std::same_as<T, U> ) return self_leq(lhs, static_cast<T>(rhs));
else
{
constexpr auto c = categorize<wide<T, N>>();
if constexpr( match(c, category::int_) ) return __riscv_vmsle(lhs, rhs, N::value);
else if constexpr( match(c, category::uint_) ) return __riscv_vmsleu(lhs, rhs, N::value);
else if constexpr( match(c, category::float_) ) return __riscv_vmfle(lhs, rhs, N::value);
}
}

template<plain_scalar_value T, typename N>
EVE_FORCEINLINE auto
self_leq(wide<T, N> lhs, wide<T, N> rhs) noexcept -> logical<wide<T, N>>
requires rvv_abi<abi_t<T, N>>
{
return self_leq_impl(lhs, rhs);
}

template<plain_scalar_value T, typename N>
EVE_FORCEINLINE auto
self_leq(wide<T, N> lhs, std::convertible_to<T> auto rhs) noexcept -> logical<wide<T, N>>
requires rvv_abi<abi_t<T, N>>
{
return self_leq_impl(lhs, rhs);
}

template<plain_scalar_value T, typename N, value U>
EVE_FORCEINLINE auto
self_eq_impl(wide<T, N> lhs, U rhs) noexcept -> logical<wide<T, N>>
Expand Down
51 changes: 0 additions & 51 deletions include/eve/detail/function/simd/x86/friends.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,55 +229,4 @@ EVE_FORCEINLINE as_logical_t<wide<T, N>>
else return !(v < w);
}
}

//================================================================================================
template<arithmetic_scalar_value T, typename N>
EVE_FORCEINLINE as_logical_t<wide<T, N>>
self_leq(wide<T, N> v, wide<T, N> w) noexcept requires x86_abi<abi_t<T, N>>
{
constexpr auto c = categorize<wide<T, N>>();
constexpr auto f = to_integer(cmp_flt::le_oq);

if constexpr( current_api >= avx512 )
{
if constexpr( c == category::float32x16 ) return mask16 {_mm512_cmp_ps_mask(v, w, f)};
else if constexpr( c == category::float32x8 ) return mask8 {_mm256_cmp_ps_mask(v, w, f)};
else if constexpr( c == category::float32x4 ) return mask8 {_mm_cmp_ps_mask(v, w, f)};
else if constexpr( c == category::float64x8 ) return mask8 {_mm512_cmp_pd_mask(v, w, f)};
else if constexpr( c == category::float64x4 ) return mask8 {_mm256_cmp_pd_mask(v, w, f)};
else if constexpr( c == category::float64x2 ) return mask8 {_mm_cmp_pd_mask(v, w, f)};
else if constexpr( c == category::uint64x8 ) return mask8 {_mm512_cmple_epu64_mask(v, w)};
else if constexpr( c == category::uint64x4 ) return mask8 {_mm256_cmple_epu64_mask(v, w)};
else if constexpr( c == category::uint64x2 ) return mask8 {_mm_cmple_epu64_mask(v, w)};
else if constexpr( c == category::uint32x16 ) return mask16 {_mm512_cmple_epu32_mask(v, w)};
else if constexpr( c == category::uint32x8 ) return mask8 {_mm256_cmple_epu32_mask(v, w)};
else if constexpr( c == category::uint32x4 ) return mask8 {_mm_cmple_epu32_mask(v, w)};
else if constexpr( c == category::uint16x32 ) return mask32 {_mm512_cmple_epu16_mask(v, w)};
else if constexpr( c == category::uint16x16 ) return mask16 {_mm256_cmple_epu16_mask(v, w)};
else if constexpr( c == category::uint16x8 ) return mask8 {_mm_cmple_epu16_mask(v, w)};
else if constexpr( c == category::uint8x64 ) return mask64 {_mm512_cmple_epu8_mask(v, w)};
else if constexpr( c == category::uint8x32 ) return mask32 {_mm256_cmple_epu8_mask(v, w)};
else if constexpr( c == category::uint8x16 ) return mask16 {_mm_cmple_epu8_mask(v, w)};
else if constexpr( c == category::int64x8 ) return mask8 {_mm512_cmple_epi64_mask(v, w)};
else if constexpr( c == category::int64x4 ) return mask8 {_mm256_cmple_epi64_mask(v, w)};
else if constexpr( c == category::int64x2 ) return mask8 {_mm_cmple_epi64_mask(v, w)};
else if constexpr( c == category::int32x16 ) return mask16 {_mm512_cmple_epi32_mask(v, w)};
else if constexpr( c == category::int32x8 ) return mask8 {_mm256_cmple_epi32_mask(v, w)};
else if constexpr( c == category::int32x4 ) return mask8 {_mm_cmple_epi32_mask(v, w)};
else if constexpr( c == category::int16x32 ) return mask32 {_mm512_cmple_epi16_mask(v, w)};
else if constexpr( c == category::int16x16 ) return mask16 {_mm256_cmple_epi16_mask(v, w)};
else if constexpr( c == category::int16x8 ) return mask8 {_mm_cmple_epi16_mask(v, w)};
else if constexpr( c == category::int8x64 ) return mask64 {_mm512_cmple_epi8_mask(v, w)};
else if constexpr( c == category::int8x32 ) return mask32 {_mm256_cmple_epi8_mask(v, w)};
else if constexpr( c == category::int8x16 ) return mask16 {_mm_cmple_epi8_mask(v, w)};
}
else
{
if constexpr( c == category::float32x8 ) return _mm256_cmp_ps(v, w, f);
else if constexpr( c == category::float64x4 ) return _mm256_cmp_pd(v, w, f);
else if constexpr( c == category::float32x4 ) return _mm_cmple_ps(v, w);
else if constexpr( c == category::float64x2 ) return _mm_cmple_pd(v, w);
else return !(v > w);
}
}
}
4 changes: 2 additions & 2 deletions include/eve/module/core/regular/impl/is_less.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
//==================================================================================================
#pragma once

#include <eve/module/core/regular/if_else.hpp>
#include <eve/module/core/regular/fam.hpp>
#include <eve/module/core/regular/prev.hpp>
#include <eve/module/core/regular/max.hpp>
#include <eve/traits/as_logical.hpp>

namespace eve::detail
{
Expand All @@ -31,7 +31,7 @@ namespace eve::detail
else
{
if constexpr (scalar_value<T>) return as_logical_t<T>(a < b);
else return map([](auto e, auto f) { return e < f; }, a, b);
else return map([]<typename E>(E e, E f){ return as_logical_t<E>(e < f); }, a, b);
}
}
}
36 changes: 36 additions & 0 deletions include/eve/module/core/regular/impl/is_less_equal.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//==================================================================================================
/*
EVE - Expressive Vector Engine
Copyright : EVE Project Contributors
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once

#include <eve/module/core/regular/fam.hpp>
#include <eve/module/core/regular/next.hpp>
#include <eve/module/core/regular/max.hpp>
#include <eve/traits/as_logical.hpp>

namespace eve::detail
{
template<callable_options O, typename T>
EVE_FORCEINLINE constexpr as_logical_t<T> is_less_equal_(EVE_REQUIRES(cpu_), O const& o, T a, T b) noexcept
{
if constexpr (O::contains(almost))
{
auto tol = o[almost].value(T{});
if constexpr(integral_value<decltype(tol)>) return a <= eve::next(b, tol);
else return a <= fam(b, tol, eve::max(eve::abs(a), eve::abs(b)));
}
else if constexpr (product_type<T>)
{
return kumi::to_tuple(a) <= kumi::to_tuple(b);
}
else
{
if constexpr (scalar_value<T>) return as_logical_t<T>(a <= b);
else return map([]<typename E>(E e, E f){ return as_logical_t<E>(e <= f); }, a, b);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ namespace eve::detail
else if constexpr (cat == category::int64x2) return vcltq_s64(a, b);
else if constexpr (cat == category::uint64x2) return vcltq_u64(a, b);
}
else return map(is_less, a, b);
else return map([]<typename E>(E e, E f){ return as_logical_t<E>(e < f); }, a, b);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//==================================================================================================
/*
EVE - Expressive Vector Engine
Copyright : EVE Project Contributors
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once

#include <eve/concept/value.hpp>
#include <eve/detail/abi.hpp>
#include <eve/detail/category.hpp>
#include <eve/forward.hpp>

namespace eve::detail
{
template<callable_options O, arithmetic_scalar_value T, typename N>
EVE_FORCEINLINE logical<wide<T, N>> is_less_equal_(EVE_REQUIRES(neon128_), O const& opts, wide<T, N> a, wide<T, N> b) noexcept
requires arm_abi<abi_t<T, N>>
{
if constexpr (O::contains(almost))
{
return is_less_equal.behavior(cpu_{}, opts, a, b);
}
else
{
constexpr auto cat = categorize<wide<T, N>>();

if constexpr (cat == category::int32x4) return vcleq_s32(a, b);
else if constexpr (cat == category::int16x8) return vcleq_s16(a, b);
else if constexpr (cat == category::int8x16) return vcleq_s8(a, b);
else if constexpr (cat == category::uint32x4) return vcleq_u32(a, b);
else if constexpr (cat == category::uint16x8) return vcleq_u16(a, b);
else if constexpr (cat == category::uint8x16) return vcleq_u8(a, b);
else if constexpr (cat == category::float32x4) return vcleq_f32(a, b);
else if constexpr (cat == category::int32x2) return vcle_s32(a, b);
else if constexpr (cat == category::int16x4) return vcle_s16(a, b);
else if constexpr (cat == category::int8x8) return vcle_s8(a, b);
else if constexpr (cat == category::uint32x2) return vcle_u32(a, b);
else if constexpr (cat == category::uint16x4) return vcle_u16(a, b);
else if constexpr (cat == category::uint8x8) return vcle_u8(a, b);
else if constexpr (cat == category::float32x2) return vcle_f32(a, b);
else if constexpr (current_api >= asimd)
{
if constexpr (cat == category::float64x1) return vcle_f64(a, b);
else if constexpr (cat == category::int64x1) return vcle_s64(a, b);
else if constexpr (cat == category::uint64x1) return vcle_u64(a, b);
else if constexpr (cat == category::float64x2) return vcleq_f64(a, b);
else if constexpr (cat == category::int64x2) return vcleq_s64(a, b);
else if constexpr (cat == category::uint64x2) return vcleq_u64(a, b);
}
else return map([]<typename E>(E e, E f){ return as_logical_t<E>(e <= f); }, a, b);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//==================================================================================================
/*
EVE - Expressive Vector Engine
Copyright : EVE Project Contributors
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once

#include <eve/concept/value.hpp>
#include <eve/detail/implementation.hpp>

namespace eve::detail
{
template<callable_options O, typename T, typename N>
EVE_FORCEINLINE logical<wide<T, N>> is_less_equal_(EVE_REQUIRES(sve_), O const& opts, wide<T, N> a, wide<T, N> b) noexcept
requires sve_abi<abi_t<T, N>>
{
if constexpr (O::contains(almost)) return is_less_equal.behavior(cpu_{}, opts, a, b);
else return svcmple(sve_true<T>(), a, b);
}
}
25 changes: 25 additions & 0 deletions include/eve/module/core/regular/impl/simd/ppc/is_less_equal.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//==================================================================================================
/*
EVE - Expressive Vector Engine
Copyright : EVE Project Contributors
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once

#include <eve/concept/value.hpp>
#include <eve/detail/abi.hpp>
#include <eve/detail/category.hpp>
#include <eve/forward.hpp>

namespace eve::detail
{
template<callable_options O, arithmetic_scalar_value T, typename N>
EVE_FORCEINLINE logical<wide<T, N>> is_less_equal_(EVE_REQUIRES(vmx_), O const& opts, wide<T, N> a, wide<T, N> b) noexcept
requires ppc_abi<abi_t<T, N>>
{
if constexpr (O::contains(almost)) return is_less_equal.behavior(cpu_{}, opts, a, b);
else if constexpr(std::is_floating_point_v<T>) return logical<wide<T, N>>(vec_cmple(a.storage(), b.storage()));
else return !(a > b);
}
}
Loading