Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support hash size that's not std::size_t #292

Merged
merged 1 commit into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions immer/detail/hamts/bits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ namespace detail {
namespace hamts {

using size_t = std::size_t;
using hash_t = std::size_t;
using bits_t = std::uint32_t;
using count_t = std::uint32_t;
using shift_t = std::uint32_t;
Expand Down Expand Up @@ -53,14 +52,14 @@ struct get_bitmap_type<4u>
template <bits_t B, typename T = count_t>
constexpr T branches = T{1u} << B;

template <bits_t B, typename T = size_t>
template <typename T, bits_t B>
constexpr T mask = branches<B, T> - 1u;

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

template <bits_t B, typename T = count_t>
constexpr T max_shift = max_depth<B, count_t> * B;
template <typename hash_t, bits_t B, typename T = count_t>
constexpr T max_shift = max_depth<hash_t, B, count_t> * B;

#define IMMER_HAS_BUILTIN_POPCOUNT 1

Expand Down
51 changes: 26 additions & 25 deletions immer/detail/hamts/champ.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ struct champ
using edit_t = typename MemoryPolicy::transience_t::edit;
using owner_t = typename MemoryPolicy::transience_t::owner;
using bitmap_t = typename get_bitmap_type<B>::type;
using hash_t = typename node_t::hash_t;

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

Expand Down Expand Up @@ -202,7 +203,7 @@ struct champ
size_t hash_mask) const
{
auto result = std::size_t{};
if (depth < max_depth<B>) {
if (depth < max_depth<hash_t, B>) {
auto nodemap = node->nodemap();
if (nodemap) {
auto fst = node->children();
Expand All @@ -213,7 +214,7 @@ struct champ
do_check_champ(child,
depth + 1,
path_hash | (idx << (B * depth)),
(hash_mask << B) | mask<B>);
(hash_mask << B) | mask<hash_t, B>);
}
}
}
Expand Down Expand Up @@ -248,7 +249,7 @@ struct champ
// due some value being moved out of the champ when it should have not.
bool check_champ() const
{
auto r = do_check_champ(root, 0, 0, mask<B>);
auto r = do_check_champ(root, 0, 0, mask<hash_t, B>);
// assert(r == size);
return r == size;
}
Expand All @@ -258,7 +259,7 @@ struct champ
node_t* node,
count_t depth) const
{
if (depth < max_depth<B>) {
if (depth < max_depth<hash_t, B>) {
++stats.inner_node_count;
stats.inner_node_w_value_count += node->data_count() > 0;
stats.inner_node_w_child_count += node->children_count() > 0;
Expand Down Expand Up @@ -317,7 +318,7 @@ struct champ
void
for_each_chunk_traversal(const node_t* node, count_t depth, Fn&& fn) const
{
if (depth < max_depth<B>) {
if (depth < max_depth<hash_t, B>) {
auto datamap = node->datamap();
if (datamap)
fn(node->values(), node->values() + node->data_count());
Expand Down Expand Up @@ -348,7 +349,7 @@ struct champ
{
if (old_node == new_node)
return;
if (depth < max_depth<B>) {
if (depth < max_depth<hash_t, B>) {
auto old_nodemap = old_node->nodemap();
auto new_nodemap = new_node->nodemap();
auto old_datamap = old_node->datamap();
Expand Down Expand Up @@ -537,8 +538,8 @@ struct champ
{
auto node = root;
auto hash = Hash{}(k);
for (auto i = count_t{}; i < max_depth<B>; ++i) {
auto bit = bitmap_t{1u} << (hash & mask<B>);
for (auto i = count_t{}; i < max_depth<hash_t, B>; ++i) {
auto bit = bitmap_t{1u} << (hash & mask<hash_t, B>);
if (node->nodemap() & bit) {
auto offset = node->children_count(bit);
node = node->children()[offset];
Expand Down Expand Up @@ -571,7 +572,7 @@ struct champ
add_result do_add(node_t* node, T v, hash_t hash, shift_t shift) const
{
assert(node);
if (shift == max_shift<B>) {
if (shift == max_shift<hash_t, B>) {
auto fst = node->collisions();
auto lst = fst + node->collision_count();
for (; fst != lst; ++fst)
Expand All @@ -581,7 +582,7 @@ struct champ
false};
return {node_t::copy_collision_insert(node, std::move(v)), true};
} else {
auto idx = (hash & (mask<B> << shift)) >> shift;
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
auto bit = bitmap_t{1u} << idx;
if (node->nodemap() & bit) {
auto offset = node->children_count(bit);
Expand Down Expand Up @@ -644,7 +645,7 @@ struct champ
do_add_mut(edit_t e, node_t* node, T v, hash_t hash, shift_t shift) const
{
assert(node);
if (shift == max_shift<B>) {
if (shift == max_shift<hash_t, B>) {
auto fst = node->collisions();
auto lst = fst + node->collision_count();
for (; fst != lst; ++fst)
Expand All @@ -663,7 +664,7 @@ struct champ
: node_t::copy_collision_insert(node, std::move(v));
return {node_t::owned(r, e), true, mutate};
} else {
auto idx = (hash & (mask<B> << shift)) >> shift;
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
auto bit = bitmap_t{1u} << idx;
if (node->nodemap() & bit) {
auto offset = node->children_count(bit);
Expand Down Expand Up @@ -756,7 +757,7 @@ struct champ
update_result
do_update(node_t* node, K&& k, Fn&& fn, hash_t hash, shift_t shift) const
{
if (shift == max_shift<B>) {
if (shift == max_shift<hash_t, B>) {
auto fst = node->collisions();
auto lst = fst + node->collision_count();
for (; fst != lst; ++fst)
Expand All @@ -774,7 +775,7 @@ struct champ
std::forward<Fn>(fn)(Default{}()))),
true};
} else {
auto idx = (hash & (mask<B> << shift)) >> shift;
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
auto bit = bitmap_t{1u} << idx;
if (node->nodemap() & bit) {
auto offset = node->children_count(bit);
Expand Down Expand Up @@ -851,7 +852,7 @@ struct champ
node_t* do_update_if_exists(
node_t* node, K&& k, Fn&& fn, hash_t hash, shift_t shift) const
{
if (shift == max_shift<B>) {
if (shift == max_shift<hash_t, B>) {
auto fst = node->collisions();
auto lst = fst + node->collision_count();
for (; fst != lst; ++fst)
Expand All @@ -864,7 +865,7 @@ struct champ
Project{}(detail::as_const(*fst)))));
return nullptr;
} else {
auto idx = (hash & (mask<B> << shift)) >> shift;
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
auto bit = bitmap_t{1u} << idx;
if (node->nodemap() & bit) {
auto offset = node->children_count(bit);
Expand Down Expand Up @@ -929,7 +930,7 @@ struct champ
hash_t hash,
shift_t shift) const
{
if (shift == max_shift<B>) {
if (shift == max_shift<hash_t, B>) {
auto fst = node->collisions();
auto lst = fst + node->collision_count();
for (; fst != lst; ++fst)
Expand All @@ -956,7 +957,7 @@ struct champ
: node_t::copy_collision_insert(node, std::move(v));
return {node_t::owned(r, e), true, mutate};
} else {
auto idx = (hash & (mask<B> << shift)) >> shift;
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
auto bit = bitmap_t{1u} << idx;
if (node->nodemap() & bit) {
auto offset = node->children_count(bit);
Expand Down Expand Up @@ -1068,7 +1069,7 @@ struct champ
hash_t hash,
shift_t shift) const
{
if (shift == max_shift<B>) {
if (shift == max_shift<hash_t, B>) {
auto fst = node->collisions();
auto lst = fst + node->collision_count();
for (; fst != lst; ++fst)
Expand All @@ -1090,7 +1091,7 @@ struct champ
}
return {nullptr, false};
} else {
auto idx = (hash & (mask<B> << shift)) >> shift;
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
auto bit = bitmap_t{1u} << idx;
if (node->nodemap() & bit) {
auto offset = node->children_count(bit);
Expand Down Expand Up @@ -1204,7 +1205,7 @@ struct champ
sub_result
do_sub(node_t* node, const K& k, hash_t hash, shift_t shift) const
{
if (shift == max_shift<B>) {
if (shift == max_shift<hash_t, B>) {
auto fst = node->collisions();
auto lst = fst + node->collision_count();
for (auto cur = fst; cur != lst; ++cur)
Expand All @@ -1227,7 +1228,7 @@ struct champ
#endif
#endif
} else {
auto idx = (hash & (mask<B> << shift)) >> shift;
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
auto bit = bitmap_t{1u} << idx;
if (node->nodemap() & bit) {
auto offset = node->children_count(bit);
Expand Down Expand Up @@ -1350,7 +1351,7 @@ struct champ
void* store) const
{
auto mutate = node->can_mutate(e);
if (shift == max_shift<B>) {
if (shift == max_shift<hash_t, B>) {
auto fst = node->collisions();
auto lst = fst + node->collision_count();
for (auto cur = fst; cur != lst; ++cur) {
Expand All @@ -1374,7 +1375,7 @@ struct champ
}
return {};
} else {
auto idx = (hash & (mask<B> << shift)) >> shift;
auto idx = (hash & (mask<hash_t, B> << shift)) >> shift;
auto bit = bitmap_t{1u} << idx;
if (node->nodemap() & bit) {
auto offset = node->children_count(bit);
Expand Down Expand Up @@ -1511,7 +1512,7 @@ struct champ
{
if (a == b)
return true;
else if (depth == max_depth<B>) {
else if (depth == max_depth<hash_t, B>) {
auto nv = a->collision_count();
return nv == b->collision_count() &&
equals_collisions<Eq>(a->collisions(), b->collisions(), nv);
Expand Down
9 changes: 5 additions & 4 deletions immer/detail/hamts/champ_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct champ_iterator
{
using tree_t = champ<T, Hash, Eq, MP, B>;
using node_t = typename tree_t::node_t;
using hash_t = typename node_t::hash_t;

champ_iterator() = default;

Expand Down Expand Up @@ -67,7 +68,7 @@ struct champ_iterator
T* cur_;
T* end_;
count_t depth_;
node_t* const* path_[max_depth<B> + 1] = {
node_t* const* path_[max_depth<hash_t, B> + 1] = {
0,
};

Expand All @@ -79,15 +80,15 @@ struct champ_iterator

bool step_down()
{
if (depth_ < max_depth<B>) {
if (depth_ < max_depth<hash_t, B>) {
auto parent = *path_[depth_];
assert(parent);
if (parent->nodemap()) {
++depth_;
path_[depth_] = parent->children();
auto child = *path_[depth_];
assert(child);
if (depth_ < max_depth<B>) {
if (depth_ < max_depth<hash_t, B>) {
if (child->datamap()) {
cur_ = child->values();
end_ = cur_ + child->data_count();
Expand All @@ -112,7 +113,7 @@ struct champ_iterator
path_[depth_] = next;
auto child = *path_[depth_];
assert(child);
if (depth_ < max_depth<B>) {
if (depth_ < max_depth<hash_t, B>) {
if (child->datamap()) {
cur_ = child->values();
end_ = cur_ + child->data_count();
Expand Down
17 changes: 9 additions & 8 deletions immer/detail/hamts/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct node
using edit_t = typename transience::edit;
using value_t = T;
using bitmap_t = typename get_bitmap_type<B>::type;
using hash_t = decltype(Hash{}(std::declval<const T&>()));

enum class kind_t
{
Expand Down Expand Up @@ -991,9 +992,9 @@ struct node
static node_t*
make_merged(shift_t shift, T v1, hash_t hash1, T v2, hash_t hash2)
{
if (shift < max_shift<B>) {
auto idx1 = hash1 & (mask<B> << shift);
auto idx2 = hash2 & (mask<B> << shift);
if (shift < max_shift<hash_t, B>) {
auto idx1 = hash1 & (mask<hash_t, B> << shift);
auto idx2 = hash2 & (mask<hash_t, B> << shift);
if (idx1 == idx2) {
auto merged = make_merged(
shift + B, std::move(v1), hash1, std::move(v2), hash2);
Expand All @@ -1020,9 +1021,9 @@ struct node
static node_t* make_merged_e(
edit_t e, shift_t shift, T v1, hash_t hash1, T v2, hash_t hash2)
{
if (shift < max_shift<B>) {
auto idx1 = hash1 & (mask<B> << shift);
auto idx2 = hash2 & (mask<B> << shift);
if (shift < max_shift<hash_t, B>) {
auto idx1 = hash1 & (mask<hash_t, B> << shift);
auto idx2 = hash2 & (mask<hash_t, B> << shift);
if (idx1 == idx2) {
auto merged = make_merged_e(
e, shift + B, std::move(v1), hash1, std::move(v2), hash2);
Expand Down Expand Up @@ -1097,7 +1098,7 @@ struct node

static void delete_deep(node_t* p, shift_t s)
{
if (s == max_depth<B>)
if (s == max_depth<hash_t, B>)
delete_collision(p);
else {
auto fst = p->children();
Expand All @@ -1111,7 +1112,7 @@ struct node

static void delete_deep_shift(node_t* p, shift_t s)
{
if (s == max_shift<B>)
if (s == max_shift<hash_t, B>)
delete_collision(p);
else {
auto fst = p->children();
Expand Down
3 changes: 2 additions & 1 deletion immer/extra/persist/detail/champ/output.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ struct output_pool_builder
void visit(const Node* node, immer::detail::hamts::count_t depth)
{
using immer::detail::hamts::max_depth;
using hash_t = typename Node::hash_t;

if (depth < max_depth<B>) {
if (depth < max_depth<hash_t, B>) {
visit_inner(node, depth);
} else {
visit_collision(node);
Expand Down
Loading
Loading