Program Listing for File utils_.hpp¶
↰ Return to documentation for file (include/ripple/graph/detail/utils_.hpp
)
#ifndef RIPPLE_GRAPH_DETAIL_UTILS__HPP
#define RIPPLE_GRAPH_DETAIL_UTILS__HPP
#include "../node.hpp"
#include <ripple/container/block.hpp>
#include <ripple/iterator/iterator_traits.hpp>
namespace ripple::detail {
/*==--- [dimensions] -------------------------------------------------------==*/
template <typename T>
constexpr size_t dims_from_block =
any_block_traits_t<typename modification_traits_t<T>::Value>::dimensions;
/*==--- [iterator deref] ---------------------------------------------------==*/
template <typename T, iterator_enable_t<T> = 0>
auto deref_if_iter(T&& iter) noexcept -> decltype(*iter)& {
return *iter;
}
template <typename T, non_iterator_enable_t<T> = 0>
decltype(auto) deref_if_iter(T&& t) noexcept {
return ripple_forward(t);
}
template <typename T, iterator_enable_t<T> = 0>
auto padding_if_iter(T&& iter) noexcept -> size_t {
if constexpr (is_any_block_v<decltype(*iter)>) {
return iter->padding();
} else {
return 0;
}
// return iter.padding();
}
template <typename T, non_iterator_enable_t<T> = 0>
auto padding_if_iter(T&& t) noexcept -> size_t {
return 0;
}
/*==--- [padding] ----------------------------------------------------------==*/
template <typename Iterator>
auto copy_face_padding(
ExecutionKind exec_kind, TransferKind transfer_kind, Iterator&& it) noexcept
-> void {
static_assert(
is_iterator_v<Iterator>, "Friend node adding requires iterator!");
static_assert(
is_multiblock_v<decltype(*it)>, "Iterator must be over block type!");
unrolled_for<iterator_traits_t<Iterator>::dimensions>([&](auto dim) {
if (!it->first_in_dim(dim)) {
it->fill_padding(
*it.offset(dim, -1),
CopySpecifier<dim, FaceLocation::start>(),
exec_kind,
transfer_kind);
}
if (!it->last_in_dim(dim)) {
it->fill_padding(
*it.offset(dim, 1),
CopySpecifier<dim, FaceLocation::end>(),
exec_kind,
transfer_kind);
}
});
}
/*==--- [node operations] --------------------------------------------------==*/
template <size_t Align, size_t MinStorage, typename Iterator>
auto add_friend_nodes(Node<Align, MinStorage>& node, Iterator&& it) noexcept
-> void {
static_assert(
is_iterator_v<Iterator>, "Friend node adding requires iterator!");
static_assert(
is_multiblock_v<decltype(*it)>, "Iterator must be over block type!");
auto ids = it->indices;
unrolled_for<iterator_traits_t<Iterator>::dimensions>([&](auto dim) {
if (!it->first_in_dim(dim)) {
ids[dim] -= 1;
node.add_friend(NodeInfo::id_from_indices(ids));
ids[dim] += 1;
}
if (!it->last_in_dim(dim)) {
ids[dim] += 1;
node.add_friend(NodeInfo::id_from_indices(ids));
ids[dim] -= 1;
}
});
}
template <typename GraphType, typename Iterator>
auto add_padding_op_nodes_for_iter(
GraphType& graph,
ExecutionKind exec_kind,
TransferKind transfer_kind,
Iterator&& it,
bool is_exclusive) noexcept -> void {
using IterValue = std::decay_t<decltype(*it)>;
if constexpr (is_multiblock_v<IterValue>) {
if (it->padding()) {
const auto name = NodeInfo::name_from_indices(it->indices);
const auto id = NodeInfo::id_from_indices(it->indices);
graph.emplace_named(
NodeInfo(name, id, NodeKind::split, exec_kind),
[exec_kind, transfer_kind](auto&& iter) {
copy_face_padding(exec_kind, transfer_kind, ripple_forward(iter));
},
ripple_forward(it));
// See function comment.
if (is_exclusive) {
auto* node = graph.find(name).value();
detail::add_friend_nodes(*node, it);
}
}
}
}
template <
typename Modifier,
typename GraphType,
typename Arg,
iterator_enable_t<Arg> = 0>
auto add_padding_op_nodes_impl(
GraphType& graph,
ExecutionKind exec_kind,
TransferKind transfer_kind,
Arg&& arg) noexcept -> void {
using Traits = modification_traits_t<Modifier>;
if constexpr (Traits::is_modifier) {
add_padding_op_nodes_for_iter(
graph,
exec_kind,
transfer_kind,
ripple_forward(arg),
Traits::is_exclusive);
}
}
template <
typename Modifier,
typename GraphType,
typename Arg,
non_iterator_enable_t<Arg> = 0>
auto add_padding_op_nodes_impl(
GraphType& graph,
ExecutionKind exec_kind,
TransferKind transfer_kind,
Arg&& arg) noexcept -> void {}
// clang-format off
template <typename Modifiers, typename GraphType, size_t... I, typename... Args>
auto add_padding_op_nodes_expanded(
GraphType& graph,
ExecutionKind exec_kind,
TransferKind transfer_kind,
std::index_sequence<I...>,
Args&&... args) noexcept -> void {
// clang-format on
(add_padding_op_nodes_impl<tuple_element_t<I, Modifiers>>(
graph, exec_kind, transfer_kind, ripple_forward(args)),
...);
}
template <typename Modifiers, typename GraphType, typename... Args>
auto add_padding_op_nodes(
GraphType& graph,
ExecutionKind exec_kind,
TransferKind transfer_kind,
Args&&... args) noexcept -> void {
add_padding_op_nodes_expanded<Modifiers>(
graph,
exec_kind,
transfer_kind,
std::make_index_sequence<sizeof...(Args)>(),
ripple_forward(args)...);
}
} // namespace ripple::detail
#endif // RIPPLE_GRAPH_DETAIL_UTILS__HPP