Program Listing for File tree_index.cpp

Return to documentation for file (SeQuant/core/tree_index.cpp)

#include <SeQuant/core/container.hpp>
#include <SeQuant/core/expr.hpp>
#include <SeQuant/core/tree_index.hpp>
#include <SeQuant/core/utility/exception.hpp>
#include <SeQuant/core/utility/macros.hpp>

#include <concepts>
#include <cstddef>
#include <initializer_list>
#include <ranges>
#include <string>
#include <type_traits>

namespace sequant {

TreeIndex::TreeIndex(container::svector<std::size_t> positions)
    : positions_(std::move(positions)) {}

TreeIndex::TreeIndex(std::initializer_list<std::size_t> positions)
    : TreeIndex(container::svector<std::size_t>(std::move(positions))) {}

template <typename ExprType>
ExprType &select_impl(ExprType &expr,
                      const container::svector<std::size_t> &positions) {
  constexpr bool is_expr_ptr =
      std::same_as<std::remove_cvref_t<ExprType>, ExprPtr>;

  ExprType *selected = &expr;

  for (std::size_t current : positions) {
    if (current >= selected->size()) {
      throw Exception("Position " + std::to_string(current) +
                      " is out of bounds for an expression of dimension " +
                      std::to_string(selected->size()));
    }

    using std::ranges::begin;

    auto it = begin(*selected) + current;

    if constexpr (is_expr_ptr) {
      selected = &(*it);
    } else {
      selected = &(*(*it));
    }
  }

  SEQUANT_ASSERT(selected);

  return *selected;
}

ExprPtr &TreeIndex::select_from(ExprPtr &expr) const {
  return select_impl(expr, positions_);
}

const ExprPtr &TreeIndex::select_from(const ExprPtr &expr) const {
  return select_impl(expr, positions_);
}

Expr &TreeIndex::select_from(Expr &expr) const {
  return select_impl(expr, positions_);
}

const Expr &TreeIndex::select_from(const Expr &expr) const {
  return select_impl(expr, positions_);
}

std::size_t TreeIndex::depth() const { return positions_.size(); }

}  // namespace sequant