Use a bitset to speed up Node256 scans
This commit is contained in:
@@ -71,7 +71,66 @@ struct Node48 : Node {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PointerSet {
|
||||||
|
bool test(int i) const {
|
||||||
|
assert(0 <= i);
|
||||||
|
assert(i < 256);
|
||||||
|
if (i < 128) {
|
||||||
|
return (lo >> i) & 1;
|
||||||
|
} else {
|
||||||
|
return (hi >> (i - 128)) & 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(int i) {
|
||||||
|
assert(0 <= i);
|
||||||
|
assert(i < 256);
|
||||||
|
if (i < 128) {
|
||||||
|
lo |= __uint128_t(1) << i;
|
||||||
|
} else {
|
||||||
|
hi |= __uint128_t(1) << (i - 128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int firstSetGeq(int i) const {
|
||||||
|
if (i < 128) {
|
||||||
|
int a = std::countr_zero(lo >> i);
|
||||||
|
if (a < 128) {
|
||||||
|
assert(i + a < 128);
|
||||||
|
return i + a;
|
||||||
|
}
|
||||||
|
i = 128;
|
||||||
|
}
|
||||||
|
int b = std::countr_zero(hi >> (i - 128));
|
||||||
|
if (b < 128) {
|
||||||
|
assert(i + b < 256);
|
||||||
|
return i + b;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastSetLeq(int i) const {
|
||||||
|
if (i >= 128) {
|
||||||
|
int a = std::countl_zero(hi << (255 - i));
|
||||||
|
if (a < 128) {
|
||||||
|
return i - a;
|
||||||
|
}
|
||||||
|
i = 127;
|
||||||
|
}
|
||||||
|
int b = std::countl_zero(lo << (127 - i));
|
||||||
|
if (b < 128) {
|
||||||
|
return i - b;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
__uint128_t lo = 0;
|
||||||
|
__uint128_t hi = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct Node256 : Node {
|
struct Node256 : Node {
|
||||||
|
PointerSet pointerSet;
|
||||||
Node *children[256] = {};
|
Node *children[256] = {};
|
||||||
Node256() { this->type = Type::Node256; }
|
Node256() { this->type = Type::Node256; }
|
||||||
};
|
};
|
||||||
@@ -334,11 +393,12 @@ int getChildGeq(Node *self, int child) {
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
auto *self256 = static_cast<Node256 *>(self);
|
auto *self256 = static_cast<Node256 *>(self);
|
||||||
for (int i = child; i < 256; ++i) {
|
#ifndef NDEBUG
|
||||||
if (self256->children[i]) {
|
for (int i = 0; i < 256; ++i) {
|
||||||
return i;
|
assert(self256->pointerSet.test(i) == (self256->children[i] != nullptr));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
return self256->pointerSet.firstSetGeq(child);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -444,11 +504,12 @@ int getChildLeq(Node *self, int child) {
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
auto *self256 = static_cast<Node256 *>(self);
|
auto *self256 = static_cast<Node256 *>(self);
|
||||||
for (int i = child; i >= 0; --i) {
|
#ifndef NDEBUG
|
||||||
if (self256->children[i]) {
|
for (int i = 0; i < 256; ++i) {
|
||||||
return i;
|
assert(self256->pointerSet.test(i) == (self256->children[i] != nullptr));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
return self256->pointerSet.lastSetLeq(child);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -459,6 +520,8 @@ void setChildrenParents(Node *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Caller is responsible for assigning a non-null pointer to the returned
|
||||||
|
// reference if null
|
||||||
Node *&getOrCreateChild(Node *&self, uint8_t index) {
|
Node *&getOrCreateChild(Node *&self, uint8_t index) {
|
||||||
if (self->type == Type::Node4) {
|
if (self->type == Type::Node4) {
|
||||||
auto *self4 = static_cast<Node4 *>(self);
|
auto *self4 = static_cast<Node4 *>(self);
|
||||||
@@ -545,6 +608,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index) {
|
|||||||
memcpy((void *)newSelf, self, offsetof(Node, type));
|
memcpy((void *)newSelf, self, offsetof(Node, type));
|
||||||
for (int i = 0; i < 256; ++i) {
|
for (int i = 0; i < 256; ++i) {
|
||||||
if (self48->index[i] >= 0) {
|
if (self48->index[i] >= 0) {
|
||||||
|
newSelf->pointerSet.set(i);
|
||||||
newSelf->children[i] = self48->children[self48->index[i]];
|
newSelf->children[i] = self48->children[self48->index[i]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -565,6 +629,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index) {
|
|||||||
if (!self256->children[index]) {
|
if (!self256->children[index]) {
|
||||||
++self->numChildren;
|
++self->numChildren;
|
||||||
}
|
}
|
||||||
|
self256->pointerSet.set(index);
|
||||||
return self256->children[index];
|
return self256->children[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user