Skip to content

Commit 6c3bdeb

Browse files
committed
Power of 2
1 parent fc48350 commit 6c3bdeb

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

src/main/java/org/tinspin/index/qthypercube/QuadTreeKD.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.function.Predicate;
2222

2323
import org.tinspin.index.*;
24+
import org.tinspin.index.util.MathTools;
2425
import org.tinspin.index.util.StringBuilderLn;
2526

2627
/**
@@ -94,7 +95,9 @@ public void insert(double[] key, T value) {
9495
PointEntry<T> e = new PointEntry<>(key, value);
9596
if (root == null) {
9697
// We calculate a better radius when adding a second point.
97-
root = new QNode<>(key.clone(), INITIAL_RADIUS);
98+
// We align the center to a power of two. That reduces precision problems when
99+
// creating subnode centers.
100+
root = new QNode<>(MathTools.floorPowerOfTwoCopy(key), INITIAL_RADIUS);
98101
}
99102
if (root.getRadius() == INITIAL_RADIUS) {
100103
adjustRootSize(key);
@@ -113,10 +116,17 @@ private void adjustRootSize(double[] key) {
113116
return;
114117
}
115118
if (root.getRadius() == INITIAL_RADIUS) {
116-
// We just use Euclidean here, that should be good enough in all cases.
117-
double dist = PointDistance.L2.dist(key, root.getCenter());
118-
if (dist > 0) {
119-
root.adjustRadius(2 * dist);
119+
// Root size has not been initialized yet.
120+
// We start by getting the maximum horizontal distance between the node center and any point in the node
121+
double dMax = MathTools.maxDelta(key, root.getCenter());
122+
for (int i = 0; i < root.getEntries().size(); i++) {
123+
dMax = Math.max(dMax, MathTools.maxDelta(root.getEntries().get(i).point(), root.getCenter()));
124+
}
125+
// We calculate the minimum required radius that is also a power of two.
126+
// This radius can be divided by 2 many times without precision problems.
127+
double radius = MathTools.ceilPowerOfTwo(dMax + QUtil.EPS_MUL);
128+
if (radius > 0) {
129+
root.adjustRadius(radius);
120130
} else if (root.getEntries().size() >= maxNodeSize - 1) {
121131
// we just set an arbitrary radius here
122132
root.adjustRadius(1000);

src/main/java/org/tinspin/index/qthypercube2/QuadTreeKD2.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ public void insert(double[] key, T value) {
109109
PointEntry<T> e = new PointEntry<>(key, value);
110110
if (root == null) {
111111
// We calculate a better radius when adding a second point.
112+
// We align the center to a power of two. That reduces precision problems when
113+
// creating subnode centers.
112114
root = new QNode<>(MathTools.floorPowerOfTwoCopy(key), INITIAL_RADIUS);
113115
}
114116
if (root.getRadius() == INITIAL_RADIUS) {
@@ -128,10 +130,14 @@ private void adjustRootSize(double[] key) {
128130
return;
129131
}
130132
if (root.getRadius() == INITIAL_RADIUS) {
133+
// Root size has not been initialized yet.
134+
// We start by getting the maximum horizontal distance between the node center and any point in the node
131135
double dMax = MathTools.maxDelta(key, root.getCenter());
132136
for (int i = 0; i < root.getValueCount(); i++) {
133137
dMax = Math.max(dMax, MathTools.maxDelta(root.getValues()[i].point(), root.getCenter()));
134138
}
139+
// We calculate the minimum required radius that is also a power of two.
140+
// This radius can be divided by 2 many times without precision problems.
135141
double radius = MathTools.ceilPowerOfTwo(dMax + QUtil.EPS_MUL);
136142
if (radius > 0) {
137143
root.adjustRadius(radius);

0 commit comments

Comments
 (0)