<commit_before>#pragma once

#include <algorithm>  // all_of, copy
#include <deque>
#include <initializer_list>
#include <iosfwd>
#include <stdexcept>  //invalid_argument
#include <unordered_map>

#include <boost/container/flat_set.hpp>

#include "sdd/dd/definition.hh"
#include "sdd/hom/context_fwd.hh"
#include "sdd/hom/definition_fwd.hh"
#include "sdd/hom/identity.hh"
#include "sdd/hom/local.hh"
#include "sdd/order/order.hh"
#include "sdd/util/packed.hh"

namespace sdd { namespace hom {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief intersection homomorphism.
template <typename C>
struct _intersection
{
  /// @brief The type of the homomorphism operands' set.
  using operands_type = boost::container::flat_set<homomorphism<C>>;

  /// @brief The type of a const iterator on this intersection's operands.
  using const_iterator = typename operands_type::const_iterator;

  /// @brief The homomorphism operands' set.
  const operands_type operands;

  /// @brief Constructor.
  _intersection(operands_type&& ops)
    : operands(std::move(ops))
  {}

  /// @brief Evaluation.
  SDD<C>
  operator()(context<C>& cxt, const order<C>& o, const SDD<C>& x)
  const
  {
    dd::intersection_builder<C, SDD<C>> intersection_operands(cxt.sdd_context());
    intersection_operands.reserve(operands.size());
    for (const auto& op : operands)
    {
      intersection_operands.add(op(cxt, o, x));
    }
    return dd::intersection(cxt.sdd_context(), std::move(intersection_operands));
  }

  /// @brief Skip variable predicate.
  bool
  skip(const order<C>& o)
  const noexcept
  {
    return std::all_of( operands.begin(), operands.end()
                      , [&o](const homomorphism<C>& h){return h.skip(o);});
  }


  /// @brief Selector predicate
  bool
  selector()
  const noexcept
  {
    return std::all_of( operands.begin(), operands.end()
                      , [](const homomorphism<C>& h){return h.selector();});
  }

  /// @brief Get an iterator to the first operand.
  ///
  /// O(1).
  const_iterator
  begin()<commit_msg>Stop hom::intersection as soon as possible<commit_after>#pragma once

#include <algorithm>  // all_of, copy
#include <deque>
#include <initializer_list>
#include <iosfwd>
#include <stdexcept>  //invalid_argument
#include <unordered_map>

#include <boost/container/flat_set.hpp>

#include "sdd/dd/definition.hh"
#include "sdd/hom/context_fwd.hh"
#include "sdd/hom/definition_fwd.hh"
#include "sdd/hom/identity.hh"
#include "sdd/hom/local.hh"
#include "sdd/order/order.hh"
#include "sdd/util/packed.hh"

namespace sdd { namespace hom {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief intersection homomorphism.
template <typename C>
struct _intersection
{
  /// @brief The type of the homomorphism operands' set.
  using operands_type = boost::container::flat_set<homomorphism<C>>;

  /// @brief The type of a const iterator on this intersection's operands.
  using const_iterator = typename operands_type::const_iterator;

  /// @brief The homomorphism operands' set.
  const operands_type operands;

  /// @brief Constructor.
  _intersection(operands_type&& ops)
    : operands(std::move(ops))
  {}

  /// @brief Evaluation.
  SDD<C>
  operator()(context<C>& cxt, const order<C>& o, const SDD<C>& x)
  const
  {
    dd::intersection_builder<C, SDD<C>> intersection_operands(cxt.sdd_context());
    intersection_operands.reserve(operands.size());
    for (const auto& op : operands)
    {
      auto res = op(cxt, o, x);
      if (res.empty())
      {
        return zero<C>();
      }
      intersection_operands.add(std::move(res));
    }
    return dd::intersection(cxt.sdd_context(), std::move(intersection_operands));
  }

  /// @brief Skip variable predicate.
  bool
  skip(const order<C>& o)
  const noexcept
  {
    return std::all_of( operands.begin(), operands.end()
                      , [&o](const homomorphism<C>& h){return h.skip(o);});
  }


  /// @brief Selector predicate
  bool
  selector()
  const noexcept
  {
    return std::all_of( operands.begin(), operands.end()
                      , [](const homomorphism<C>& h){return h.selector();});
  }

  /// @brief Get an iterator to the first operand.
  ///
  /// O(1).
  const_iterator
  begin()
{'fraction_non_alphanumeric': 0.18794407517763007, 'fraction_numerical': 0.00045840018336007336, 'mean_word_length': 2.8999106344950847, 'pattern_counts': {'":': 0, '<': 42, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7022991', 'n_tokens_mistral': 1443, 'n_tokens_neox': 1404, 'n_words': 323}