6#ifndef METALL_CONTAINER_EXPERIMENT_JGRAPH_JGRAPH_HPP 
    7#define METALL_CONTAINER_EXPERIMENT_JGRAPH_JGRAPH_HPP 
   36template <
typename allocator_type>
 
   40template <
typename storage_iterator_type>
 
 
   48template <
typename _allocator_type = std::allocator<std::
byte>>
 
   61  using other_allocator =
 
   62      typename std::allocator_traits<allocator_type>::template 
rebind_alloc<T>;
 
   65  using other_scoped_allocator =
 
   70                       typename std::allocator_traits<
 
   74  static constexpr internal_id_type k_max_internal_id =
 
   75      std::numeric_limits<internal_id_type>::max();
 
   77  class vertex_data_type {
 
   81    explicit vertex_data_type(
 
   86    vertex_data_type(
const vertex_data_type &) = 
default;
 
   89    vertex_data_type(
const vertex_data_type &other, 
const allocator_type &
alloc)
 
   90        : m_id(other.m_id, 
alloc), m_value(other.m_value, 
alloc) {}
 
   97    vertex_data_type(vertex_data_type &&other,
 
  103    vertex_data_type &operator=(
const vertex_data_type &) = 
default;
 
  112    const value_type &value()
 const { 
return m_value; }
 
  119  using vertex_storage_type =
 
  122                        other_scoped_allocator<std::pair<
const internal_id_type,
 
  125  class edge_data_type {
 
  129    explicit edge_data_type(
const id_type &source_id,
 
  131                            const internal_id_type &
edge_id,
 
  132                            const allocator_type &
allocator = allocator_type())
 
  134          m_destination_id(destination_id, 
allocator),
 
  139    edge_data_type(
const edge_data_type &) = 
default;
 
  143    edge_data_type(
const edge_data_type &other, 
const allocator_type &
alloc)
 
  144        : m_source_id(other.m_source_id, 
alloc),
 
  145          m_destination_id(other.m_destination_id, 
alloc),
 
  146          m_edge_id(other.m_edge_id),
 
  147          m_value(other.m_value, 
alloc) {}
 
  155        : m_source_id(other.m_source_id, 
alloc),
 
  156          m_destination_id(other.m_destination_id, 
alloc),
 
  157          m_edge_id(other.m_edge_id),
 
  158          m_value(other.m_value, 
alloc) {}
 
  161    edge_data_type &operator=(
const edge_data_type &) = 
default;
 
  168    const id_type destination_id()
 const { 
return id_type(m_destination_id); }
 
  176    const value_type &value()
 const { 
return m_value; }
 
  179    string_type m_source_id;
 
  180    string_type m_destination_id;
 
  181    internal_id_type m_edge_id;
 
  185  using edge_storage_type =
 
  188                        other_scoped_allocator<
 
  189                            std::pair<const internal_id_type, edge_data_type>>>;
 
  192  using adj_list_edge_list_type =
 
  195                             std::hash<internal_id_type>, std::equal_to<>,
 
  196                             other_scoped_allocator<std::pair<
 
  197                                 const internal_id_type, internal_id_type>>>;
 
  201      adj_list_edge_list_type, std::hash<internal_id_type>, std::equal_to<>,
 
  202      other_scoped_allocator<
 
  203          std::pair<const internal_id_type, adj_list_edge_list_type>>>;
 
  207      internal_id_type, string_type, std::hash<internal_id_type>,
 
  224      typename adj_list_edge_list_type::iterator,
 
  225      typename std::pointer_traits<
typename std::allocator_traits<
 
  229      typename adj_list_edge_list_type::const_iterator,
 
  230      typename std::pointer_traits<
typename std::allocator_traits<
 
  236      : m_vertex_storage(
alloc),
 
  237        m_edge_storage(
alloc),
 
  239        m_vertex_id_table(
alloc) {}
 
 
  245    return priv_get_vertex_internal_id(
vertex_id) != k_max_internal_id;
 
 
  251    if (
src == k_max_internal_id) 
return 0;
 
  254    if (
dst == k_max_internal_id) 
return 0;
 
 
  269                       adj_list_edge_list_type{m_adj_list.get_allocator()});
 
  271    auto ret = m_vertex_storage.emplace(
 
  273        vertex_data_type{
vertex_id, m_vertex_storage.get_allocator()});
 
 
  288    const auto edge_id = priv_generate_edge_id();
 
  295    m_edge_storage.emplace(
 
  297                                edge_id, m_edge_storage.get_allocator()});
 
 
  303        m_vertex_storage.find(priv_get_vertex_internal_id(
vertex_id)));
 
 
  308        m_vertex_storage.find(priv_get_vertex_internal_id(
vertex_id)));
 
 
  334  std::size_t 
