coord/ops: add elementwise apply
This commit is contained in:
parent
16c6a6d627
commit
3e9e9bff5a
@ -25,6 +25,7 @@
|
||||
|
||||
#include "../debug.hpp"
|
||||
#include "../maths.hpp"
|
||||
#include "../tuple.hpp"
|
||||
#include "../preprocessor.hpp"
|
||||
#include "../types/bits.hpp"
|
||||
|
||||
@ -473,45 +474,77 @@ namespace util {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// logic operators
|
||||
namespace detail {
|
||||
/// invoke a function elementwise to the arguments elementwise.
|
||||
///
|
||||
/// \tparam ArgsT a tuple containing the (coord) arguments for the func
|
||||
template <
|
||||
typename RetT,
|
||||
typename ArgT,
|
||||
typename FuncT,
|
||||
std::size_t ...Indices,
|
||||
typename = std::enable_if_t<
|
||||
is_coord_v<ArgT> && is_coord_v<RetT>, void
|
||||
>
|
||||
typename ArgsT,
|
||||
std::size_t ...Indices
|
||||
>
|
||||
constexpr auto
|
||||
apply (const std::index_sequence<Indices...>,
|
||||
FuncT &&func,
|
||||
const ArgT &a,
|
||||
const ArgT &b)
|
||||
ArgsT args) noexcept
|
||||
{
|
||||
using part_t = std::tuple_element_t<0,ArgsT>;
|
||||
using value_t = typename part_t::value_type;
|
||||
|
||||
return RetT {
|
||||
std::invoke (func, a[Indices], b[Indices])...
|
||||
std::apply (
|
||||
func,
|
||||
::util::tuple::convert (
|
||||
static_cast<
|
||||
const value_t& (&)(const part_t&)
|
||||
> (
|
||||
get<Indices,RetT>
|
||||
), args
|
||||
)
|
||||
)...
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// invokes a function elementwise using elementwise parameters from the
|
||||
// supplied arguments.
|
||||
//
|
||||
// equivalent to this pseduocode:
|
||||
// for (int i: indices (ReturnT))
|
||||
// res[i] = func (args[i]...);
|
||||
// return res;
|
||||
//
|
||||
// forwards the arguments as a tuple to a helper function that has access
|
||||
// to indices as a template parameter.
|
||||
template <
|
||||
typename RetT,
|
||||
std::size_t S,
|
||||
typename T,
|
||||
template <std::size_t,typename> class ArgT,
|
||||
typename ReturnT,
|
||||
typename FuncT,
|
||||
typename ...ArgT,
|
||||
typename = std::enable_if_t<
|
||||
is_coord_v<RetT> && is_coord_v<ArgT>, void
|
||||
// return type and arguments must be coordinates
|
||||
(is_coord_v<ReturnT> && ... && is_coord_v<std::decay_t<ArgT>>) &&
|
||||
// all types must be the same arity
|
||||
((ReturnT::elements == std::decay_t<ArgT>::elements) && ...) &&
|
||||
// all the arguments must be the same type
|
||||
(std::is_same_v<
|
||||
std::tuple_element_t<0,std::tuple<std::decay_t<ArgT>...>>,
|
||||
std::decay_t<ArgT>
|
||||
> && ...),
|
||||
void
|
||||
>,
|
||||
typename Indices = std::make_index_sequence<S>
|
||||
typename Indices = std::make_index_sequence<ReturnT::elements>
|
||||
>
|
||||
constexpr auto
|
||||
apply (FuncT &&func, const ArgT<S,T> &a, const ArgT<S,T> &b)
|
||||
invoke (FuncT &&func, ArgT &&...args) noexcept
|
||||
{
|
||||
return detail::apply (Indices{}, std::forward<FuncT> (func), a, b);
|
||||
return detail::apply<ReturnT> (
|
||||
Indices{},
|
||||
std::forward<FuncT> (func),
|
||||
std::tuple (std::forward<ArgT> (args)...)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user