diff --git a/src/main/java/org/apache/datasketches/filters/quotientfilter/QuotientFilter.java b/src/main/java/org/apache/datasketches/filters/quotientfilter/QuotientFilter.java index 19c81f4f7..11f87bf77 100644 --- a/src/main/java/org/apache/datasketches/filters/quotientfilter/QuotientFilter.java +++ b/src/main/java/org/apache/datasketches/filters/quotientfilter/QuotientFilter.java @@ -32,11 +32,11 @@ public class QuotientFilter extends Filter { - public static final double DEFAULT_LOAD_FACTOR = 0.8; + public static final float DEFAULT_LOAD_FACTOR = 0.8f; int lgQ_; int numFingerprintBits_; - double loadFactor_; + float loadFactor_; int numEntries_; int numExpansions_; BitArray bitArray_; @@ -51,7 +51,7 @@ public QuotientFilter(final int lgQ, final int numFingerprintBits) { this(lgQ, numFingerprintBits, DEFAULT_LOAD_FACTOR); } - public QuotientFilter(final int lgQ, final int numFingerprintBits, final double loadFactor) { + public QuotientFilter(final int lgQ, final int numFingerprintBits, final float loadFactor) { lgQ_ = lgQ; numFingerprintBits_ = numFingerprintBits; loadFactor_ = loadFactor; @@ -149,7 +149,7 @@ public int getLgQ() { return lgQ_; } - public double getLoadFactor() { + public float getLoadFactor() { return loadFactor_; } diff --git a/src/main/java/org/apache/datasketches/filters/quotientfilter/QuotientFilterBuilder.java b/src/main/java/org/apache/datasketches/filters/quotientfilter/QuotientFilterBuilder.java index d0f38b39a..6a1b83a81 100644 --- a/src/main/java/org/apache/datasketches/filters/quotientfilter/QuotientFilterBuilder.java +++ b/src/main/java/org/apache/datasketches/filters/quotientfilter/QuotientFilterBuilder.java @@ -59,7 +59,7 @@ public static byte suggestFingerprintLength(double targetFalsePositiveProb) { * @param maxDistinctItems The maximum number of distinct items that can be inserted into the filter. * @return The log-base-2 of the number of slots in the filter. */ - public static byte suggestLgNumSlots(long maxDistinctItems, double loadFactor) { + public static byte suggestLgNumSlots(long maxDistinctItems, float loadFactor) { if (maxDistinctItems <= 0) { throw new SketchesArgumentException("maxDistinctItems must be strictly positive"); } @@ -82,7 +82,7 @@ public static byte suggestLgNumSlots(long maxDistinctItems) { @param lgNumSlots The log-base-2 of the number of slots in the filter @return The maximum number of items that can be inserted into the filter */ - public static long suggestMaxNumItemsFromNumSlots(int lgNumSlots, double loadFactor) { + public static long suggestMaxNumItemsFromNumSlots(int lgNumSlots, float loadFactor) { if (lgNumSlots <= 0) { throw new SketchesArgumentException("lgNumSlots must be at least 1."); } else if (lgNumSlots >= 31) { @@ -107,7 +107,7 @@ public static long suggestMaxNumItemsFromNumSlots(byte lgNumSlots) { * @return A QFPair object containing the suggested number of slots (lgNumSlots) and the suggested fingerprint length. * @throws SketchesArgumentException if the input parameters are not valid. */ - public static QFPair suggestParamsFromMaxDistinctsFPP(long maxDistinctItems, double loadFactor, double targetFalsePositiveProb) { + public static QFPair suggestParamsFromMaxDistinctsFPP(long maxDistinctItems, float loadFactor, double targetFalsePositiveProb) { validateAccuracyInputs(maxDistinctItems, loadFactor, targetFalsePositiveProb); byte lgNumSlots = suggestLgNumSlots(maxDistinctItems, loadFactor); byte fingerprintLength = suggestFingerprintLength(targetFalsePositiveProb); @@ -118,7 +118,7 @@ public static QFPair suggestParamsFromMaxDistinctsFPP(long maxDistinctItems, dou return suggestParamsFromMaxDistinctsFPP(maxDistinctItems, DEFAULT_LOAD_FACTOR, targetFalsePositiveProb); } - private static void validateAccuracyInputs(final long maxDistinctItems, final double loadFactor, final double targetFalsePositiveProb) { + private static void validateAccuracyInputs(final long maxDistinctItems, final float loadFactor, final double targetFalsePositiveProb) { if (maxDistinctItems <= 0) { throw new SketchesArgumentException("maxDistinctItems must be strictly positive"); } diff --git a/src/test/java/org/apache/datasketches/filters/quotientfilter/QuotientFilterBuilderTest.java b/src/test/java/org/apache/datasketches/filters/quotientfilter/QuotientFilterBuilderTest.java index 3199c60af..f3920a70c 100644 --- a/src/test/java/org/apache/datasketches/filters/quotientfilter/QuotientFilterBuilderTest.java +++ b/src/test/java/org/apache/datasketches/filters/quotientfilter/QuotientFilterBuilderTest.java @@ -46,9 +46,9 @@ public static void testSuggestLgNumSlots(){ QuotientFilterBuilder qfb = new QuotientFilterBuilder(); // invalid number of items - assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestLgNumSlots(0,0.9)); - assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestLgNumSlots(-1, 0.9)); - assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestLgNumSlots(5000000000L, 0.9)); + assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestLgNumSlots(0,0.9f)); + assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestLgNumSlots(-1, 0.9f)); + assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestLgNumSlots(5000000000L, 0.9f)); assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestLgNumSlots(0)); assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestLgNumSlots(-1)); assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestLgNumSlots(5000000000L)); @@ -58,7 +58,7 @@ public static void testSuggestLgNumSlots(){ for (int i = 0; i < numItems.length; i++) { long num = numItems[i]; - byte result = qfb.suggestLgNumSlots(num, 0.9); + byte result = qfb.suggestLgNumSlots(num, 0.9f); assertEquals(result, results[i]); result = qfb.suggestLgNumSlots(num); assertEquals(result, results[i]); @@ -74,14 +74,17 @@ public static void testSuggestMaxNumItems(){ assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestMaxNumItemsFromNumSlots((byte)0)); assertThrows(SketchesArgumentException.class, () -> QuotientFilterBuilder.suggestMaxNumItemsFromNumSlots((byte)32)); - int[] lgNumSlots = {1, 2, 3, 6, 10, 15, 25, 30,}; - long[] results_ninety_pc = {1, 3, 7, 57, 921, 29491, 30198988, 966367641} ; - long[] results_eighty_pc = {1, 3, 6, 51, 819, 26214, 26843545, 858993459} ; + long[] results_ninety_pc = {1, 3, 7, 57, 922, 29504, 30212096, 966787072} ; + long[] results_eighty_pc = {1, 3, 6, 51, 820, 26240, 26869760, 859832320} ; + + // load capacities arbitrarily chosen using powers of two for exact arithmetic + float ninety_pc_appx = 922f / 1024f; // ≈ 0.9 + float eighty_pc_appx = 820f / 1024f; // ≈ 0.8 for (int i = 0; i < lgNumSlots.length; i++) { - long result_ninety = qfb.suggestMaxNumItemsFromNumSlots(lgNumSlots[i], 0.9); - long result_eighty = qfb.suggestMaxNumItemsFromNumSlots(lgNumSlots[i], 0.8); + long result_ninety = qfb.suggestMaxNumItemsFromNumSlots(lgNumSlots[i], ninety_pc_appx); + long result_eighty = qfb.suggestMaxNumItemsFromNumSlots(lgNumSlots[i], eighty_pc_appx); assertEquals(result_ninety, results_ninety_pc[i]); assertEquals(result_eighty, results_eighty_pc[i]); } @@ -109,7 +112,7 @@ public static void testSuggestParamsFromMaxDistinctsFPP(){ byte[] expected_fingerprintLength = {34, 7, 24} ; for (int i = 0; i < numItems.length; i++) { - QuotientFilterBuilder.QFPair pair = qfb.suggestParamsFromMaxDistinctsFPP(numItems[i], 0.9, fpp[i]); + QuotientFilterBuilder.QFPair pair = qfb.suggestParamsFromMaxDistinctsFPP(numItems[i], 0.9f, fpp[i]); lgNumSlots = pair.lgNumSlots; fingerprintLength = pair.fingerprintLength; assertEquals(expected_lgNumSlotsNinety[i], lgNumSlots);