Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5d356d7
Added code for lil implementation. Currently, it is not functioning c…
NoahP-K Jun 20, 2025
e4958d0
Continued debugging, still not fully functional. Handles inserts from…
NoahP-K Jun 25, 2025
dbbccd3
The code still does not work. Just committing to back up the current …
NoahP-K Jun 27, 2025
d01e1ce
Updated insert to determine depth from the sum of the prefix length o…
NoahP-K Jun 30, 2025
e5665f1
Just some tweaking from the previous version. It currently is facing …
NoahP-K Jul 2, 2025
0fe2232
Committing before pulling from main
NoahP-K Jul 10, 2025
4454c3e
Merge branch 'main' of github.com:BU-DiSC/Qu-ART into noahpk/implemen…
NoahP-K Jul 10, 2025
d0f4997
Updated gitignore
NoahP-K Jul 10, 2025
9df268e
..
NoahP-K Jul 10, 2025
3de004d
fixed conflicts from earlier merge from main
ramananeesh Jul 11, 2025
36575ff
removed commented code
ramananeesh Jul 11, 2025
9cce11e
cleared warnings
ramananeesh Jul 11, 2025
37258e9
Started writing documentation file for lil insertion.
NoahP-K Jul 11, 2025
0a585a8
Wrote file to document lil insertion
NoahP-K Jul 14, 2025
df1eaa5
lil_insert.md contents have been moved to the wiki and the original f…
NoahP-K Jul 14, 2025
f657eea
Implemented new version of lil. Not yet functional.
NoahP-K Jul 15, 2025
50e44b8
Recent changes
NoahP-K Jul 17, 2025
3dde821
New changes
NoahP-K Jul 21, 2025
d6acd23
Unclear if the insert function works. The tree printing method shows …
NoahP-K Jul 22, 2025
7fd4f59
More debugging. The code passes basic tests, but will still need to t…
NoahP-K Jul 22, 2025
9c2d256
Re-committing without large workload file included.
NoahP-K Jul 24, 2025
96edd57
Merge branch 'main' of github.com:BU-DiSC/Qu-ART into noahpk/implemen…
NoahP-K Jul 24, 2025
c428fb0
Update main.cpp
NoahP-K Jul 25, 2025
4cf501d
Update main.cpp
NoahP-K Jul 25, 2025
e7a54f3
Update insert_profiling.cpp
NoahP-K Jul 25, 2025
a564c4d
Update QuART_lil.h
NoahP-K Jul 25, 2025
83294d3
Update Helper.h
NoahP-K Jul 25, 2025
051a23d
Fixed code according to PR comments.
NoahP-K Jul 26, 2025
52f7e0d
Merge branch 'noahpk/implement-lil-optimization-in-art' of github.com…
NoahP-K Jul 26, 2025
5e54c62
Minor change to deal with compilation error.
NoahP-K Jul 28, 2025
fc6649f
Fixed according to PR comments.
NoahP-K Jul 29, 2025
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
**/*.csv
build/
.DS_Store
.DS_Store
.vscode/launch.json
.vscode/tasks.json
198 changes: 181 additions & 17 deletions ART.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,148 @@
#include <stdexcept>

#include "ArtNode.h" // ArtNode definitions
#include "Chain.h" // Chain definitions
#include "Helper.h" // Helper functions
#include "ArtNode_lil.h"
#include "Chain.h" // Chain definitions
#include "Helper.h" // Helper functions

namespace ART {

class ART {
public:
ArtNode* root; // pointer to root node
ArtNode* fp; // fast path
ArtNode** fp_ref; // pointer to fp
unsigned fp_depth; // depth of fp
std::array<ArtNode*, maxPrefixLength> fp_path; // fp path
std::array<ArtNode**, maxPrefixLength>
fp_path_ref; // references to nodes on fp_path
size_t fp_path_length; // stores real length of fp path
ArtNode* fp_leaf;

// constructor
ART() { root = NULL; }
ART() {
root = NULL;
fp_path_length = 0;
fp = NULL;
}

void insert(uint8_t key[], uintptr_t value) {
insert(this, root, &root, key, 0, value, maxPrefixLength);
}

ArtNode* lookup(uint8_t key[]) {
return lookup(this, root, key, maxPrefixLength, 0, maxPrefixLength);
return lookup(root, key, maxPrefixLength, 0, maxPrefixLength);
}

Chain* rangelookup(uint8_t l_key[], unsigned l_keyLength, uint8_t h_key[],
uint8_t h_keyLength, unsigned depth,
unsigned maxKeyLength) {
return rangelookup(this, root, l_key, l_keyLength, h_key, h_keyLength,
depth, maxKeyLength);
uint8_t h_keyLength, unsigned maxKeyLength) {
return rangelookup(root, l_key, l_keyLength, h_key, h_keyLength,
maxKeyLength);
}

void printTree() { printTree(this->root, 0); }

// Method to verify the tail path after each insertion
// Returns true if the fast path (fp_path) leads to the correct fp and
// fp_leaf
bool verifyTailPath() {
if (this->fp_path_length == 0) {
// No fast path to verify
return true;
}

ArtNode* current = this->root;
// Traverse the tree following the fp_path
for (size_t i = 0; i < this->fp_path_length; i++) {
// If we're at the last node in the fp_path, check if it's the fp
Comment thread
NoahP-K marked this conversation as resolved.
// node
if (i == this->fp_path_length - 1) {
if (current == this->fp) {
// Check if the leaf value matches the expected fp_leaf
if (getLeafValue(maximum(current)) ==
getLeafValue(this->fp_leaf)) {
return true;
} else {
std::cerr << "Error: fp_leaf mismatch. Expected "
<< getLeafValue(maximum(current)) << ", got "
<< getLeafValue(this->fp_leaf) << "."
<< std::endl;
return false;
}
} else {
std::cerr << "Error: last node in fp_path is not the fp. "
"Expected "
<< static_cast<void*>(current) << ", got "
<< static_cast<void*>(this->fp) << "."
<< std::endl;
return false;
}
}

// Move to the rightmost child for each node type
switch (current->type) {
case NodeType4: {
Node4* node = static_cast<Node4*>(current);
if (node->count > 0) {
// Move to the last child (rightmost)
current = node->child[node->count - 1];
} else {
std::cerr << "Error: NodeType4 has no children."
<< std::endl;
return false;
}
break;
}
case NodeType16: {
Node16* node = static_cast<Node16*>(current);
if (node->count > 0) {
// Move to the last child (rightmost)
current = node->child[node->count - 1];
} else {
std::cerr << "Error: NodeType16 has no children."
<< std::endl;
return false;
}
break;
}
case NodeType48: {
Node48* node = static_cast<Node48*>(current);
unsigned pos = 255;
// Find the rightmost valid child
while (pos > 0 && node->childIndex[pos] == emptyMarker)
pos--;
if (node->childIndex[pos] != emptyMarker) {
current = node->child[node->childIndex[pos]];
} else {
std::cerr << "Error: NodeType48 has no valid children."
<< std::endl;
return false;
}
break;
}
case NodeType256: {
Node256* node = static_cast<Node256*>(current);
unsigned pos = 255;
// Find the rightmost valid child
while (pos > 0 && !node->child[pos]) pos--;
if (node->child[pos]) {
current = node->child[pos];
} else {
std::cerr << "Error: NodeType256 has no valid children."
<< std::endl;
return false;
}
break;
}
default:
std::cerr << "Error: Unknown node type." << std::endl;
return false;
}
}

// If we exit the loop without returning, the path is incorrect
std::cerr << "Error: fp_path does not lead to the fp." << std::endl;
return false;
}

private:
Expand Down Expand Up @@ -155,7 +268,7 @@ class ART {
}

// Lookup function, returns ArtNode
ArtNode* lookup(ART* tree, ArtNode* node, uint8_t key[], unsigned keyLength,
ArtNode* lookup(ArtNode* node, uint8_t key[], unsigned keyLength,
unsigned depth, unsigned maxKeyLength) {
// Find the node with a matching key, optimistic version

Expand Down Expand Up @@ -222,18 +335,17 @@ class ART {
// Leaf found, delete it in inner node
switch (node->type) {
case NodeType4:
static_cast<Node4*>(node)->eraseNode4(this, nodeRef, child);
static_cast<Node4*>(node)->eraseNode4(nodeRef, child);
break;
case NodeType16:
static_cast<Node16*>(node)->eraseNode16(this, nodeRef,
child);
static_cast<Node16*>(node)->eraseNode16(nodeRef, child);
break;
case NodeType48:
static_cast<Node48*>(node)->eraseNode48(this, nodeRef,
static_cast<Node48*>(node)->eraseNode48(nodeRef,
key[depth]);
break;
case NodeType256:
static_cast<Node256*>(node)->eraseNode256(this, nodeRef,
static_cast<Node256*>(node)->eraseNode256(nodeRef,
key[depth]);
break;
}
Expand All @@ -244,9 +356,8 @@ class ART {
}

// Range lookup function, returns a Chain of ArtNode
Chain* rangelookup(ART* tree, ArtNode* node, uint8_t l_key[],
unsigned l_keyLength, uint8_t h_key[],
uint8_t h_keyLength, unsigned depth,
Chain* rangelookup(ArtNode* node, uint8_t l_key[], unsigned l_keyLength,
uint8_t h_key[], uint8_t h_keyLength,
unsigned maxKeyLength) {
// Find the node with a matching key, optimistic version
Chain* queue =
Expand Down Expand Up @@ -321,5 +432,58 @@ class ART {
delete queue;
return result;
}

void printTree(ArtNode* node, int depth) {
if (!node) return;

// Indent based on depth
for (int i = 0; i < depth; i++) {
printf(" ");
}

if (isLeaf(node)) {
printf("Leaf(%lu)\n", getLeafValue(node));
return;
}

switch (node->type) {
case NodeType4: {
Node4* n = static_cast<Node4*>(node);
printf("Node4 [%p]\n", static_cast<void*>(n));
for (unsigned i = 0; i < n->count; i++) {
printTree(n->child[i], depth + 1);
}
break;
}
case NodeType16: {
Node16* n = static_cast<Node16*>(node);
printf("Node16 [%p]\n", static_cast<void*>(n));
for (unsigned i = 0; i < n->count; i++) {
printTree(n->child[i], depth + 1);
}
break;
}
case NodeType48: {
Node48* n = static_cast<Node48*>(node);
printf("Node48 [%p]\n", static_cast<void*>(n));
for (unsigned i = 0; i < 256; i++) {
if (n->childIndex[i] != emptyMarker) {
printTree(n->child[n->childIndex[i]], depth + 1);
}
}
break;
}
case NodeType256: {
Node256* n = static_cast<Node256*>(node);
printf("Node256 [%p]\n", static_cast<void*>(n));
for (unsigned i = 0; i < 256; i++) {
if (n->child[i]) {
printTree(n->child[i], depth + 1);
}
}
break;
}
}
}
};
} // namespace ART
Loading