Skip to content

Commit 4c41f12

Browse files
committed
Added QuART_tail under trees and added implementations of tailInsertNodeX methods
1 parent 220f0d7 commit 4c41f12

3 files changed

Lines changed: 498 additions & 9 deletions

File tree

‎ART.h‎

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ namespace ART {
3434

3535
class ART {
3636
public:
37-
ArtNode* root; // pointer to root node of tree
38-
ArtNode* fp; // pointer to fast path node
39-
std::array<ArtNode*, maxPrefixLength> fp_path; // path that leads to fp
40-
size_t fp_path_length; // stores length of fp path
41-
ArtNode* fp_leaf; // pointer to leaf node in fast path
42-
size_t fp_depth; // depth that will be used during fp insertion
43-
ArtNode** fp_ref; // reference to fp node, used for insertion
37+
ArtNode* root; // pointer to root node of tree
38+
ArtNode* fp; // pointer to fast path node
39+
std::array<ArtNode*, maxPrefixLength> fp_path; // path that leads to fp
40+
size_t fp_path_length; // stores length of fp path
41+
ArtNode* fp_leaf; // pointer to leaf node in fast path
42+
size_t fp_depth; // depth that will be used during fp insertion
43+
ArtNode** fp_ref; // reference to fp node, used for insertion
4444

4545
// constructor
4646
ART()
@@ -50,8 +50,7 @@ class ART {
5050
fp_path_length(0),
5151
fp_leaf(nullptr),
5252
fp_depth(0),
53-
fp_ref(nullptr)
54-
{}
53+
fp_ref(nullptr) {}
5554

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

‎ArtNodeNewMethods.cpp‎

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
#include "ART.h"
2+
#include "ArtNode.h"
3+
4+
/*
5+
* QuART related insertNodeX methods
6+
*/
7+
8+
namespace ART {
9+
// fp insert method for Node4
10+
void Node4::tailInsertNode4(ART* tree, ArtNode** nodeRef, uint8_t keyByte,
11+
ArtNode* child,
12+
std::array<ArtNode*, maxPrefixLength>& temp_fp_path,
13+
size_t& temp_fp_path_length, size_t depth_prev) {
14+
// Insert leaf into inner node
15+
if (this->count < 4) {
16+
// Insert element
17+
unsigned pos;
18+
for (pos = 0; (pos < this->count) && (this->key[pos] < keyByte); pos++)
19+
;
20+
memmove(this->key + pos + 1, this->key + pos, this->count - pos);
21+
memmove(this->child + pos + 1, this->child + pos,
22+
(this->count - pos) * sizeof(uintptr_t));
23+
this->key[pos] = keyByte;
24+
this->child[pos] = child;
25+
26+
// If what's being inserted is a leaf
27+
if (isLeaf(child)) {
28+
// If the new value is greater than or equal to the current fp_leaf,
29+
// update the fp_leaf, fp and fp_path
30+
if (getLeafValue(child) >= getLeafValue(tree->fp_leaf)) {
31+
tree->fp_leaf = child;
32+
tree->fp = temp_fp_path[temp_fp_path_length - 1];
33+
tree->fp_path = temp_fp_path;
34+
tree->fp_path_length =
35+
temp_fp_path_length; // update fp_path size
36+
tree->fp_depth = depth_prev;
37+
tree->fp_ref = nodeRef;
38+
}
39+
}
40+
41+
this->count++;
42+
} else {
43+
// Grow to Node16
44+
Node16* newNode = new Node16();
45+
*nodeRef = newNode;
46+
newNode->count = 4;
47+
copyPrefix(this, newNode);
48+
for (unsigned i = 0; i < 4; i++)
49+
newNode->key[i] = flipSign(this->key[i]);
50+
memcpy(newNode->child, this->child, this->count * sizeof(uintptr_t));
51+
52+
// The sizes of temp_fp_path and fp_path before operations
53+
int temp_fp_path_length_old = temp_fp_path_length;
54+
int fp_path_length_old = tree->fp_path_length;
55+
// If the changing node is on the fp_path
56+
if (temp_fp_path_length_old <= fp_path_length_old &&
57+
tree->fp_path[temp_fp_path_length_old - 1] == this) {
58+
// Change the node to the newNode which has a greater capacity
59+
temp_fp_path[temp_fp_path_length_old - 1] = newNode;
60+
// If the new value doesn't create a new fp_leaf, restore the
61+
// remaining part of the fp_path
62+
if (getLeafValue(child) < getLeafValue(tree->fp_leaf)) {
63+
// create a deep copy of remainder of fp_path here
64+
std::array<ArtNode*, maxPrefixLength> fp_path_remainder;
65+
std::copy(tree->fp_path.begin() + temp_fp_path_length_old,
66+
tree->fp_path.end(), fp_path_remainder.begin());
67+
tree->fp_path = temp_fp_path; // update fp_path
68+
tree->fp_path_length =
69+
temp_fp_path_length_old; // update fp_path size
70+
// Add the remaining part of the fp_path
71+
for (int i = 0;
72+
i < fp_path_length_old - temp_fp_path_length_old; i++) {
73+
tree->fp_path[i + temp_fp_path_length_old] =
74+
fp_path_remainder[i];
75+
tree->fp_path_length++;
76+
}
77+
tree->fp = tree->fp_path[tree->fp_path_length - 1];
78+
}
79+
}
80+
81+
delete this;
82+
return newNode->tailInsertNode16(tree, nodeRef, keyByte, child,
83+
temp_fp_path, temp_fp_path_length,
84+
depth_prev);
85+
}
86+
}
87+
88+
// fp insert method for Node16
89+
void Node16::tailInsertNode16(
90+
ART* tree, ArtNode** nodeRef, uint8_t keyByte, ArtNode* child,
91+
std::array<ArtNode*, maxPrefixLength>& temp_fp_path,
92+
size_t& temp_fp_path_length, size_t depth_prev) {
93+
// Insert leaf into inner node
94+
if (this->count < 16) {
95+
// Insert element
96+
uint8_t keyByteFlipped = flipSign(keyByte);
97+
__m128i cmp = _mm_cmplt_epi8(
98+
_mm_set1_epi8(keyByteFlipped),
99+
_mm_loadu_si128(reinterpret_cast<__m128i*>(this->key)));
100+
uint16_t bitfield =
101+
_mm_movemask_epi8(cmp) & (0xFFFF >> (16 - this->count));
102+
unsigned pos = bitfield ? ctz(bitfield) : this->count;
103+
memmove(this->key + pos + 1, this->key + pos, this->count - pos);
104+
memmove(this->child + pos + 1, this->child + pos,
105+
(this->count - pos) * sizeof(uintptr_t));
106+
107+
this->key[pos] = keyByteFlipped;
108+
this->child[pos] = child;
109+
110+
// If what's being inserted is a leaf
111+
if (isLeaf(child)) {
112+
// If the new value is greater than or equal to the current fp_leaf,
113+
// update the fp_leaf, fp and fp_path
114+
if (getLeafValue(child) >= getLeafValue(tree->fp_leaf)) {
115+
tree->fp_leaf = child;
116+
tree->fp = temp_fp_path[temp_fp_path_length - 1];
117+
tree->fp_path = temp_fp_path;
118+
tree->fp_path_length = temp_fp_path_length;
119+
tree->fp_depth = depth_prev;
120+
tree->fp_ref = nodeRef;
121+
}
122+
}
123+
124+
this->count++;
125+
} else {
126+
// Grow to Node48
127+
Node48* newNode = new Node48();
128+
*nodeRef = newNode;
129+
memcpy(newNode->child, this->child, this->count * sizeof(uintptr_t));
130+
for (unsigned i = 0; i < this->count; i++)
131+
newNode->childIndex[flipSign(this->key[i])] = i;
132+
copyPrefix(this, newNode);
133+
newNode->count = this->count;
134+
135+
// The sizes of temp_fp_path and fp_path before operations
136+
int temp_fp_path_length_old = temp_fp_path_length;
137+
int fp_path_length_old = tree->fp_path_length;
138+
// If the changing node is on the fp_path
139+
if (temp_fp_path_length_old <= fp_path_length_old &&
140+
tree->fp_path[temp_fp_path_length_old - 1] == this) {
141+
// Change the node to the newNode which has a greater capacity
142+
temp_fp_path[temp_fp_path_length_old - 1] = newNode;
143+
// If the new value doesn't create a new fp_leaf, restore the
144+
// remaining part of the fp_path
145+
if (getLeafValue(child) < getLeafValue(tree->fp_leaf)) {
146+
// create a deep copy of remainder of fp_path here
147+
std::array<ArtNode*, maxPrefixLength> fp_path_remainder;
148+
std::copy(tree->fp_path.begin() + temp_fp_path_length_old,
149+
tree->fp_path.end(), fp_path_remainder.begin());
150+
tree->fp_path = temp_fp_path; // update fp_path
151+
tree->fp_path_length =
152+
temp_fp_path_length_old; // update fp_path size
153+
// Add the remaining part of the fp_path
154+
for (int i = 0;
155+
i < fp_path_length_old - temp_fp_path_length_old; i++) {
156+
tree->fp_path[i + temp_fp_path_length_old] =
157+
fp_path_remainder[i];
158+
tree->fp_path_length++;
159+
}
160+
tree->fp = tree->fp_path[tree->fp_path_length -
161+
1]; // update the fp pointer
162+
}
163+
}
164+
165+
delete this;
166+
return newNode->tailInsertNode48(tree, nodeRef, keyByte, child,
167+
temp_fp_path, temp_fp_path_length,
168+
depth_prev);
169+
}
170+
}
171+
172+
// fp insert method for Node48
173+
void Node48::tailInsertNode48(
174+
ART* tree, ArtNode** nodeRef, uint8_t keyByte, ArtNode* child,
175+
std::array<ArtNode*, maxPrefixLength>& temp_fp_path,
176+
size_t& temp_fp_path_length, size_t depth_prev) {
177+
// Insert leaf into inner node
178+
if (this->count < 48) {
179+
// Insert element
180+
unsigned pos = this->count;
181+
if (this->child[pos])
182+
for (pos = 0; this->child[pos] != NULL; pos++)
183+
;
184+
this->child[pos] = child;
185+
this->childIndex[keyByte] = pos;
186+
this->count++;
187+
188+
// If what's being inserted is a leaf
189+
if (isLeaf(child)) {
190+
// If the new value is greater than or equal to the current fp_leaf,
191+
// update the fp_leaf, fp and fp_path
192+
if (getLeafValue(child) >= getLeafValue(tree->fp_leaf)) {
193+
tree->fp_leaf = child;
194+
tree->fp = temp_fp_path[temp_fp_path_length - 1];
195+
tree->fp_path = temp_fp_path;
196+
tree->fp_path_length = temp_fp_path_length;
197+
tree->fp_depth = depth_prev;
198+
tree->fp_ref = nodeRef;
199+
}
200+
}
201+
202+
} else {
203+
// Grow to Node256
204+
Node256* newNode = new Node256();
205+
for (unsigned i = 0; i < 256; i++)
206+
if (this->childIndex[i] != 48)
207+
newNode->child[i] = this->child[this->childIndex[i]];
208+
newNode->count = this->count;
209+
copyPrefix(this, newNode);
210+
*nodeRef = newNode;
211+
212+
// The sizes of temp_fp_path and fp_path before operations
213+
int temp_fp_path_length_old = temp_fp_path_length;
214+
int fp_path_length_old = tree->fp_path_length;
215+
// If the changing node is on the fp_path
216+
if (temp_fp_path_length_old <= fp_path_length_old &&
217+
tree->fp_path[temp_fp_path_length_old - 1] == this) {
218+
// Change the node to the newNode which has a greater capacity
219+
temp_fp_path[temp_fp_path_length_old - 1] = newNode;
220+
// If the new value doesn't create a new fp_leaf, restore the
221+
// remaining part of the fp_path
222+
if (getLeafValue(child) < getLeafValue(tree->fp_leaf)) {
223+
// create a deep copy of remainder of fp_path here
224+
std::array<ArtNode*, maxPrefixLength> fp_path_remainder;
225+
std::copy(tree->fp_path.begin() + temp_fp_path_length_old,
226+
tree->fp_path.end(), fp_path_remainder.begin());
227+
tree->fp_path = temp_fp_path; // update fp_path
228+
tree->fp_path_length =
229+
temp_fp_path_length_old; // update fp_path size
230+
// Add the remaining part of the fp_path
231+
for (int i = 0;
232+
i < fp_path_length_old - temp_fp_path_length_old; i++) {
233+
tree->fp_path[i + temp_fp_path_length_old] =
234+
fp_path_remainder[i];
235+
tree->fp_path_length++;
236+
}
237+
tree->fp = tree->fp_path[tree->fp_path_length -
238+
1]; // update the fp pointer
239+
}
240+
}
241+
242+
delete this;
243+
return newNode->tailInsertNode256(tree, nodeRef, keyByte, child,
244+
temp_fp_path, temp_fp_path_length,
245+
depth_prev);
246+
}
247+
}
248+
249+
// fp insert method for Node256
250+
void Node256::tailInsertNode256(
251+
ART* tree, ArtNode** nodeRef, uint8_t keyByte, ArtNode* child,
252+
std::array<ArtNode*, maxPrefixLength>& temp_fp_path,
253+
size_t& temp_fp_path_length, size_t depth_prev) {
254+
// Insert leaf into inner node
255+
this->count++;
256+
this->child[keyByte] = child;
257+
258+
// If what's being inserted is a leaf
259+
if (isLeaf(child)) {
260+
// If the new value is greater than or equal to the current fp_leaf,
261+
// update the fp_leaf, fp and fp_path
262+
if (getLeafValue(child) >= getLeafValue(tree->fp_leaf)) {
263+
tree->fp_leaf = child;
264+
tree->fp = temp_fp_path[temp_fp_path_length - 1];
265+
tree->fp_path = temp_fp_path;
266+
tree->fp_path_length = temp_fp_path_length;
267+
tree->fp_depth = depth_prev;
268+
tree->fp_ref = nodeRef;
269+
}
270+
}
271+
}
272+
} // namespace ART

0 commit comments

Comments
 (0)