coord/ops: add elementwise apply
This commit is contained in:
parent
16c6a6d627
commit
3e9e9bff5a
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "../debug.hpp"
|
#include "../debug.hpp"
|
||||||
#include "../maths.hpp"
|
#include "../maths.hpp"
|
||||||
|
#include "../tuple.hpp"
|
||||||
#include "../preprocessor.hpp"
|
#include "../preprocessor.hpp"
|
||||||
#include "../types/bits.hpp"
|
#include "../types/bits.hpp"
|
||||||
|
|
||||||
@ -473,45 +474,77 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// logic operators
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
/// invoke a function elementwise to the arguments elementwise.
|
||||||
|
///
|
||||||
|
/// \tparam ArgsT a tuple containing the (coord) arguments for the func
|
||||||
template <
|
template <
|
||||||
typename RetT,
|
typename RetT,
|
||||||
typename ArgT,
|
|
||||||
typename FuncT,
|
typename FuncT,
|
||||||
std::size_t ...Indices,
|
typename ArgsT,
|
||||||
typename = std::enable_if_t<
|
std::size_t ...Indices
|
||||||
is_coord_v<ArgT> && is_coord_v<RetT>, void
|
|
||||||
>
|
|
||||||
>
|
>
|
||||||
constexpr auto
|
constexpr auto
|
||||||
apply (const std::index_sequence<Indices...>,
|
apply (const std::index_sequence<Indices...>,
|
||||||
FuncT &&func,
|
FuncT &&func,
|
||||||
const ArgT &a,
|
ArgsT args) noexcept
|
||||||
const ArgT &b)
|
|
||||||
{
|
{
|
||||||
|
using part_t = std::tuple_element_t<0,ArgsT>;
|
||||||
|
using value_t = typename part_t::value_type;
|
||||||
|
|
||||||
return RetT {
|
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 <
|
template <
|
||||||
typename RetT,
|
typename ReturnT,
|
||||||
std::size_t S,
|
|
||||||
typename T,
|
|
||||||
template <std::size_t,typename> class ArgT,
|
|
||||||
typename FuncT,
|
typename FuncT,
|
||||||
|
typename ...ArgT,
|
||||||
typename = std::enable_if_t<
|
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
|
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