ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
hash_tree.hpp
1// This file is part of the ACTS project.
2//
3// Copyright (C) 2016 CERN for the benefit of the ACTS project
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#pragma once
10
11// Project include(s)
12#include "detray/definitions/indexing.hpp"
13#include "detray/definitions/math.hpp"
14
15// System include(s)
16#include <iterator>
17#include <sstream>
18#include <type_traits>
19
20namespace detray {
21
23template <typename value_t>
26 using hash_type = std::size_t;
28 using data_hasher = std::hash<value_t>;
30 using node_hasher = std::hash<hash_type>;
31
35 auto operator()(const value_t &v) { return data_hasher{}(v); }
36
41 auto operator()(const hash_type &left, const hash_type &right) {
42 return node_hasher{}(left) + node_hasher{}(right);
43 }
44};
45
55template <typename input_collection_t,
56 typename data_t = typename input_collection_t::value_type,
57 typename hash_function_t = default_hash<data_t>,
58 typename hash_t =
59 decltype(std::declval<hash_function_t>()(data_t{0})),
60 template <typename> class vector_t = dvector>
61 requires std::is_invocable_v<hash_function_t, data_t> &&
62 std::is_invocable_v<hash_function_t, hash_t>
63class hash_tree {
64 public:
66 using hash_function = hash_function_t;
68 using hash_type = hash_t;
69
71 struct hashed_node {
74 explicit hashed_node(hash_t hash) : _key(hash) {}
75
77 hash_t _key;
79 dindex _parent{detail::invalid_value<dindex>()};
81 dindex _left_child{detail::invalid_value<dindex>()};
83 dindex _right_child{detail::invalid_value<dindex>()};
84
87 const hash_t &key() const { return _key; }
90 hash_t &key() { return _key; }
91
94 void set_parent(dindex pi) { _parent = pi; }
95
99 void set_children(dindex lc, dindex rc) {
100 _left_child = lc;
101 _right_child = rc;
102 }
103 };
104
106 hash_tree() = delete;
107
113 explicit hash_tree(const input_collection_t &data,
114 const hash_function_t & /*hf*/ = {}) {
115 build(data);
116 }
117
119 ~hash_tree() = default;
120
124 auto root() { return _tree.back().key(); }
125
127 inline std::string to_string() const {
128 std::stringstream ss;
129 for (const auto &n : _tree) {
130 ss << n.key() << std::endl;
131 }
132 return ss.str();
133 };
134
136 const vector_t<hashed_node> &tree() const { return _tree; }
137
138 private:
140 void build(const input_collection_t &input_data) noexcept(false) {
141 // Build leaves from input data type
142 for (const auto &data : input_data) {
143 _tree.emplace_back(_hash(data));
144 }
145 // Need an even number of leaves to build the tree correctly
146 if (input_data.size() % 2u != 0u) {
147 _tree.emplace_back(_hash(0));
148 }
149 // Size of the tree is already known (all iterators stay valid in
150 // recursion)
151 // we might need to add one dummy node per level
152 auto n_levels = static_cast<dindex>(math::log(input_data.size()));
153 _tree.reserve(2u * _tree.size() + n_levels);
154 // Build next level
155 build(_tree.begin(), static_cast<dindex>(_tree.size()));
156 }
157
163 template <typename iterator_t>
164 void build(iterator_t &&first_child, dindex n_prev_level) {
165 // base case
166 if (n_prev_level <= 1u) {
167 return;
168 }
169
170 auto last_child = first_child + static_cast<std::ptrdiff_t>(n_prev_level);
171
172 // Run over previous tree level to build the next level
173 for (auto current_child = first_child; current_child != last_child;
174 current_child += 2u) {
175 auto parent_digest =
176 _hash(current_child->key(), (current_child + 1u)->key());
177 hashed_node parent = _tree.emplace_back(parent_digest);
178
179 // Parent node index is at the back of the tree
180 current_child->set_parent(static_cast<dindex>(_tree.size()) - 1u);
181 (current_child + 1)->set_parent(static_cast<dindex>(_tree.size()) - 1u);
182
183 // Set the indices as distances in the contiguous container
184 auto left_child_idx = std::distance(current_child, _tree.begin());
185 parent.set_children(static_cast<dindex>(left_child_idx),
186 static_cast<dindex>(left_child_idx) + 1u);
187 }
188 dindex n_level = n_prev_level / 2u;
189 // Need dummy leaf node for next level?
190 if (n_level % 2u != 0u && n_level > 1u) {
191 _tree.emplace_back(0);
192 n_level++;
193 }
194 // begin next time where we ended this time
195 build(last_child, n_level);
196 }
197
199 hash_function_t _hash{hash_function_t{}};
200
202 vector_t<hashed_node> _tree = {};
203};
204
205} // namespace detray
const vector_t< hashed_node > & tree() const
Definition hash_tree.hpp:136
hash_tree()=delete
No empty tree.
auto root()
Definition hash_tree.hpp:124
hash_t hash_type
Type of hashes stored in the tree.
Definition hash_tree.hpp:68
~hash_tree()=default
Default destructor.
hash_function_t hash_function
Hash function used by the tree.
Definition hash_tree.hpp:66
hash_tree(const input_collection_t &data, const hash_function_t &={})
Build from an input collection using the configured hash function.
Definition hash_tree.hpp:113
std::string to_string() const
Definition hash_tree.hpp:127
Detray include(s).
Definition array_operators.hpp:18
vecmem::vector< value_t > dvector
Vector container backed by vecmem.
Definition containers.hpp:34
unsigned int dindex
Default index type.
Definition indexing.hpp:18
Default hash function makes use of default node in the hash tree.
Definition hash_tree.hpp:24
std::hash< hash_type > node_hasher
Hash function used for child hashes.
Definition hash_tree.hpp:30
auto operator()(const hash_type &left, const hash_type &right)
Combine two child hashes.
Definition hash_tree.hpp:41
std::hash< value_t > data_hasher
Hash function used for input data values.
Definition hash_tree.hpp:28
std::size_t hash_type
Type returned by the hash function.
Definition hash_tree.hpp:26
auto operator()(const value_t &v)
Hash an input value.
Definition hash_tree.hpp:35
Default node in the hash tree.
Definition hash_tree.hpp:71
hash_t & key()
Get the mutable node hash.
Definition hash_tree.hpp:90
void set_parent(dindex pi)
Set the parent node index.
Definition hash_tree.hpp:94
hash_t _key
Hash key of this node.
Definition hash_tree.hpp:77
dindex _parent
Index of this node's parent.
Definition hash_tree.hpp:79
dindex _right_child
Index of this node's right child.
Definition hash_tree.hpp:83
hashed_node(hash_t hash)
Construct a node with its hash.
Definition hash_tree.hpp:74
void set_children(dindex lc, dindex rc)
Set the child node indices.
Definition hash_tree.hpp:99
const hash_t & key() const
Get the node hash.
Definition hash_tree.hpp:87
dindex _left_child
Index of this node's left child.
Definition hash_tree.hpp:81