num_edges()
 const { 
return m_edge_storage.size(); }
 
  400    return m_vertex_storage.get_allocator();
 
 
  404  internal_id_type priv_get_vertex_internal_id(
 
  405      const std::string_view &
vid)
 const {
 
  406    auto hash = priv_hash_id(
vid.data());
 
  408    for (std::size_t 
d = 0; 
d <= m_max_vid_distance; ++
d) {
 
  409      const auto vitr = m_vertex_id_table.find(hash);
 
  410      if (
vitr == m_vertex_id_table.end()) {
 
  417      hash = (hash + 1) % k_max_internal_id;
 
  420    return k_max_internal_id;  
 
  423  internal_id_type priv_generate_vertex_internal_id(
 
  424      const std::string_view &
vid) {
 
  425    auto hash = priv_hash_id(
vid.data());
 
  428    while (m_vertex_id_table.count(hash) > 0) {
 
  429      hash = (hash + 1) % k_max_internal_id;
 
  432    m_max_vid_distance = std::max(
distance, m_max_vid_distance);
 
  434    m_vertex_id_table[
hash] = 
vid.data();
 
  439  internal_id_type priv_generate_edge_id() { 
return ++m_max_edge_id; }
 
  441  static internal_id_type priv_hash_id(
const std::string_view &
id) {
 
  442    return metall::mtlldetail::murmur_hash_64a(
id.
data(), 
id.
length(), 1234);
 
  445  vertex_storage_type m_vertex_storage;
 
  446  edge_storage_type m_edge_storage;
 
  447  adj_list_type m_adj_list;
 
  448  id_table_type m_vertex_id_table;
 
  449  internal_id_type m_max_edge_id{0};
 
  450  std::size_t m_max_vid_distance{0};
 
 
  455template <
typename storage_iterator_type>
 
  458  static constexpr bool is_const_value = std::is_const_v<
 
  459      typename std::iterator_traits<storage_iterator_type>::value_type>;
 
  462  using raw_value_type = 
typename std::tuple_element<
 
  464      typename std::iterator_traits<storage_iterator_type>::value_type>
::type;
 
  468      std::conditional_t<is_const_value, const raw_value_type, raw_value_type>;
 
  469  using pointer = 
typename std::pointer_traits<
typename std::iterator_traits<
 
  473      typename std::iterator_traits<storage_iterator_type>::difference_type;
 
  496    return m_current_pos == other.m_current_pos;
 
 
 
  511template <
typename storage_iterator_type>
 
  517template <
typename storage_iterator_type>
 
  527  static constexpr bool is_const_value = std::is_const_v<
 
  528      typename std::pointer_traits<storage_pointer_type>::element_type>;
 
  531  using raw_value_type = 
typename std::pointer_traits<
 
  536      std::conditional_t<is_const_value, const raw_value_type, raw_value_type>;
 
  538      typename std::pointer_traits<storage_pointer_type>::element_type::
 
  568    return m_current_pos == other.m_current_pos;
 
 
  572    const auto &
edge_id = m_current_pos->second;
 
  573    return &(m_storage_pointer->at(
edge_id));
 
 
  577    const auto &
edge_id = m_current_pos->second;
 
  578    return &(m_storage_pointer->at(
edge_id));
 
 
  582    const auto &
edge_id = m_current_pos->second;
 
  583    return (m_storage_pointer->at(
edge_id));
 
 
  587    const auto &
edge_id = m_current_pos->second;
 
  588    return (m_storage_pointer->at(
edge_id));