• Docs >
  • Program Listing for File utils_.hpp
Shortcuts

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

Docs

Access comprehensive developer documentation for Ripple

View Docs

Tutorials

Get tutorials to help with understand all features

View Tutorials

Examples

Find examples to help get started

View Examples