Skip to content

Commit df6ef46

Browse files
authored
Merge pull request arximboldi#292 from alex-sparus/hash-size
Support hash size that's not std::size_t
2 parents 045c2b3 + 48d559a commit df6ef46

File tree

11 files changed

+241
-92
lines changed

11 files changed

+241
-92
lines changed

immer/detail/hamts/bits.hpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ namespace detail {
2020
namespace hamts {
2121

2222
using size_t = std::size_t;
23-
using hash_t = std::size_t;
2423
using bits_t = std::uint32_t;
2524
using count_t = std::uint32_t;
2625
using shift_t = std::uint32_t;
@@ -53,14 +52,14 @@ struct get_bitmap_type<4u>
5352
template <bits_t B, typename T = count_t>
5453
constexpr T branches = T{1u} << B;
5554

56-
template <bits_t B, typename T = size_t>
55+
template <typename T, bits_t B>
5756
constexpr T mask = branches<B, T> - 1u;
5857

59-
template <bits_t B, typename T = count_t>
58+
template <typename hash_t, bits_t B, typename T = count_t>
6059
constexpr T max_depth = (sizeof(hash_t) * 8u + B - 1u) / B;
6160

62-
template <bits_t B, typename T = count_t>
63-
constexpr T max_shift = max_depth<B, count_t> * B;
61+
template <typename hash_t, bits_t B, typename T = count_t>
62+
constexpr T max_shift = max_depth<hash_t, B, count_t> * B;
6463

6564
#define IMMER_HAS_BUILTIN_POPCOUNT 1
6665

immer/detail/hamts/champ.hpp

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ struct champ
131131
using edit_t = typename MemoryPolicy::transience_t::edit;
132132
using owner_t = typename MemoryPolicy::transience_t::owner;
133133
using bitmap_t = typename get_bitmap_type<B>::type;
134+
using hash_t = typename node_t::hash_t;
134135

135136
static_assert(branches<B> <= sizeof(bitmap_t) * 8, "");
136137

@@ -202,7 +203,7 @@ struct champ
202203
size_t hash_mask) const
203204
{
204205
auto result = std::size_t{};
205-
if (depth < max_depth<B>) {
206+
if (depth < max_depth<hash_t, B>) {
206207
auto nodemap = node->nodemap();
207208
if (nodemap) {
208209
auto fst = node->children();
@@ -213,7 +214,7 @@ struct champ
213214
do_check_champ(child,
214215
depth + 1,
215216
path_hash | (idx << (B * depth)),
216-
(hash_mask << B) | mask<B>);
217+
(hash_mask << B) | mask<hash_t, B>);
217218
}
218219
}
219220
}
@@ -248,7 +249,7 @@ struct champ
248249
// due some value being moved out of the champ when it should have not.
249250
bool check_champ() const
250251
{
251-
auto r = do_check_champ(root, 0, 0, mask<B>);
252+
auto r = do_check_champ(root, 0, 0, mask<hash_t, B>);
252253
// assert(r == size);
253254
return r == size;
254255
}
@@ -258,7 +259,7 @@ struct champ
258259
node_t* node,
259260
count_t depth) const
260261
{
261-
if (depth < max_depth<B>) {
262+
if (depth < max_depth<hash_t, B>) {
262263
++stats.inner_node_count;
263264
stats.inner_node_w_value_count += node->data_count() > 0;
264265
stats.inner_node_w_child_count += node->children_count() > 0;
@@ -317,7 +318,7 @@ struct champ
317318
void
318319
for_each_chunk_traversal(const node_t* node, count_t depth, Fn&& fn) const
319320
{
320-
if (depth < max_depth<B>) {
321+
if (depth < max_depth<hash_t, B>) {
321322
auto datamap = node->datamap();
322323
if (datamap)
323324
fn(node->values(), node->values() + node->data_count());
@@ -348,7 +349,7 @@ struct champ
348349
{
349350
if (old_node == new_node)
350351
return;
351-
if (depth < max_depth<B>) {
352+
if (depth < max_depth<hash_t, B>) {
352353
auto old_nodemap = old_node->nodemap();
353354
auto new_nodemap = new_node->nodemap();
354355
auto old_datamap = old_node->datamap();
@@ -537,8 +538,8 @@ struct champ
537538
{
538539
auto node = root;
539540
auto hash = Hash{}(k);
540-
for (auto i = count_t{}; i < max_depth<B>; ++i) {
541-
auto bit = bitmap_t{1u} << (hash & mask<B>);
541+
for (auto i = count_t{}; i < max_depth<hash_t, B>; ++i) {
542+
auto bit = bitmap_t{1u} << (hash & mask<hash_t, B>);
542543
if (node->nodemap() & bit) {
543544
auto offset = node->children_count(bit);
544545
node = node->children()[offset];
@@ -571,7 +572,7 @@ struct champ
571572
add_result do_add(node_t* node, T v, hash_t hash, shift_t shift) const
572573
{
573574
assert(node);
574-
if (shift == max_shift<B>) {
575+
if (shift == max_shift<hash_t, B>) {
575576
auto fst = node->collisions();
576577
auto lst = fst + node->collision_count();
577578
for (; fst != lst; ++fst)
@@ -581,7 +582,7 @@ struct champ
581582
false};
582583
return {node_t::copy_collision_insert(node, std::move(v)), true};
583584
} else {
584-
auto idx = (hash & (mask<B> << shift)) >> shift;
585+
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
585586
auto bit = bitmap_t{1u} << idx;
586587
if (node->nodemap() & bit) {
587588
auto offset = node->children_count(bit);
@@ -644,7 +645,7 @@ struct champ
644645
do_add_mut(edit_t e, node_t* node, T v, hash_t hash, shift_t shift) const
645646
{
646647
assert(node);
647-
if (shift == max_shift<B>) {
648+
if (shift == max_shift<hash_t, B>) {
648649
auto fst = node->collisions();
649650
auto lst = fst + node->collision_count();
650651
for (; fst != lst; ++fst)
@@ -663,7 +664,7 @@ struct champ
663664
: node_t::copy_collision_insert(node, std::move(v));
664665
return {node_t::owned(r, e), true, mutate};
665666
} else {
666-
auto idx = (hash & (mask<B> << shift)) >> shift;
667+
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
667668
auto bit = bitmap_t{1u} << idx;
668669
if (node->nodemap() & bit) {
669670
auto offset = node->children_count(bit);
@@ -756,7 +757,7 @@ struct champ
756757
update_result
757758
do_update(node_t* node, K&& k, Fn&& fn, hash_t hash, shift_t shift) const
758759
{
759-
if (shift == max_shift<B>) {
760+
if (shift == max_shift<hash_t, B>) {
760761
auto fst = node->collisions();
761762
auto lst = fst + node->collision_count();
762763
for (; fst != lst; ++fst)
@@ -774,7 +775,7 @@ struct champ
774775
std::forward<Fn>(fn)(Default{}()))),
775776
true};
776777
} else {
777-
auto idx = (hash & (mask<B> << shift)) >> shift;
778+
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
778779
auto bit = bitmap_t{1u} << idx;
779780
if (node->nodemap() & bit) {
780781
auto offset = node->children_count(bit);
@@ -851,7 +852,7 @@ struct champ
851852
node_t* do_update_if_exists(
852853
node_t* node, K&& k, Fn&& fn, hash_t hash, shift_t shift) const
853854
{
854-
if (shift == max_shift<B>) {
855+
if (shift == max_shift<hash_t, B>) {
855856
auto fst = node->collisions();
856857
auto lst = fst + node->collision_count();
857858
for (; fst != lst; ++fst)
@@ -864,7 +865,7 @@ struct champ
864865
Project{}(detail::as_const(*fst)))));
865866
return nullptr;
866867
} else {
867-
auto idx = (hash & (mask<B> << shift)) >> shift;
868+
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
868869
auto bit = bitmap_t{1u} << idx;
869870
if (node->nodemap() & bit) {
870871
auto offset = node->children_count(bit);
@@ -929,7 +930,7 @@ struct champ
929930
hash_t hash,
930931
shift_t shift) const
931932
{
932-
if (shift == max_shift<B>) {
933+
if (shift == max_shift<hash_t, B>) {
933934
auto fst = node->collisions();
934935
auto lst = fst + node->collision_count();
935936
for (; fst != lst; ++fst)
@@ -956,7 +957,7 @@ struct champ
956957
: node_t::copy_collision_insert(node, std::move(v));
957958
return {node_t::owned(r, e), true, mutate};
958959
} else {
959-
auto idx = (hash & (mask<B> << shift)) >> shift;
960+
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
960961
auto bit = bitmap_t{1u} << idx;
961962
if (node->nodemap() & bit) {
962963
auto offset = node->children_count(bit);
@@ -1068,7 +1069,7 @@ struct champ
10681069
hash_t hash,
10691070
shift_t shift) const
10701071
{
1071-
if (shift == max_shift<B>) {
1072+
if (shift == max_shift<hash_t, B>) {
10721073
auto fst = node->collisions();
10731074
auto lst = fst + node->collision_count();
10741075
for (; fst != lst; ++fst)
@@ -1090,7 +1091,7 @@ struct champ
10901091
}
10911092
return {nullptr, false};
10921093
} else {
1093-
auto idx = (hash & (mask<B> << shift)) >> shift;
1094+
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
10941095
auto bit = bitmap_t{1u} << idx;
10951096
if (node->nodemap() & bit) {
10961097
auto offset = node->children_count(bit);
@@ -1204,7 +1205,7 @@ struct champ
12041205
sub_result
12051206
do_sub(node_t* node, const K& k, hash_t hash, shift_t shift) const
12061207
{
1207-
if (shift == max_shift<B>) {
1208+
if (shift == max_shift<hash_t, B>) {
12081209
auto fst = node->collisions();
12091210
auto lst = fst + node->collision_count();
12101211
for (auto cur = fst; cur != lst; ++cur)
@@ -1227,7 +1228,7 @@ struct champ
12271228
#endif
12281229
#endif
12291230
} else {
1230-
auto idx = (hash & (mask<B> << shift)) >> shift;
1231+
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
12311232
auto bit = bitmap_t{1u} << idx;
12321233
if (node->nodemap() & bit) {
12331234
auto offset = node->children_count(bit);
@@ -1350,7 +1351,7 @@ struct champ
13501351
void* store) const
13511352
{
13521353
auto mutate = node->can_mutate(e);
1353-
if (shift == max_shift<B>) {
1354+
if (shift == max_shift<hash_t, B>) {
13541355
auto fst = node->collisions();
13551356
auto lst = fst + node->collision_count();
13561357
for (auto cur = fst; cur != lst; ++cur) {
@@ -1374,7 +1375,7 @@ struct champ
13741375
}
13751376
return {};
13761377
} else {
1377-
auto idx = (hash & (mask<B> << shift)) >> shift;
1378+
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
13781379
auto bit = bitmap_t{1u} << idx;
13791380
if (node->nodemap() & bit) {
13801381
auto offset = node->children_count(bit);
@@ -1511,7 +1512,7 @@ struct champ
15111512
{
15121513
if (a == b)
15131514
return true;
1514-
else if (depth == max_depth<B>) {
1515+
else if (depth == max_depth<hash_t, B>) {
15151516
auto nv = a->collision_count();
15161517
return nv == b->collision_count() &&
15171518
equals_collisions<Eq>(a->collisions(), b->collisions(), nv);

immer/detail/hamts/champ_iterator.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct champ_iterator
2626
{
2727
using tree_t = champ<T, Hash, Eq, MP, B>;
2828
using node_t = typename tree_t::node_t;
29+
using hash_t = typename node_t::hash_t;
2930

3031
champ_iterator() = default;
3132

@@ -67,7 +68,7 @@ struct champ_iterator
6768
T* cur_;
6869
T* end_;
6970
count_t depth_;
70-
node_t* const* path_[max_depth<B> + 1] = {
71+
node_t* const* path_[max_depth<hash_t, B> + 1] = {
7172
0,
7273
};
7374

@@ -79,15 +80,15 @@ struct champ_iterator
7980

8081
bool step_down()
8182
{
82-
if (depth_ < max_depth<B>) {
83+
if (depth_ < max_depth<hash_t, B>) {
8384
auto parent = *path_[depth_];
8485
assert(parent);
8586
if (parent->nodemap()) {
8687
++depth_;
8788
path_[depth_] = parent->children();
8889
auto child = *path_[depth_];
8990
assert(child);
90-
if (depth_ < max_depth<B>) {
91+
if (depth_ < max_depth<hash_t, B>) {
9192
if (child->datamap()) {
9293
cur_ = child->values();
9394
end_ = cur_ + child->data_count();
@@ -112,7 +113,7 @@ struct champ_iterator
112113
path_[depth_] = next;
113114
auto child = *path_[depth_];
114115
assert(child);
115-
if (depth_ < max_depth<B>) {
116+
if (depth_ < max_depth<hash_t, B>) {
116117
if (child->datamap()) {
117118
cur_ = child->values();
118119
end_ = cur_ + child->data_count();

immer/detail/hamts/node.hpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct node
4747
using edit_t = typename transience::edit;
4848
using value_t = T;
4949
using bitmap_t = typename get_bitmap_type<B>::type;
50+
using hash_t = decltype(Hash{}(std::declval<const T&>()));
5051

5152
enum class kind_t
5253
{
@@ -991,9 +992,9 @@ struct node
991992
static node_t*
992993
make_merged(shift_t shift, T v1, hash_t hash1, T v2, hash_t hash2)
993994
{
994-
if (shift < max_shift<B>) {
995-
auto idx1 = hash1 & (mask<B> << shift);
996-
auto idx2 = hash2 & (mask<B> << shift);
995+
if (shift < max_shift<hash_t, B>) {
996+
auto idx1 = hash1 & (mask<hash_t, B> << shift);
997+
auto idx2 = hash2 & (mask<hash_t, B> << shift);
997998
if (idx1 == idx2) {
998999
auto merged = make_merged(
9991000
shift + B, std::move(v1), hash1, std::move(v2), hash2);
@@ -1020,9 +1021,9 @@ struct node
10201021
static node_t* make_merged_e(
10211022
edit_t e, shift_t shift, T v1, hash_t hash1, T v2, hash_t hash2)
10221023
{
1023-
if (shift < max_shift<B>) {
1024-
auto idx1 = hash1 & (mask<B> << shift);
1025-
auto idx2 = hash2 & (mask<B> << shift);
1024+
if (shift < max_shift<hash_t, B>) {
1025+
auto idx1 = hash1 & (mask<hash_t, B> << shift);
1026+
auto idx2 = hash2 & (mask<hash_t, B> << shift);
10261027
if (idx1 == idx2) {
10271028
auto merged = make_merged_e(
10281029
e, shift + B, std::move(v1), hash1, std::move(v2), hash2);
@@ -1097,7 +1098,7 @@ struct node
10971098

10981099
static void delete_deep(node_t* p, shift_t s)
10991100
{
1100-
if (s == max_depth<B>)
1101+
if (s == max_depth<hash_t, B>)
11011102
delete_collision(p);
11021103
else {
11031104
auto fst = p->children();
@@ -1111,7 +1112,7 @@ struct node
11111112

11121113
static void delete_deep_shift(node_t* p, shift_t s)
11131114
{
1114-
if (s == max_shift<B>)
1115+
if (s == max_shift<hash_t, B>)
11151116
delete_collision(p);
11161117
else {
11171118
auto fst = p->children();

immer/extra/persist/detail/champ/output.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ struct output_pool_builder
6161
void visit(const Node* node, immer::detail::hamts::count_t depth)
6262
{
6363
using immer::detail::hamts::max_depth;
64+
using hash_t = typename Node::hash_t;
6465

65-
if (depth < max_depth<B>) {
66+
if (depth < max_depth<hash_t, B>) {
6667
visit_inner(node, depth);
6768
} else {
6869
visit_collision(node);

0 commit comments

Comments
 (0)