Skip to content

Commit

Permalink
Made scan a new format callable
Browse files Browse the repository at this point in the history
  • Loading branch information
SadiinsoSnowfall committed Feb 6, 2025
1 parent f0cf2ca commit 8b89205
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 88 deletions.
83 changes: 39 additions & 44 deletions include/eve/module/core/regular/impl/scan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,59 +13,54 @@

namespace eve::detail
{
template<int group_size, simd_value Wide, typename Op>
EVE_FORCEINLINE Wide
scan_common_impl(Wide x, Op op)
{
if constexpr( group_size == 1 ) return x;
else
template<int group_size, simd_value Wide, typename Op>
EVE_FORCEINLINE Wide scan_common_impl(Wide x, Op op)
{
x = scan_common_impl<group_size / 2>(x, op);
return op(x, slide_right(x, eve::index<group_size / 2>));
if constexpr (group_size == 1) return x;
else
{
x = scan_common_impl<group_size / 2>(x, op);
return op(x, slide_right(x, eve::index<group_size / 2>));
}
}
}

template<int group_size, simd_value Wide, typename Op>
EVE_FORCEINLINE Wide
scan_common_impl(Wide x, Op op, Wide z)
{
if constexpr( group_size == 1 ) return x;
else
template<int group_size, simd_value Wide, typename Op>
EVE_FORCEINLINE Wide scan_common_impl(Wide x, Op op, Wide init)
{
x = scan_common_impl<group_size / 2>(x, op, z);
return op(x, slide_right(z, x, eve::index<group_size / 2>));
if constexpr (group_size == 1) return x;
else
{
x = scan_common_impl<group_size / 2>(x, op, init);
return op(x, slide_right(init, x, eve::index<group_size / 2>));
}
}
}

template<simd_value Wide, typename Op, typename Zero>
EVE_FORCEINLINE Wide
scan_(EVE_SUPPORTS(cpu_), Wide v, Op op, Zero z) noexcept
{
if constexpr( Wide::size() == 1 ) return v;
else if constexpr( has_emulated_abi_v<Wide> )
template<callable_options O, simd_value Wide, typename Op, typename Init>
EVE_FORCEINLINE Wide scan_(EVE_REQUIRES(cpu_), O const&, Wide v, Op op, Init init) noexcept
{
auto sum_value = v.get(0);

for( int i = 1; i != Wide::size(); ++i )
if constexpr (Wide::size() == 1)
{
sum_value = op(sum_value, v.get(i));
v.set(i, sum_value);
return v;
}
else if constexpr (has_emulated_abi_v<Wide>)
{
auto sum_value = as_value(init, as<element_type_t<Wide>>{});

return v;
}
else if constexpr( std::same_as<Zero, callable_zero_> )
{
return scan_common_impl<Wide::size()>(v, op);
}
else { return scan_common_impl<Wide::size()>(v, op, Wide {z}); }
}

template<simd_value Wide>
EVE_FORCEINLINE Wide
scan_(EVE_SUPPORTS(cpu_), Wide v) noexcept
{
return scan(v, add, eve::zero);
}
for (int i = 0; i != Wide::size(); ++i)
{
sum_value = op(sum_value, v.get(i));
v.set(i, sum_value);
}

return v;
}
else if constexpr (std::same_as<Init, callable_zero_>)
{
return scan_common_impl<Wide::size()>(v, op);
}
else
{
return scan_common_impl<Wide::size()>(v, op, as_value(init, as<Wide>{}));
}
}
}
18 changes: 10 additions & 8 deletions include/eve/module/core/regular/impl/simd/x86/scan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,20 @@ use_scan_in_lanes(Wide)
else return std::false_type {};
}

