Skip to content

Commit 9b105f4

Browse files
committed
XorBinaryFuse8 failed to construct on some data, at around 11511 entries #32
1 parent 85fda9d commit 9b105f4

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

fastfilter/src/main/java/org/fastfilter/utils/Hash.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,16 @@ public static int reduce(int hash, int n) {
3535
return (int) (((hash & 0xffffffffL) * n) >>> 32);
3636
}
3737

38+
/**
39+
* Multiply two unsigned 64-bit values.
40+
* See https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8188044
41+
*
42+
* @param a the first value
43+
* @param b the second value
44+
* @return the result
45+
*/
46+
public static long multiplyHighUnsigned(long a, long b) {
47+
return Math.multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a);
48+
}
49+
3850
}

fastfilter/src/main/java/org/fastfilter/xor/XorBinaryFuse8.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public long getBitCount() {
4242
static int calculateSegmentLength(int arity, int size) {
4343
int segmentLength;
4444
if (arity == 3) {
45-
segmentLength = 1 << (int) Math.floor(Math.log(size) / Math.log(3.33) + 2.25);
45+
segmentLength = 1 << (int) Math.floor(Math.log(size) / Math.log(3.33) + 2.11);
4646
} else if (arity == 4) {
4747
segmentLength = 1 << (int) Math.floor(Math.log(size) / Math.log(2.91) - 0.5);
4848
} else {
@@ -200,17 +200,17 @@ private void addAll(long[] keys) {
200200
Arrays.fill(reverseOrder, 0);
201201

202202
// TODO
203-
System.out.println("WARNING: hashIndex " + hashIndex + "\n");
204-
if (hashIndex >= 0) {
205-
System.out.println(size + " keys; arrayLength " + arrayLength + " reverseOrderPos " + reverseOrderPos);
206-
}
203+
// if (hashIndex > 10) {
204+
// System.out.println("WARNING: hashIndex " + hashIndex + "\n");
205+
// System.out.println(size + " keys; arrayLength " + arrayLength + " reverseOrderPos " + reverseOrderPos + " segmentLength " + segmentLength + " segmentCount " + segmentCount);
206+
// }
207207
if (hashIndex > 100) {
208208
// if construction doesn't succeed eventually,
209209
// then there is likely a problem with the hash function
210-
break;
210+
throw new IllegalArgumentException("Construction failed after " + hashIndex + " retries for size " + size);
211211
}
212212
// use a new random numbers
213-
seed++;
213+
seed = Hash.randomSeed();
214214
}
215215
alone = null;
216216
t2count = null;
@@ -246,8 +246,14 @@ public boolean mayContain(long key) {
246246
return (f & 0xff) == 0;
247247
}
248248

249+
@Override
250+
public String toString() {
251+
return "segmentLength " + segmentLength + " segmentCount " + segmentCount;
252+
}
253+
249254
int getHashFromHash(long hash, int index) {
250255
long h = Hash.reduce((int) (hash >>> 32), segmentCountLength);
256+
// long h = Hash.multiplyHighUnsigned(hash, segmentCountLength);
251257
h += index * segmentLength;
252258
// keep the lower 36 bits
253259
long hh = hash & ((1L << 36) - 1);

fastfilter/src/test/java/org/fastfilter/xor/SmallSetTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,37 @@ public void small() {
1616
XorSimple.construct(new long[]{0xef9bddc5166c081cL, 0x33bf87adaa46dcfcL});
1717
XorSimple2.construct(new long[]{0xef9bddc5166c081cL, 0x33bf87adaa46dcfcL});
1818
}
19+
20+
@Test
21+
public void verySmallSizes() {
22+
int n = 1;
23+
for (; n < 2000; n++) {
24+
testWithSize(n);
25+
}
26+
for (; n < 20000; n += 7) {
27+
testWithSize(n);
28+
}
29+
}
30+
31+
@Test
32+
public void smallSizes() {
33+
long lastTime = System.currentTimeMillis();
34+
for (int n = 1; n < 1_500_000; n = (int) ((n * 1.01) + 7)) {
35+
XorBinaryFuse8 f = testWithSize(n);
36+
long now = System.currentTimeMillis();
37+
if (now - lastTime > 5000) {
38+
lastTime = now;
39+
System.out.println("n=" + n + " " + f.toString());
40+
}
41+
}
42+
}
43+
44+
private static XorBinaryFuse8 testWithSize(int n) {
45+
long[] keys = new long[n];
46+
for (int i = 0; i < n; i++) {
47+
keys[i] = i;
48+
}
49+
return XorBinaryFuse8.construct(keys);
50+
}
51+
1952
}

0 commit comments

Comments
 (0)