template<simd_value Wide, typename Op, typename Zero>
EVE_FORCEINLINE auto
scan_(EVE_SUPPORTS(avx2_), Wide v, Op op, Zero z_) requires(current_api == avx2)
template<callable_options O, typename T, typename N, typename Op, typename Zero>
EVE_FORCEINLINE auto scan_(EVE_REQUIRES(avx2_), O const& opts, wide<T, N> v, Op op, Zero z_)
requires x86_abi<abi_t<T, N>>
{
if constexpr( decltype(use_scan_in_lanes(v))::value )
{
Wide z = as_value(z_, eve::as<Wide> {});
constexpr auto size = wide<T, N>::size();

v = scan_in_lanes<Wide::size() / 2>(v, op, z);
Wide left_sum = broadcast(v, index<Wide::size() / 2 - 1>);
return op(v, slide_right(z, left_sum, index<Wide::size() / 2>));
Wide z = as_value(z_, eve::as<wide<T, N>> {});

v = scan_in_lanes<size / 2>(v, op, z);
Wide left_sum = broadcast(v, index<size / 2 - 1>);
return op(v, slide_right(z, left_sum, index<size / 2>));
}
else return scan_(EVE_RETARGET(cpu_), v, op, z_);
else return scan.behavior(cpu_{}, opts, v, op, z_);
}
}
96 changes: 60 additions & 36 deletions include/eve/module/core/regular/scan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,73 @@
//==================================================================================================
#pragma once

#include <eve/arch.hpp>
#include <eve/detail/overload.hpp>

namespace eve
{
template<typename Options>
struct scan_t : callable<scan_t, Options>
{
template<simd_value Wide, typename Op, typename Init>
constexpr EVE_FORCEINLINE Wide operator()(Wide w, Op op, Init init) const noexcept
{
return EVE_DISPATCH_CALL(w, op, init);
}

template<simd_value Wide>
constexpr EVE_FORCEINLINE Wide operator()(Wide w) const noexcept
{
return EVE_DISPATCH_CALL(w, add, eve::zero);
}

EVE_CALLABLE_OBJECT(scan_t, scan_);
};

//TODO DOC
//================================================================================================
//! @addtogroup core_simd
//! @{
//! @var scan
//! @brief Computes the TODO
//!
//! @groupheader{Header file}
//!
//! @code
//! #include <eve/module/core.hpp>
//! @endcode
//!
//! @groupheader{Callable Signatures}
//!
//! @code
//! namespace eve
//! {
//! TODO
//! }
//! @endcode
//!
//! **Parameters**
//!
//! * `x`: An instance of an [SIMD value](@ref eve::simd_value)
//!
//! **Return value**
//!
//! * TODO
//!
//! @groupheader{Example}
//!
//! TODO
//! @}
//================================================================================================
EVE_MAKE_CALLABLE(scan_, scan);
//================================================================================================
//! @addtogroup core_simd
//! @{
//! @var scan
//! @brief Computes the generalized prefix sum
//!
//! @groupheader{Header file}
//!
//! @code
//! #include <eve/module/core.hpp>
//! @endcode
//!
//! @groupheader{Callable Signatures}
//!
//! @code
//! namespace eve
//! {
//! constexpr simd_value scan(simd_value auto x, auto op, auto init) noexcept; // 1
//! constexpr simd_value scan(simd_value auto x) noexcept; // 2
//! }
//! @endcode
//!
//! **Parameters**
//!
//! * `x`: An instance of an [SIMD value](@ref eve::simd_value)
//!
//! **Return value**
//!
//! 1. The generalized prefix sum of the elements of `x` using the binary operation `op`
//! and the initial value `init`.
//! 2. The prefix sum of the elements of `x`.
//!
//! @groupheader{Example}
//!
//! @godbolt{doc/core/scan.cpp}
//!
//================================================================================================
inline constexpr auto scan = functor<scan_t>;
//================================================================================================
//! @}
//================================================================================================
}

#include <eve/arch.hpp>
#include <eve/module/core/regular/impl/scan.hpp>

#if defined(EVE_INCLUDE_X86_HEADER)
Expand Down
11 changes: 11 additions & 0 deletions test/doc/core/scan.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <eve/module/core.hpp>
#include <iostream>

int main()
{
eve::wide x = {1.0, 2.0, 3.0, 4.0};

std::cout << "x: " << x << "\n";
std::cout << "eve::scan(x): " << eve::scan(x) << "\n";
std::cout << "eve::scan(x, eve::mul, eve::one): " << eve::scan(x, eve::mul, eve::one) << "\n";
}

0 comments on commit 8b89205

Please sign in to comment.