From 2f736a179a64a63feb239ee8f3200856a05c49ba Mon Sep 17 00:00:00 2001
From: Lee Rhodes
This implementation uses xxHash64 and follows the approach in Kirsch and Mitzenmacher, - * "Less Hashing, Same Performance: Building a Better Bloom Filter," Wiley Interscience, 2008, - * pp. 187-218.
+ * "Less Hashing, Same Performance: Building a Better Bloom Filter," Wiley Interscience, 2008, pp. 187-218. */ public final class BloomFilter { + /** + * The maximum size of a bloom filter in bits. + */ public static final long MAX_SIZE_BITS = (Integer.MAX_VALUE - Family.BLOOMFILTER.getMaxPreLongs()) * (long) Long.SIZE; private static final int SER_VER = 1; private static final int EMPTY_FLAG_MASK = 4; @@ -133,11 +135,23 @@ public static BloomFilter heapify(final Memory mem) { return internalHeapifyOrWrap((WritableMemory) mem, false, false); } + /** + * Wraps the given Memory into this filter class. The class itself only contains a few metadata items and holds + * a reference to the Memory object, which contains all the data. + * @param mem the given Memory object + * @return the wrapping BloomFilter class. + */ public static BloomFilter wrap(final Memory mem) { // casting to writable, but tracking that the object is read-only return internalHeapifyOrWrap((WritableMemory) mem, true, false); } + /** + * Wraps the given WritableMemory into this filter class. The class itself only contains a few metadata items and holds + * a reference to the Memory object, which contains all the data. + * @param wmem the given WritableMemory object + * @return the wrapping BloomFilter class. + */ public static BloomFilter writableWrap(final WritableMemory wmem) { return internalHeapifyOrWrap(wmem, true, true); } diff --git a/src/main/java/org/apache/datasketches/filters/bloomfilter/DirectBitArrayR.java b/src/main/java/org/apache/datasketches/filters/bloomfilter/DirectBitArrayR.java index 19c495af6..8acc36be2 100644 --- a/src/main/java/org/apache/datasketches/filters/bloomfilter/DirectBitArrayR.java +++ b/src/main/java/org/apache/datasketches/filters/bloomfilter/DirectBitArrayR.java @@ -24,6 +24,9 @@ import org.apache.datasketches.memory.Memory; import org.apache.datasketches.memory.WritableMemory; +/** + * This class can maintain the BitArray object off-heap. + */ public class DirectBitArrayR extends BitArray { final static protected long NUM_BITS_OFFSET = Long.BYTES; final static protected long DATA_OFFSET = 2L * Long.BYTES; diff --git a/src/main/java/org/apache/datasketches/hll/TgtHllType.java b/src/main/java/org/apache/datasketches/hll/TgtHllType.java index a0ee79a45..a5dc395ce 100644 --- a/src/main/java/org/apache/datasketches/hll/TgtHllType.java +++ b/src/main/java/org/apache/datasketches/hll/TgtHllType.java @@ -50,10 +50,27 @@ * * @author Lee Rhodes */ -public enum TgtHllType { HLL_4, HLL_6, HLL_8; +public enum TgtHllType { + /** + * An HLL sketch with a bin size of 4 bits + */ + HLL_4, + /** + * An HLL sketch with a bin size of 6 bits + */ + HLL_6, + /** + * An Hll Sketch with a bin size of 8 bits + */ + HLL_8; private static final TgtHllType values[] = values(); + /** + * Convert the typeId to the enum type + * @param typeId the given typeId + * @return the enum type + */ public static final TgtHllType fromOrdinal(final int typeId) { return values[typeId]; } diff --git a/src/main/java/org/apache/datasketches/kll/KllItemsSketch.java b/src/main/java/org/apache/datasketches/kll/KllItemsSketch.java index 392da0673..6fb9772fb 100644 --- a/src/main/java/org/apache/datasketches/kll/KllItemsSketch.java +++ b/src/main/java/org/apache/datasketches/kll/KllItemsSketch.java @@ -290,6 +290,10 @@ public void reset() { itemsSV = null; } + /** + * Export the current sketch as a compact byte array. + * @return the current sketch as a compact byte array. + */ public byte[] toByteArray() { return KllHelper.toByteArray(this, false); } diff --git a/src/main/java/org/apache/datasketches/kll/KllItemsSketchIterator.java b/src/main/java/org/apache/datasketches/kll/KllItemsSketchIterator.java index 3a0a8da0f..02bda7a20 100644 --- a/src/main/java/org/apache/datasketches/kll/KllItemsSketchIterator.java +++ b/src/main/java/org/apache/datasketches/kll/KllItemsSketchIterator.java @@ -23,6 +23,7 @@ /** * Iterator over KllItemsSketch. The order is not defined. + * @paramThe sample may be smaller than k and the resulting size of the sample potentially includes
* a probabilistic component, meaning the resulting sample size is not always constant.
- *
+ * @param Please refer to the documentation in the package-info: Please refer to the documentation in the package-info: Here is what we do for each level: It can be proved that generalCompress returns a sketch that satisfies the space constraints
+ * no matter how much data is passed in.
+ * We are pretty sure that it works correctly when inBuf and outBuf are the same.
+ * All levels except for level zero must be sorted before calling this, and will still be
+ * sorted afterwards.
+ * Level zero is not required to be sorted before, and may not be sorted afterwards. This trashes inBuf and inLevels and modifies outBuf and outLevels. The parameter k will not change. The resulting approximations have a probabilistic guarantee that can be obtained from the
+ * getNormalizedRankError(false) function. The start of each interval is below the lowest item retained by the sketch
+ * corresponding to a zero rank or zero probability, and the end of the interval
+ * is the rank or cumulative probability corresponding to the split point. The (m+1)th interval represents 100% of the distribution represented by the sketch
+ * and consistent with the definition of a cumulative probability distribution, thus the (m+1)th
+ * rank or probability in the returned array is always 1.0. If a split point exactly equals a retained item of the sketch and the search criterion is: It is not recommended to include either the minimum or maximum items of the input stream. The resulting approximations have a probabilistic guarantee that can be obtained from the
+ * getNormalizedRankError(true) function. Each interval except for the end intervals starts with a split point and ends with the next split
+ * point in sequence. The first interval starts below the lowest item retained by the sketch
+ * corresponding to a zero rank or zero probability, and ends with the first split point The last (m+1)th interval starts with the last split point and ends after the last
+ * item retained by the sketch corresponding to a rank or probability of 1.0. The sum of the probability masses of all (m+1) intervals is 1.0. If the search criterion is: It is not recommended to include either the minimum or maximum items of the input stream. Don't call this before calling next() for the first time
+ * or after getting false from next(). The resulting approximations have a probabilistic guarantee that can be obtained from the
+ * getNormalizedRankError(false) function. The start of each interval is below the lowest item retained by the sketch
+ * corresponding to a zero rank or zero probability, and the end of the interval
+ * is the rank or cumulative probability corresponding to the split point. The (m+1)th interval represents 100% of the distribution represented by the sketch
+ * and consistent with the definition of a cumulative probability distribution, thus the (m+1)th
+ * rank or probability in the returned array is always 1.0. If a split point exactly equals a retained item of the sketch and the search criterion is: It is not recommended to include either the minimum or maximum items of the input stream. The resulting approximations have a probabilistic guarantee that can be obtained from the
+ * getNormalizedRankError(true) function. Each interval except for the end intervals starts with a split point and ends with the next split
+ * point in sequence. The first interval starts below the lowest item retained by the sketch
+ * corresponding to a zero rank or zero probability, and ends with the first split point The last (m+1)th interval starts with the last split point and ends after the last
+ * item retained by the sketch corresponding to a rank or probability of 1.0. The sum of the probability masses of all (m+1) intervals is 1.0. If the search criterion is: It is not recommended to include either the minimum or maximum items of the input stream. Although it is possible to estimate the probability that the true quantile
+ * exists within the quantile confidence interval specified by the upper and lower quantile bounds,
+ * it is not possible to guarantee the width of the quantile confidence interval
+ * as an additive or multiplicative percent of the true quantile. Although it is possible to estimate the probability that the true quantile
+ * exists within the quantile confidence interval specified by the upper and lower quantile bounds,
+ * it is not possible to guarantee the width of the quantile interval
+ * as an additive or multiplicative percent of the true quantile. Don't call this before calling next() for the first time
+ * or after getting false from next(). Please refer to the documentation in the package-info: Given a sorted array of values arr[] and a search key value v, the algorithms for
* the searching criteria are given with each enum criterion. Given a sorted array of values arr[] and a search key value v, the algorithms for
* the searching criteria are given with each enum criterion. [*] Note that obtaining epsilon may require using a similar function but with more parameters
* based on the specific sketch implementation. Note: Only certain set operators during stateful operations can be serialized.
- * Only when they are stored into Memory will this be relevant. A Bloom filter is a data structure that can be used for probabilistic
- * set membership. When querying a Bloom filter, there are no false positives. Specifically:
* When querying an item that has already been inserted to the filter, the filter will
diff --git a/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilterBuilder.java b/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilterBuilder.java
index f865a3350..ee17a9918 100644
--- a/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilterBuilder.java
+++ b/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilterBuilder.java
@@ -25,8 +25,8 @@
import org.apache.datasketches.memory.WritableMemory;
/**
- * This class provides methods to help estimate the correct parameters when
- * creating a Bloom filter, and methods to create the filter using those values.
- * The intent of the design of this class was to isolate the detailed knowledge of the bit and byte
+ * The intent of the design of this class was to isolate the detailed knowledge of the bit and byte
* layout of the serialized form of the sketches derived from the Sketch class into one place. This
* allows the possibility of the introduction of different serialization schemes with minimal impact
- * on the rest of the library.
- * S[] copySummaryArray(final S[] summaryArr) {
return tmpSummaryArr;
}
+ /**
+ * Creates a new Summary Array with the specified length
+ * @param summaryArr example array, only used to obtain the component type. It has no data.
+ * @param length the desired length of the returned array.
+ * @param the summary class type
+ * @return a new Summary Array with the specified length
+ */
@SuppressWarnings("unchecked")
public static S[] newSummaryArray(final S[] summaryArr, final int length) {
final Class summaryType = (Class) summaryArr.getClass().getComponentType();
From 6c469cb197c960673c51a00694051d87a4474da8 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
+ * {@link org.apache.datasketches.kll}
+ * {@link org.apache.datasketches.kll}
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
* {@link org.apache.datasketches.kll}The DataSketches™ HLL sketch family package
+ * The DataSketches™ HLL sketch family package
* {@link org.apache.datasketches.hll.HllSketch HllSketch} and {@link org.apache.datasketches.hll.Union Union}
* are the public facing classes of this high performance implementation of Phillipe Flajolet's
* HyperLogLog algorithm[1] but with significantly improved error behavior and important features that can be
diff --git a/src/main/java/org/apache/datasketches/quantiles/CompactDoublesSketch.java b/src/main/java/org/apache/datasketches/quantiles/CompactDoublesSketch.java
index f6df9e87e..18e05d315 100644
--- a/src/main/java/org/apache/datasketches/quantiles/CompactDoublesSketch.java
+++ b/src/main/java/org/apache/datasketches/quantiles/CompactDoublesSketch.java
@@ -20,7 +20,6 @@
package org.apache.datasketches.quantiles;
import org.apache.datasketches.common.SketchesStateException;
-import org.apache.datasketches.memory.Memory;
/**
* Compact sketches are inherently read only.
@@ -31,10 +30,6 @@ public abstract class CompactDoublesSketch extends DoublesSketch {
super(k);
}
- public static CompactDoublesSketch heapify(final Memory srcMem) {
- return HeapCompactDoublesSketch.heapifyInstance(srcMem);
- }
-
@Override
boolean isCompact() {
return true;
diff --git a/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java b/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java
index 03f84116a..49e7c5fbb 100644
--- a/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java
+++ b/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java
@@ -140,7 +140,7 @@ public static final DoublesSketchBuilder builder() {
*/
public static DoublesSketch heapify(final Memory srcMem) {
if (checkIsCompactMemory(srcMem)) {
- return CompactDoublesSketch.heapify(srcMem);
+ return HeapCompactDoublesSketch.heapifyInstance(srcMem);
}
return UpdateDoublesSketch.heapify(srcMem);
}
diff --git a/src/main/java/org/apache/datasketches/quantiles/UpdateDoublesSketch.java b/src/main/java/org/apache/datasketches/quantiles/UpdateDoublesSketch.java
index 155001c87..f56c3b352 100644
--- a/src/main/java/org/apache/datasketches/quantiles/UpdateDoublesSketch.java
+++ b/src/main/java/org/apache/datasketches/quantiles/UpdateDoublesSketch.java
@@ -49,6 +49,13 @@ public static UpdateDoublesSketch wrap(final WritableMemory srcMem) {
@Override
public abstract void update(double item);
+ /**
+ * Factory heapify takes a compact sketch image in Memory and instantiates an on-heap sketch.
+ * The resulting sketch will not retain any link to the source Memory.
+ * @param srcMem a compact Memory image of a sketch serialized by this sketch.
+ * See Memory
+ * @return a heap-based sketch based on the given Memory.
+ */
public static UpdateDoublesSketch heapify(final Memory srcMem) {
return HeapUpdateDoublesSketch.heapifyInstance(srcMem);
}
diff --git a/src/main/java/org/apache/datasketches/quantilescommon/QuantilesAPI.java b/src/main/java/org/apache/datasketches/quantilescommon/QuantilesAPI.java
index 9943fefee..3dc0651a7 100644
--- a/src/main/java/org/apache/datasketches/quantilescommon/QuantilesAPI.java
+++ b/src/main/java/org/apache/datasketches/quantilescommon/QuantilesAPI.java
@@ -205,11 +205,22 @@
@SuppressWarnings("javadoc")
public interface QuantilesAPI {
+ /** The sketch must not be empty for this operation. */
static String EMPTY_MSG = "The sketch must not be empty for this operation. ";
+
+ /** Unsupported operation for this Sketch Type. */
static String UNSUPPORTED_MSG = "Unsupported operation for this Sketch Type. ";
+
+ /** Sketch does not have just one item. */
static String NOT_SINGLE_ITEM_MSG = "Sketch does not have just one item. ";
+
+ /** MemoryRequestServer must not be null. */
static String MEM_REQ_SVR_NULL_MSG = "MemoryRequestServer must not be null. ";
+
+ /** Target sketch is Read Only, cannot write. */
static String TGT_IS_READ_ONLY_MSG = "Target sketch is Read Only, cannot write. ";
+
+ /** A sketch cannot merge with itself. */
static String SELF_MERGE_MSG = "A sketch cannot merge with itself. ";
/**
diff --git a/src/main/java/org/apache/datasketches/req/BaseReqSketch.java b/src/main/java/org/apache/datasketches/req/BaseReqSketch.java
index 2460308fc..05d4d3ce2 100644
--- a/src/main/java/org/apache/datasketches/req/BaseReqSketch.java
+++ b/src/main/java/org/apache/datasketches/req/BaseReqSketch.java
@@ -89,11 +89,23 @@ public static double getRSE(final int k, final double rank, final boolean hra, f
@Override
public abstract float getQuantileLowerBound(double rank);
+ /**
+ * Gets an approximate lower bound of the quantile associated with the given rank.
+ * @param rank the given normalized rank, a number between 0 and 1.0.
+ * @param numStdDev the number of standard deviations. Must be 1, 2, or 3.
+ * @return an approximate lower bound quantile, if it exists.
+ */
public abstract float getQuantileLowerBound(double rank, int numStdDev);
@Override
public abstract float getQuantileUpperBound(double rank);
+ /**
+ * Gets an approximate upper bound of the quantile associated with the given rank.
+ * @param rank the given normalized rank, a number between 0 and 1.0.
+ * @param numStdDev the number of standard deviations. Must be 1, 2, or 3.
+ * @return an approximate upper bound quantile, if it exists.
+ */
public abstract float getQuantileUpperBound(double rank, int numStdDev);
@Override
@@ -101,7 +113,7 @@ public static double getRSE(final int k, final double rank, final boolean hra, f
/**
* Gets an approximate lower bound rank of the given normalized rank.
- * @param rank the given rank, a number between 0 and 1.0.
+ * @param rank the given normalized rank, a number between 0 and 1.0.
* @param numStdDev the number of standard deviations. Must be 1, 2, or 3.
* @return an approximate lower bound rank.
*/
diff --git a/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java b/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java
index 20dd6ee7d..72a98565d 100644
--- a/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java
+++ b/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java
@@ -46,10 +46,18 @@ private IntersectAction(final String actionId, final String actionDescription) {
this.actionDescription = actionDescription;
}
+ /**
+ * Gets the Action ID
+ * @return the actionId
+ */
public String getActionId() {
return actionId;
}
+ /**
+ * Gets the Action Description
+ * @return the actionDescription
+ */
public String getActionDescription() {
return actionDescription;
}
@@ -72,24 +80,42 @@ private AnotbAction(final String actionId, final String actionDescription) {
this.actionDescription = actionDescription;
}
+ /**
+ * Gets the Action ID
+ * @return the actionId
+ */
public String getActionId() {
return actionId;
}
+ /**
+ * Gets the action description
+ * @return the action description
+ */
public String getActionDescription() {
return actionDescription;
}
}
+ /** List of union actions */
public enum UnionAction {
+ /** Sketch A Exactly */
SKETCH_A("A", "Sketch A Exactly"),
+ /** Trim Sketch A by MinTheta */
TRIM_A("TA", "Trim Sketch A by MinTheta"),
+ /** Sketch B Exactly */
SKETCH_B("B", "Sketch B Exactly"),
+ /** Trim Sketch B by MinTheta */
TRIM_B("TB", "Trim Sketch B by MinTheta"),
+ /** Degenerate{MinTheta, 0, F} */
DEGEN_MIN_0_F("D", "Degenerate{MinTheta, 0, F}"),
+ /** Degenerate{ThetaA, 0, F} */
DEGEN_THA_0_F("DA", "Degenerate{ThetaA, 0, F}"),
+ /** Degenerate{ThetaB, 0, F} */
DEGEN_THB_0_F("DB", "Degenerate{ThetaB, 0, F}"),
+ /** Empty{1.0, 0, T} */
EMPTY_1_0_T("E", "Empty{1.0, 0, T}"),
+ /** Full Union */
FULL_UNION("N", "Full Union");
private String actionId;
@@ -100,49 +126,74 @@ private UnionAction(final String actionId, final String actionDescription) {
this.actionDescription = actionDescription;
}
+ /**
+ * Gets the action ID
+ * @return the actionId
+ */
public String getActionId() {
return actionId;
}
+ /**
+ * Gets the action description
+ * @return the actionDescription
+ */
public String getActionDescription() {
return actionDescription;
}
}
+ /** List of corner cases */
public enum CornerCase {
+ /** Empty Empty */
Empty_Empty(055, "A{ 1.0, 0, T} ; B{ 1.0, 0, T}",
IntersectAction.EMPTY_1_0_T, AnotbAction.EMPTY_1_0_T, UnionAction.EMPTY_1_0_T),
+ /** Empty Exact */
Empty_Exact(056, "A{ 1.0, 0, T} ; B{ 1.0,>0, F}",
IntersectAction.EMPTY_1_0_T, AnotbAction.EMPTY_1_0_T, UnionAction.SKETCH_B),
+ /** Empty Estimation */
Empty_Estimation(052, "A{ 1.0, 0, T} ; B{<1.0,>0, F",
IntersectAction.EMPTY_1_0_T, AnotbAction.EMPTY_1_0_T, UnionAction.SKETCH_B),
+ /** Empty Degen */
Empty_Degen(050, "A{ 1.0, 0, T} ; B{<1.0, 0, F}",
IntersectAction.EMPTY_1_0_T, AnotbAction.EMPTY_1_0_T, UnionAction.DEGEN_THB_0_F),
+ /** Exact Empty */
Exact_Empty(065, "A{ 1.0,>0, F} ; B{ 1.0, 0, T}",
IntersectAction.EMPTY_1_0_T, AnotbAction.SKETCH_A, UnionAction.SKETCH_A),
+ /** Exact Exact */
Exact_Exact(066, "A{ 1.0,>0, F} ; B{ 1.0,>0, F}",
IntersectAction.FULL_INTERSECT, AnotbAction.FULL_ANOTB, UnionAction.FULL_UNION),
+ /** Exact Estimation */
Exact_Estimation(062, "A{ 1.0,>0, F} ; B{<1.0,>0, F}",
IntersectAction.FULL_INTERSECT, AnotbAction.FULL_ANOTB, UnionAction.FULL_UNION),
+ /** Exact Degen */
Exact_Degen(060, "A{ 1.0,>0, F} ; B{<1.0, 0, F}",
IntersectAction.DEGEN_MIN_0_F, AnotbAction.TRIM_A, UnionAction.TRIM_A),
+ /** Estimation_Empty */
Estimation_Empty(025, "A{<1.0,>0, F} ; B{ 1.0, 0, T}",
IntersectAction.EMPTY_1_0_T, AnotbAction.SKETCH_A, UnionAction.SKETCH_A),
+ /** Estimation_Exact */
Estimation_Exact(026, "A{<1.0,>0, F} ; B{ 1.0,>0, F}",
IntersectAction.FULL_INTERSECT, AnotbAction.FULL_ANOTB, UnionAction.FULL_UNION),
+ /** Estimation_Estimation */
Estimation_Estimation(022, "A{<1.0,>0, F} ; B{<1.0,>0, F}",
IntersectAction.FULL_INTERSECT, AnotbAction.FULL_ANOTB, UnionAction.FULL_UNION),
+ /** Estimation_Degen */
Estimation_Degen(020, "A{<1.0,>0, F} ; B{<1.0, 0, F}",
IntersectAction.DEGEN_MIN_0_F, AnotbAction.TRIM_A, UnionAction.TRIM_A),
+ /** Degen_Empty */
Degen_Empty(005, "A{<1.0, 0, F} ; B{ 1.0, 0, T}",
IntersectAction.EMPTY_1_0_T, AnotbAction.DEGEN_THA_0_F, UnionAction.DEGEN_THA_0_F),
+ /** Degen_Exact */
Degen_Exact(006, "A{<1.0, 0, F} ; B{ 1.0,>0, F}",
IntersectAction.DEGEN_MIN_0_F, AnotbAction.DEGEN_THA_0_F, UnionAction.TRIM_B),
+ /** Degen_Estimation */
Degen_Estimation(002, "A{<1.0, 0, F} ; B{<1.0,>0, F}",
IntersectAction.DEGEN_MIN_0_F, AnotbAction.DEGEN_MIN_0_F, UnionAction.TRIM_B),
+ /** Degen_Degen */
Degen_Degen(000, "A{<1.0, 0, F} ; B{<1.0, 0, F}",
IntersectAction.DEGEN_MIN_0_F, AnotbAction.DEGEN_MIN_0_F, UnionAction.DEGEN_MIN_0_F);
@@ -168,27 +219,52 @@ private CornerCase(final int caseId, final String caseDescription,
this.unionAction = unionAction;
}
+ /**
+ * Gets the case ID
+ * @return the caseId
+ */
public int getId() {
return caseId;
}
+ /**
+ * Gets the case description
+ * @return the caseDescription
+ */
public String getCaseDescription() {
return caseDescription;
}
+ /**
+ * Gets the intersect action
+ * @return the intersectAction
+ */
public IntersectAction getIntersectAction() {
return intersectAction;
}
+ /**
+ * Gets the AnotB action
+ * @return the anotbAction
+ */
public AnotbAction getAnotbAction() {
return anotbAction;
}
+ /**
+ * Gets the union action
+ * @return the unionAction
+ */
public UnionAction getUnionAction() {
return unionAction;
}
//See checkById test in /tuple/MiscTest.
+ /**
+ * Converts caseId to CornerCaseId
+ * @param id the case ID
+ * @return the Corner Case ID
+ */
public static CornerCase caseIdToCornerCase(final int id) {
final CornerCase cc = caseIdToCornerCaseMap.get(id);
if (cc == null) {
@@ -198,12 +274,29 @@ public static CornerCase caseIdToCornerCase(final int id) {
}
} //end of enum CornerCase
+ /**
+ * Creates the CornerCase ID
+ * @param thetaLongA the theta of A as a long
+ * @param countA the count of A
+ * @param emptyA true if A is empty
+ * @param thetaLongB the theta of B as a long
+ * @param countB the count of B
+ * @param emptyB true if B is empty
+ * @return the Corner Case ID
+ */
public static int createCornerCaseId(
final long thetaLongA, final int countA, final boolean emptyA,
final long thetaLongB, final int countB, final boolean emptyB) {
return (sketchStateId(emptyA, countA, thetaLongA) << 3) | sketchStateId(emptyB, countB, thetaLongB);
}
+ /**
+ * Returns the sketch state ID
+ * @param isEmpty true if empty
+ * @param numRetained the number of items retained
+ * @param thetaLong the value of theta as a long
+ * @return the sketch state ID
+ */
public static int sketchStateId(final boolean isEmpty, final int numRetained, final long thetaLong) {
// assume thetaLong = MAX if empty
return (((thetaLong == MAX) || isEmpty) ? 4 : 0) | ((numRetained > 0) ? 2 : 0) | (isEmpty ? 1 : 0);
diff --git a/src/main/java/org/apache/datasketches/tuple/SerializerDeserializer.java b/src/main/java/org/apache/datasketches/tuple/SerializerDeserializer.java
index 44d1d9cc0..9b0ca33cb 100644
--- a/src/main/java/org/apache/datasketches/tuple/SerializerDeserializer.java
+++ b/src/main/java/org/apache/datasketches/tuple/SerializerDeserializer.java
@@ -32,8 +32,17 @@ public final class SerializerDeserializer {
* Defines the sketch classes that this SerializerDeserializer can handle.
*/
@SuppressWarnings("javadoc")
- public static enum SketchType { QuickSelectSketch, CompactSketch, ArrayOfDoublesQuickSelectSketch,
- ArrayOfDoublesCompactSketch, ArrayOfDoublesUnion }
+ public static enum SketchType {
+ /** QuickSelectSketch */
+ QuickSelectSketch,
+ /** CompactSketch */
+ CompactSketch,
+ /** ArrayOfDoublesQuickSelectSketch */
+ ArrayOfDoublesQuickSelectSketch,
+ /** ArrayOfDoublesCompactSketch */
+ ArrayOfDoublesCompactSketch,
+ /** ArrayOfDoublesUnion */
+ ArrayOfDoublesUnion }
static final int TYPE_BYTE_OFFSET = 3;
diff --git a/src/test/java/org/apache/datasketches/quantiles/QuantilesSketchCrossLanguageTest.java b/src/test/java/org/apache/datasketches/quantiles/QuantilesSketchCrossLanguageTest.java
index 8c80f4399..68347ffb8 100644
--- a/src/test/java/org/apache/datasketches/quantiles/QuantilesSketchCrossLanguageTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/QuantilesSketchCrossLanguageTest.java
@@ -249,7 +249,7 @@ private static void getAndCheck(String ver, int n, double quantile) {
Assert.assertEquals(q2, quantile, 0.0);
// same thing with compact sketch
- qs2 = CompactDoublesSketch.heapify(srcMem);
+ qs2 = HeapCompactDoublesSketch.heapifyInstance(srcMem);
//Test the quantile
q2 = qs2.getQuantile(nf, EXCLUSIVE);
println("New Median: " + q2);
From f42af451b38c096d0d4af5f45814c86ef252e78e Mon Sep 17 00:00:00 2001
From: Lee Rhodes The DataSketches™ HLL sketch family package
+ * The DataSketches™ HLL sketch family package
* {@link org.apache.datasketches.hll.HllSketch HllSketch} and {@link org.apache.datasketches.hll.Union Union}
* are the public facing classes of this high performance implementation of Phillipe Flajolet's
* HyperLogLog algorithm[1] but with significantly improved error behavior and important features that can be
diff --git a/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java b/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java
index 72a98565d..d9fda48bb 100644
--- a/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java
+++ b/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java
@@ -34,8 +34,11 @@ public class SetOperationCornerCases {
/** Intersection actions */
public enum IntersectAction {
+ /** Degenerate{MinTheta, 0, F} */
DEGEN_MIN_0_F("D", "Degenerate{MinTheta, 0, F}"),
+ /** Empty{1.0, 0, T */
EMPTY_1_0_T("E", "Empty{1.0, 0, T}"),
+ /** Full Intersect */
FULL_INTERSECT("I", "Full Intersect");
private String actionId;
@@ -65,11 +68,17 @@ public String getActionDescription() {
/** A not B actions */
public enum AnotbAction {
+ /** Sketch A Exact */
SKETCH_A("A", "Sketch A Exactly"),
+ /** Trim Sketch A by MinTheta */
TRIM_A("TA", "Trim Sketch A by MinTheta"),
+ /** Degenerate{MinTheta, 0, F} */
DEGEN_MIN_0_F("D", "Degenerate{MinTheta, 0, F}"),
+ /** Degenerate{ThetaA, 0, F} */
DEGEN_THA_0_F("DA", "Degenerate{ThetaA, 0, F}"),
+ /** Empty{1.0, 0, T} */
EMPTY_1_0_T("E", "Empty{1.0, 0, T}"),
+ /** Full AnotB */
FULL_ANOTB("N", "Full AnotB");
private String actionId;
From 34aaa8baf679cccdac2ea6bdefef46870e5bc004 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
- * MAP: Low significance bytes of this long data structure are on the right. However, the + *
MAP: Low significance bytes of this long data structure are on the right. However, the * multi-byte integers (int and long) are stored in native byte order. The byte - * values are treated as unsigned. - *
+ * values are treated as unsigned. * - *- * An empty FrequentItems only requires 8 bytes. All others require 32 bytes of preamble. - *
+ *An empty FrequentItems only requires 8 bytes. All others require 32 bytes of preamble.
* *
* * Long || Start Byte Adr:
diff --git a/src/main/java/org/apache/datasketches/quantiles/DoublesByteArrayImpl.java b/src/main/java/org/apache/datasketches/quantiles/DoublesByteArrayImpl.java
index f4df5aa8b..8451bad33 100644
--- a/src/main/java/org/apache/datasketches/quantiles/DoublesByteArrayImpl.java
+++ b/src/main/java/org/apache/datasketches/quantiles/DoublesByteArrayImpl.java
@@ -58,7 +58,7 @@ static byte[] toByteArray(final DoublesSketch sketch, final boolean ordered, fin
| (ordered ? ORDERED_FLAG_MASK : 0)
| (compact ? (COMPACT_FLAG_MASK | READ_ONLY_FLAG_MASK) : 0);
- if (empty && !sketch.hasMemory()) { //empty & has Memory
+ if (empty && !sketch.hasMemory()) { //empty & !has Memory
final byte[] outByteArr = new byte[Long.BYTES];
final WritableMemory memOut = WritableMemory.writableWrap(outByteArr);
final int preLongs = 1;
@@ -79,15 +79,7 @@ static byte[] toByteArray(final DoublesSketch sketch, final boolean ordered, fin
*/
private static byte[] convertToByteArray(final DoublesSketch sketch, final int flags,
final boolean ordered, final boolean compact) {
- final int preLongs = 2;
- final int extra = 2; // extra space for min and max quantiles
- final int prePlusExtraBytes = (preLongs + extra) << 3;
- final int k = sketch.getK();
- final long n = sketch.getN();
-
- // If not-compact, have accessor always report full levels. Then use level size to determine
- // whether to copy data out.
- final DoublesSketchAccessor dsa = DoublesSketchAccessor.wrap(sketch, !compact);
+ final int preLongs = sketch.isEmpty() ? 1 : 2;
final int outBytes = (compact ? sketch.getCurrentCompactSerializedSizeBytes()
: sketch.getCurrentUpdatableSerializedSizeBytes());
@@ -95,15 +87,23 @@ private static byte[] convertToByteArray(final DoublesSketch sketch, final int f
final byte[] outByteArr = new byte[outBytes];
final WritableMemory memOut = WritableMemory.writableWrap(outByteArr);
- //insert preamble-0, N, min, max
+ //insert pre0
+ final int k = sketch.getK();
insertPre0(memOut, preLongs, flags, k);
if (sketch.isEmpty()) { return outByteArr; }
+ //insert N, min, max
+ final long n = sketch.getN();
insertN(memOut, n);
insertMinDouble(memOut, sketch.isEmpty() ? Double.NaN : sketch.getMinItem());
insertMaxDouble(memOut, sketch.isEmpty() ? Double.NaN : sketch.getMaxItem());
- long memOffsetBytes = prePlusExtraBytes;
+ // If not-compact, have accessor always report full levels. Then use level size to determine
+ // whether to copy data out.
+ final DoublesSketchAccessor dsa = DoublesSketchAccessor.wrap(sketch, !compact);
+
+ final int minAndMax = 2; // extra space for min and max quantiles
+ long memOffsetBytes = (preLongs + minAndMax) << 3;
// might need to sort base buffer but don't want to change input sketch
final int bbCnt = computeBaseBufferItems(k, n);
diff --git a/src/main/java/org/apache/datasketches/tdigest/TDigestDouble.java b/src/main/java/org/apache/datasketches/tdigest/TDigestDouble.java
index 1e3408511..951bd7244 100644
--- a/src/main/java/org/apache/datasketches/tdigest/TDigestDouble.java
+++ b/src/main/java/org/apache/datasketches/tdigest/TDigestDouble.java
@@ -32,6 +32,7 @@
import org.apache.datasketches.memory.WritableBuffer;
import org.apache.datasketches.memory.WritableMemory;
import org.apache.datasketches.quantilescommon.QuantilesAPI;
+import org.apache.datasketches.quantilescommon.QuantilesUtil;
/**
* t-Digest for estimating quantiles and ranks.
@@ -125,7 +126,7 @@ public void merge(final TDigestDouble other) {
/**
* Process buffered values and merge centroids if needed
*/
- public void compress() {
+ private void compress() {
if (numBuffered_ == 0) { return; }
final int num = numBuffered_ + numCentroids_;
final double[] values = new double[num];
@@ -277,6 +278,51 @@ public double getQuantile(final double rank) {
return weightedAverage(centroidWeights_[numCentroids_ - 1], w1, maxValue_, w2);
}
+ /**
+ * Returns an approximation to the Probability Mass Function (PMF) of the input stream
+ * given a set of split points.
+ *
+ * @param splitPoints an array of m unique, monotonically increasing values
+ * that divide the input domain into m+1 consecutive disjoint intervals (bins).
+ *
+ * @return an array of m+1 doubles each of which is an approximation
+ * to the fraction of the input stream values (the mass) that fall into one of those intervals.
+ * @throws SketchesStateException if sketch is empty.
+ */
+ public double[] getPMF(final double[] splitPoints) {
+ final double[] buckets = getCDF(splitPoints);
+ for (int i = buckets.length; i-- > 1; ) {
+ buckets[i] -= buckets[i - 1];
+ }
+ return buckets;
+ }
+
+ /**
+ * Returns an approximation to the Cumulative Distribution Function (CDF), which is the
+ * cumulative analog of the PMF, of the input stream given a set of split points.
+ *
+ * @param splitPoints an array of m unique, monotonically increasing values
+ * that divide the input domain into m+1 consecutive disjoint intervals.
+ *
+ * @return an array of m+1 doubles, which are a consecutive approximation to the CDF
+ * of the input stream given the splitPoints. The value at array position j of the returned
+ * CDF array is the sum of the returned values in positions 0 through j of the returned PMF
+ * array. This can be viewed as array of ranks of the given split points plus one more value
+ * that is always 1.
+ * @throws SketchesStateException if sketch is empty.
+ */
+ public double[] getCDF(final double[] splitPoints) {
+ if (isEmpty()) { throw new SketchesStateException(QuantilesAPI.EMPTY_MSG); }
+ QuantilesUtil.checkDoublesSplitPointsOrder(splitPoints);
+ final int len = splitPoints.length + 1;
+ final double[] ranks = new double[len];
+ for (int i = 0; i < len - 1; i++) {
+ ranks[i] = getRank(splitPoints[i]);
+ }
+ ranks[len - 1] = 1.0;
+ return ranks;
+ }
+
/**
* Computes size needed to serialize the current state.
* @return size in bytes needed to serialize this tdigest
diff --git a/src/test/java/org/apache/datasketches/filters/bloomfilter/DirectBitArrayTest.java b/src/test/java/org/apache/datasketches/filters/bloomfilter/DirectBitArrayTest.java
index 1df6cc9d9..8327a0d5e 100644
--- a/src/test/java/org/apache/datasketches/filters/bloomfilter/DirectBitArrayTest.java
+++ b/src/test/java/org/apache/datasketches/filters/bloomfilter/DirectBitArrayTest.java
@@ -139,7 +139,7 @@ public void basicWritableWrapTest() {
@Test
public void countWritableWrappedBitsWhenDirty() {
// like basicOperationTest but with setBit which does
- // not neecssarily track numBitsSet_
+ // not necessarily track numBitsSet_
final HeapBitArray hba = new HeapBitArray(128);
assertFalse(hba.getAndSetBit(1));
assertFalse(hba.getAndSetBit(2));
diff --git a/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java b/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java
index 985cdf798..09eebabf7 100644
--- a/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java
+++ b/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java
@@ -31,7 +31,6 @@
import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.Memory;
-//import org.apache.datasketches.memory.WritableHandle;
import org.apache.datasketches.memory.WritableMemory;
/**
@@ -74,8 +73,6 @@ private static void promotions(int lgConfigK, int n, TgtHllType tgtHllType, bool
byte[] barr1;
WritableMemory wmem;
try (ResourceScope scope = (wmem = WritableMemory.allocateDirect(bytes)).scope()) {
- //byte[] byteArr = new byte[bytes];
- //WritableMemory wmem = WritableMemory.wrap(byteArr);
hllSketch = new HllSketch(lgConfigK, tgtHllType, wmem);
assertTrue(hllSketch.isEmpty());
diff --git a/src/test/java/org/apache/datasketches/hll/PreambleUtilTest.java b/src/test/java/org/apache/datasketches/hll/PreambleUtilTest.java
index deb8c5be5..17f3d0d0f 100644
--- a/src/test/java/org/apache/datasketches/hll/PreambleUtilTest.java
+++ b/src/test/java/org/apache/datasketches/hll/PreambleUtilTest.java
@@ -109,7 +109,6 @@ public void checkCorruptMemoryInput() {
HllSketch sk = new HllSketch(12);
byte[] memObj = sk.toCompactByteArray();
WritableMemory wmem = WritableMemory.writableWrap(memObj);
- //long memAdd = wmem.getCumulativeOffset(0);
HllSketch bad;
//checkFamily
@@ -148,7 +147,6 @@ public void checkCorruptMemoryInput() {
for (int i = 1; i <= 15; i++) { sk.update(i); }
memObj = sk.toCompactByteArray();
wmem = WritableMemory.writableWrap(memObj);
- //memAdd = wmem.getCumulativeOffset(0);
//check wrong PreInts and SET
try {
@@ -162,7 +160,6 @@ public void checkCorruptMemoryInput() {
for (int i = 15; i <= 1000; i++) { sk.update(i); }
memObj = sk.toCompactByteArray();
wmem = WritableMemory.writableWrap(memObj);
- //memAdd = wmem.getCumulativeOffset(0);
//check wrong PreInts and HLL
try {
@@ -179,7 +176,6 @@ public void checkExtractFlags() {
int bytes = HllSketch.getMaxUpdatableSerializationBytes(4, TgtHllType.HLL_4);
WritableMemory wmem = WritableMemory.allocate(bytes);
Object memObj = wmem.getArray();
- //long memAdd = wmem.getCumulativeOffset(0L);
HllSketch sk = new HllSketch(4, TgtHllType.HLL_4, wmem);
int flags = extractFlags(wmem);
assertEquals(flags, EMPTY_FLAG_MASK);
diff --git a/src/test/java/org/apache/datasketches/kll/KllCrossLanguageTest.java b/src/test/java/org/apache/datasketches/kll/KllCrossLanguageTest.java
index 078f3503b..53b422b7c 100644
--- a/src/test/java/org/apache/datasketches/kll/KllCrossLanguageTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllCrossLanguageTest.java
@@ -67,6 +67,16 @@ public void generateKllFloatsSketchBinaries() throws IOException {
}
}
+ @Test(groups = {GENERATE_JAVA_FILES})
+ public void generateKllLongsSketchBinaries() throws IOException {
+ final int[] nArr = {0, 1, 10, 100, 1_000, 10_000, 100_000, 1_000_000};
+ for (int n: nArr) {
+ final KllLongsSketch sk = KllLongsSketch.newHeapInstance();
+ for (int i = 1; i <= n; i++) { sk.update(i); }
+ Files.newOutputStream(javaPath.resolve("kll_long_n" + n + "_java.sk")).write(sk.toByteArray());
+ }
+ }
+
@Test(groups = {GENERATE_JAVA_FILES})
public void generateKllItemsSketchBinaries() throws IOException {
final int[] nArr = {0, 1, 10, 100, 1_000, 10_000, 100_000, 1_000_000};
diff --git a/src/test/java/org/apache/datasketches/kll/KllDirectCompactDoublesSketchTest.java b/src/test/java/org/apache/datasketches/kll/KllDirectCompactDoublesSketchTest.java
index 9831c2f57..7a4d061ad 100644
--- a/src/test/java/org/apache/datasketches/kll/KllDirectCompactDoublesSketchTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllDirectCompactDoublesSketchTest.java
@@ -110,13 +110,13 @@ public void checkDirectCompactGetDoubleItemsArray() {
KllDoublesSketch sk2 = KllDoublesSketch.wrap(Memory.wrap(sk.toByteArray()));
double[] itemsArr = sk2.getDoubleItemsArray();
- for (int i = 0; i < 20; i++) { assertEquals(itemsArr[i], 0F); }
+ for (int i = 0; i < 20; i++) { assertEquals(itemsArr[i], 0.0); }
sk.update(1);
sk2 = KllDoublesSketch.wrap(Memory.wrap(sk.toByteArray()));
itemsArr = sk2.getDoubleItemsArray();
- for (int i = 0; i < 19; i++) { assertEquals(itemsArr[i], 0F); }
- assertEquals(itemsArr[19], 1F);
+ for (int i = 0; i < 19; i++) { assertEquals(itemsArr[i], 0.0); }
+ assertEquals(itemsArr[19], 1.0);
for (int i = 2; i <= 21; i++) { sk.update(i); }
sk2 = KllDoublesSketch.wrap(Memory.wrap(sk.toByteArray()));
@@ -169,12 +169,12 @@ public void checkMinAndMax() {
try { sk2.getMaxItem(); fail(); } catch (SketchesArgumentException e) {}
sk.update(1);
sk2 = KllDoublesSketch.wrap(Memory.wrap(sk.toByteArray()));
- assertEquals(sk2.getMaxItem(),1.0F);
- assertEquals(sk2.getMinItem(),1.0F);
+ assertEquals(sk2.getMaxItem(),1.0);
+ assertEquals(sk2.getMinItem(),1.0);
for (int i = 2; i <= 21; i++) { sk.update(i); }
sk2 = KllDoublesSketch.wrap(Memory.wrap(sk.toByteArray()));
- assertEquals(sk2.getMaxItem(),21.0F);
- assertEquals(sk2.getMinItem(),1.0F);
+ assertEquals(sk2.getMaxItem(),21.0);
+ assertEquals(sk2.getMinItem(),1.0);
}
@Test
diff --git a/src/test/java/org/apache/datasketches/kll/KllDirectDoublesSketchIteratorTest.java b/src/test/java/org/apache/datasketches/kll/KllDirectDoublesSketchIteratorTest.java
index 78a3b9cd5..4bfdfa4fc 100644
--- a/src/test/java/org/apache/datasketches/kll/KllDirectDoublesSketchIteratorTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllDirectDoublesSketchIteratorTest.java
@@ -41,7 +41,7 @@ public void oneItemSketch() {
sketch.update(0);
QuantilesDoublesSketchIterator it = sketch.iterator();
Assert.assertTrue(it.next());
- Assert.assertEquals(it.getQuantile(), 0f);
+ Assert.assertEquals(it.getQuantile(), 0);
Assert.assertEquals(it.getWeight(), 1);
Assert.assertFalse(it.next());
}
diff --git a/src/test/java/org/apache/datasketches/kll/KllDirectDoublesSketchTest.java b/src/test/java/org/apache/datasketches/kll/KllDirectDoublesSketchTest.java
index 33219a806..6342ac33d 100644
--- a/src/test/java/org/apache/datasketches/kll/KllDirectDoublesSketchTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllDirectDoublesSketchTest.java
@@ -189,11 +189,11 @@ public void mergeLowerK() {
sketch2.update(2 * n - i - 1);
}
- assertEquals(sketch1.getMinItem(), 0.0f);
- assertEquals(sketch1.getMaxItem(), n - 1f);
+ assertEquals(sketch1.getMinItem(), 0.0);
+ assertEquals(sketch1.getMaxItem(), n - 1.0);
assertEquals(sketch2.getMinItem(), n);
- assertEquals(sketch2.getMaxItem(), 2f * n - 1f);
+ assertEquals(sketch2.getMaxItem(), 2.0 * n - 1.0);
assertTrue(sketch1.getNormalizedRankError(false) < sketch2.getNormalizedRankError(false));
assertTrue(sketch1.getNormalizedRankError(true) < sketch2.getNormalizedRankError(true));
@@ -613,7 +613,7 @@ public void checkWritableWrapOfCompactForm() {
public void checkReadOnlyExceptions() {
int k = 20;
double[] dblArr = new double[0];
- double dblV = 1.0f;
+ double dblV = 1.0;
int idx = 1;
boolean bool = true;
KllDoublesSketch sk = KllDoublesSketch.newHeapInstance(k);
diff --git a/src/test/java/org/apache/datasketches/kll/KllDoublesSketchSerDeTest.java b/src/test/java/org/apache/datasketches/kll/KllDoublesSketchSerDeTest.java
index e07a395da..007cc8370 100644
--- a/src/test/java/org/apache/datasketches/kll/KllDoublesSketchSerDeTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllDoublesSketchSerDeTest.java
@@ -64,7 +64,7 @@ public void serializeDeserializeEmpty() {
@Test
public void serializeDeserializeOneValue() {
final KllDoublesSketch sk1 = KllDoublesSketch.newHeapInstance();
- sk1.update(1);
+ sk1.update(1.0);
//from heap -> byte[] -> heap
final byte[] bytes = sk1.toByteArray();
diff --git a/src/test/java/org/apache/datasketches/kll/KllDoublesSketchTest.java b/src/test/java/org/apache/datasketches/kll/KllDoublesSketchTest.java
index 0b3818f1f..e143577f4 100644
--- a/src/test/java/org/apache/datasketches/kll/KllDoublesSketchTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllDoublesSketchTest.java
@@ -165,8 +165,8 @@ public void manyValuesEstimationMode() {
assertEquals(pmf[0], 0.5, PMF_EPS_FOR_K_256);
assertEquals(pmf[1], 0.5, PMF_EPS_FOR_K_256);
- assertEquals(sketch.getMinItem(), 0f); // min value is exact
- assertEquals(sketch.getMaxItem(), n - 1f); // max value is exact
+ assertEquals(sketch.getMinItem(), 0.0); // min value is exact
+ assertEquals(sketch.getMaxItem(), n - 1.0); // max value is exact
// check at every 0.1 percentage point
final double[] fractions = new double[1001];
@@ -261,11 +261,11 @@ public void mergeLowerK() {
sketch2.update(2 * n - i - 1);
}
- assertEquals(sketch1.getMinItem(), 0.0f);
- assertEquals(sketch1.getMaxItem(), n - 1f);
+ assertEquals(sketch1.getMinItem(), 0.0);
+ assertEquals(sketch1.getMaxItem(), n - 1);
assertEquals(sketch2.getMinItem(), n);
- assertEquals(sketch2.getMaxItem(), 2f * n - 1.0);
+ assertEquals(sketch2.getMaxItem(), 2.0 * n - 1.0);
assertTrue(sketch1.getNormalizedRankError(false) < sketch2.getNormalizedRankError(false));
assertTrue(sketch1.getNormalizedRankError(true) < sketch2.getNormalizedRankError(true));
@@ -306,7 +306,7 @@ public void mergeEmptyLowerK() {
sketch2.merge(sketch1);
assertFalse(sketch1.isEmpty());
assertEquals(sketch1.getN(), n);
- assertEquals(sketch1.getMinItem(), 0f);
+ assertEquals(sketch1.getMinItem(), 0.0);
assertEquals(sketch1.getMaxItem(), n - 1.0);
assertEquals(sketch1.getQuantile(0.5), n / 2.0, n * PMF_EPS_FOR_K_256);
}
@@ -424,7 +424,7 @@ public void checkNewDirectInstanceAndSize() {
KllDoublesSketch.newDirectInstance(wmem, memReqSvr);
try { KllDoublesSketch.newDirectInstance(null, memReqSvr); fail(); }
catch (NullPointerException e) { }
- try { KllFloatsSketch.newDirectInstance(wmem, null); fail(); }
+ try { KllDoublesSketch.newDirectInstance(wmem, null); fail(); }
catch (NullPointerException e) { }
int updateSize = KllSketch.getMaxSerializedSizeBytes(200, 0, DOUBLES_SKETCH, true);
int compactSize = KllSketch.getMaxSerializedSizeBytes(200, 0, DOUBLES_SKETCH, false);
diff --git a/src/test/java/org/apache/datasketches/kll/KllItemsSketchTest.java b/src/test/java/org/apache/datasketches/kll/KllItemsSketchTest.java
index 00028e341..9fc74d97b 100644
--- a/src/test/java/org/apache/datasketches/kll/KllItemsSketchTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllItemsSketchTest.java
@@ -570,7 +570,7 @@ public void checkCDF_PDF() {
}
@Test
- public void checkWrapCase1Floats() {
+ public void checkWrapCase1Items() {
KllItemsSketch sk = KllItemsSketch.newHeapInstance(20, Comparator.naturalOrder(), serDe);
final int n = 21;
final int digits = Util.numDigits(n);
diff --git a/src/test/java/org/apache/datasketches/kll/KllMiscDoublesTest.java b/src/test/java/org/apache/datasketches/kll/KllMiscDoublesTest.java
index e58c27419..4ce988d22 100644
--- a/src/test/java/org/apache/datasketches/kll/KllMiscDoublesTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllMiscDoublesTest.java
@@ -100,8 +100,8 @@ public void checkHeapifyExceptions2() {
@Test(expectedExceptions = SketchesArgumentException.class)
public void checkHeapifyExceptions3() {
KllDoublesSketch sk = KllDoublesSketch.newHeapInstance();
- sk.update(1.0f);
- sk.update(2.0f);
+ sk.update(1.0);
+ sk.update(2.0);
WritableMemory wmem = WritableMemory.writableWrap(sk.toByteArray());
wmem.putByte(0, (byte) 1); //corrupt preamble ints, should be 5
KllDoublesSketch.heapify(wmem);
diff --git a/src/test/java/org/apache/datasketches/kll/KllMiscItemsTest.java b/src/test/java/org/apache/datasketches/kll/KllMiscItemsTest.java
index acf3343d9..5f51a7f1a 100644
--- a/src/test/java/org/apache/datasketches/kll/KllMiscItemsTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllMiscItemsTest.java
@@ -293,7 +293,7 @@ public void checkSketchInitializeItemsHeap() {
final int digits = Util.numDigits(n);
KllItemsSketch sk;
- println("#### CASE: FLOAT FULL HEAP");
+ println("#### CASE: ITEM FULL HEAP");
sk = KllItemsSketch.newHeapInstance(k, Comparator.naturalOrder(), serDe);
for (int i = 1; i <= n; i++) { sk.update(Util.longToFixedLengthString(i, digits)); }
println(sk.toString(true, true));
@@ -310,7 +310,7 @@ public void checkSketchInitializeItemsHeap() {
assertEquals(sk.getNumLevels(), 2);
assertFalse(sk.isLevelZeroSorted());
- println("#### CASE: FLOAT HEAP EMPTY");
+ println("#### CASE: ITEM HEAP EMPTY");
sk = KllItemsSketch.newHeapInstance(k, Comparator.naturalOrder(), serDe);
println(sk.toString(true, true));
assertEquals(sk.getK(), k);
@@ -326,7 +326,7 @@ public void checkSketchInitializeItemsHeap() {
assertEquals(sk.getNumLevels(), 1);
assertFalse(sk.isLevelZeroSorted());
- println("#### CASE: FLOAT HEAP SINGLE");
+ println("#### CASE: ITEM HEAP SINGLE");
sk = KllItemsSketch.newHeapInstance(k, Comparator.naturalOrder(), serDe);
sk.update("1");
println(sk.toString(true, true));
@@ -354,7 +354,7 @@ public void checkSketchInitializeItemsHeapifyCompactMem() {
byte[] compBytes;
Memory mem;
- println("#### CASE: FLOAT FULL HEAPIFIED FROM COMPACT");
+ println("#### CASE: ITEM FULL HEAPIFIED FROM COMPACT");
sk2 = KllItemsSketch.newHeapInstance(k, Comparator.naturalOrder(), serDe);
for (int i = 1; i <= n; i++) { sk2.update(Util.longToFixedLengthString(i, digits)); }
println(sk2.toString(true, true));
@@ -375,7 +375,7 @@ public void checkSketchInitializeItemsHeapifyCompactMem() {
assertEquals(sk.getNumLevels(), 2);
assertFalse(sk.isLevelZeroSorted());
- println("#### CASE: FLOAT EMPTY HEAPIFIED FROM COMPACT");
+ println("#### CASE: ITEM EMPTY HEAPIFIED FROM COMPACT");
sk2 = KllItemsSketch.newHeapInstance(k, Comparator.naturalOrder(), serDe);
//println(sk.toString(true, true));
compBytes = sk2.toByteArray();
@@ -395,7 +395,7 @@ public void checkSketchInitializeItemsHeapifyCompactMem() {
assertEquals(sk.getNumLevels(), 1);
assertFalse(sk.isLevelZeroSorted());
- println("#### CASE: FLOAT SINGLE HEAPIFIED FROM COMPACT");
+ println("#### CASE: ITEM SINGLE HEAPIFIED FROM COMPACT");
sk2 = KllItemsSketch.newHeapInstance(k, Comparator.naturalOrder(), serDe);
sk2.update("1");
//println(sk2.toString(true, true));
@@ -417,7 +417,7 @@ public void checkSketchInitializeItemsHeapifyCompactMem() {
assertFalse(sk.isLevelZeroSorted());
}
- //public void checkSketchInitializeFloatHeapifyUpdatableMem() Not Supported
+ //public void checkSketchInitializeItemHeapifyUpdatableMem() Not Supported
@Test //set static enablePrinting = true for visual checking
public void checkMemoryToStringItemsCompact() {
@@ -431,7 +431,7 @@ public void checkMemoryToStringItemsCompact() {
Memory mem;
String s;
- println("#### CASE: FLOAT FULL COMPACT");
+ println("#### CASE: ITEM FULL COMPACT");
sk = KllItemsSketch.newHeapInstance(k, Comparator.naturalOrder(), serDe);
for (int i = 1; i <= n; i++) { sk.update(Util.longToFixedLengthString(i, digits)); }
compBytes = sk.toByteArray();
@@ -447,7 +447,7 @@ public void checkMemoryToStringItemsCompact() {
println(s);
assertEquals(compBytes, compBytes2);
- println("#### CASE: FLOAT EMPTY COMPACT");
+ println("#### CASE: ITEM EMPTY COMPACT");
sk = KllItemsSketch.newHeapInstance(k, Comparator.naturalOrder(), serDe);
compBytes = sk.toByteArray();
mem = Memory.wrap(compBytes);
@@ -462,7 +462,7 @@ public void checkMemoryToStringItemsCompact() {
println(s);
assertEquals(compBytes, compBytes2);
- println("#### CASE: FLOAT SINGLE COMPACT");
+ println("#### CASE: ITEM SINGLE COMPACT");
sk = KllItemsSketch.newHeapInstance(k, Comparator.naturalOrder(), serDe);
sk.update("1");
compBytes = sk.toByteArray();
diff --git a/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java b/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java
index b1bd5818d..636105ef8 100644
--- a/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java
@@ -31,7 +31,6 @@
import jdk.incubator.foreign.ResourceScope;
import org.apache.datasketches.memory.DefaultMemoryRequestServer;
-//import org.apache.datasketches.memory.WritableHandle;
import org.apache.datasketches.memory.WritableMemory;
import org.apache.datasketches.quantilescommon.QuantilesDoublesSketchIterator;
diff --git a/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java b/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java
index c252eef3c..d896bbefa 100644
--- a/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java
@@ -30,7 +30,6 @@
import org.testng.annotations.Test;
import org.apache.datasketches.memory.Memory;
-//import org.apache.datasketches.memory.WritableHandle;
import org.apache.datasketches.memory.WritableMemory;
import jdk.incubator.foreign.ResourceScope;
diff --git a/src/test/java/org/apache/datasketches/quantiles/DoublesSketchTest.java b/src/test/java/org/apache/datasketches/quantiles/DoublesSketchTest.java
index ea928ba02..8cdc7bf71 100644
--- a/src/test/java/org/apache/datasketches/quantiles/DoublesSketchTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/DoublesSketchTest.java
@@ -141,7 +141,6 @@ public void checkEmptyExceptions() {
@Test
public void directSketchShouldMoveOntoHeapEventually() {
-
WritableMemory wmem = WritableMemory.allocateDirect(1000, 1, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer());
WritableMemory wmem2 = wmem;
UpdateDoublesSketch sketch = DoublesSketch.builder().build(wmem);
diff --git a/src/test/java/org/apache/datasketches/tdigest/TDigestDoubleTest.java b/src/test/java/org/apache/datasketches/tdigest/TDigestDoubleTest.java
index db043cff6..e1c6914c7 100644
--- a/src/test/java/org/apache/datasketches/tdigest/TDigestDoubleTest.java
+++ b/src/test/java/org/apache/datasketches/tdigest/TDigestDoubleTest.java
@@ -41,6 +41,8 @@ public void empty() {
assertThrows(SketchesStateException.class, () -> td.getMaxValue());
assertThrows(SketchesStateException.class, () -> td.getRank(0));
assertThrows(SketchesStateException.class, () -> td.getQuantile(0.5));
+ assertThrows(SketchesStateException.class, () -> td.getPMF(new double[]{0}));
+ assertThrows(SketchesStateException.class, () -> td.getCDF(new double[]{0}));
}
@Test
@@ -82,6 +84,14 @@ public void manyValues() {
assertEquals(td.getQuantile(0.9), n * 0.9, n * 0.9 * 0.01);
assertEquals(td.getQuantile(0.95), n * 0.95, n * 0.95 * 0.01);
assertEquals(td.getQuantile(1), n - 1);
+ final double[] pmf = td.getPMF(new double[] {n / 2});
+ assertEquals(pmf.length, 2);
+ assertEquals(pmf[0], 0.5, 0.0001);
+ assertEquals(pmf[1], 0.5, 0.0001);
+ final double[] cdf = td.getCDF(new double[] {n / 2});
+ assertEquals(cdf.length, 2);
+ assertEquals(cdf[0], 0.5, 0.0001);
+ assertEquals(cdf[1], 1.0);
}
@Test
diff --git a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
index 1e2089b51..188dbf427 100644
--- a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
+++ b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
@@ -32,7 +32,6 @@
import org.apache.datasketches.common.SketchesArgumentException;
import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.Memory;
-//import org.apache.datasketches.memory.WritableHandle;
import org.apache.datasketches.memory.WritableMemory;
import org.testng.annotations.Test;
diff --git a/src/test/java/org/apache/datasketches/theta/ConcurrentDirectQuickSelectSketchTest.java b/src/test/java/org/apache/datasketches/theta/ConcurrentDirectQuickSelectSketchTest.java
index e4c112281..6d6af7047 100644
--- a/src/test/java/org/apache/datasketches/theta/ConcurrentDirectQuickSelectSketchTest.java
+++ b/src/test/java/org/apache/datasketches/theta/ConcurrentDirectQuickSelectSketchTest.java
@@ -119,7 +119,6 @@ public void checkHeapifyByteArrayExact() {
// That is, this is being run for its side-effect of accessing things.
// If something is wonky, it will generate an exception and fail the test.
local2.toString(true, true, 8, true);
-
}
@Test
diff --git a/src/test/java/org/apache/datasketches/theta/ConcurrentHeapQuickSelectSketchTest.java b/src/test/java/org/apache/datasketches/theta/ConcurrentHeapQuickSelectSketchTest.java
index 2261edc3b..84ddcb80e 100644
--- a/src/test/java/org/apache/datasketches/theta/ConcurrentHeapQuickSelectSketchTest.java
+++ b/src/test/java/org/apache/datasketches/theta/ConcurrentHeapQuickSelectSketchTest.java
@@ -114,7 +114,7 @@ public void checkIllegalSketchID_UpdateSketch() {
WritableMemory mem = WritableMemory.writableWrap(byteArray);
mem.putByte(FAMILY_BYTE, (byte) 0); //corrupt the Sketch ID byte
- //try to heapify the corruped mem
+ //try to heapify the corrupted mem
Sketch.heapify(mem, sl.seed);
}
diff --git a/src/test/java/org/apache/datasketches/theta/DirectQuickSelectSketchTest.java b/src/test/java/org/apache/datasketches/theta/DirectQuickSelectSketchTest.java
index ef6004a1b..f36597b7c 100644
--- a/src/test/java/org/apache/datasketches/theta/DirectQuickSelectSketchTest.java
+++ b/src/test/java/org/apache/datasketches/theta/DirectQuickSelectSketchTest.java
@@ -47,7 +47,6 @@
import org.apache.datasketches.common.SketchesReadOnlyException;
import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.Memory;
-//import org.apache.datasketches.memory.WritableHandle;
import org.apache.datasketches.memory.WritableMemory;
import org.apache.datasketches.thetacommon.HashOperations;
import org.apache.datasketches.thetacommon.ThetaUtil;
@@ -86,7 +85,7 @@ public void checkBadSerVer() {
}
}
- @Test//(expectedExceptions = SketchesArgumentException.class)
+ @Test
public void checkConstructorKtooSmall() {
int k = 8;
WritableMemory wmem;
@@ -98,7 +97,7 @@ public void checkConstructorKtooSmall() {
}
}
- @Test//(expectedExceptions = SketchesArgumentException.class)
+ @Test
public void checkConstructorMemTooSmall() {
int k = 16;
WritableMemory wmem;
@@ -195,7 +194,7 @@ public void checkWrapIllegalFamilyID_direct() {
DirectQuickSelectSketch.writableWrap(mem, ThetaUtil.DEFAULT_UPDATE_SEED);
}
- @Test //(expectedExceptions = SketchesArgumentException.class)
+ @Test
public void checkHeapifySeedConflict() {
int k = 512;
long seed1 = 1021;
@@ -213,7 +212,7 @@ public void checkHeapifySeedConflict() {
}
}
- @Test//(expectedExceptions = SketchesArgumentException.class)
+ @Test
public void checkCorruptLgNomLongs() {
int k = 16;
WritableMemory wmem;
diff --git a/src/test/java/org/apache/datasketches/theta/HeapifyWrapSerVer1and2Test.java b/src/test/java/org/apache/datasketches/theta/HeapifyWrapSerVer1and2Test.java
index 5e81b1808..c0cff6eb2 100644
--- a/src/test/java/org/apache/datasketches/theta/HeapifyWrapSerVer1and2Test.java
+++ b/src/test/java/org/apache/datasketches/theta/HeapifyWrapSerVer1and2Test.java
@@ -41,29 +41,29 @@ public void checkHeapifyCompactSketchAssumedDefaultSeed() {
final int k = 64;
final long seed = ThetaUtil.DEFAULT_UPDATE_SEED;
final short seedHash = Util.computeSeedHash(seed);
- UpdateSketch sv3usk = UpdateSketch.builder().setNominalEntries(k).setSeed(seed).build();
- for (int i=0; i
-
+
From 14174086dfdac3b8b586b9cf2d3aaaf7b7cabacb Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Wed, 18 Dec 2024 14:51:14 -0800
Subject: [PATCH 32/88] update GHA workflows
---
.github/workflows/auto-check_cpp_files.yml | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/auto-check_cpp_files.yml b/.github/workflows/auto-check_cpp_files.yml
index b9e05ae97..4b06687e0 100644
--- a/.github/workflows/auto-check_cpp_files.yml
+++ b/.github/workflows/auto-check_cpp_files.yml
@@ -12,33 +12,33 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
-
+
- name: Checkout C++
uses: actions/checkout@v4
with:
repository: apache/datasketches-cpp
path: cpp
-
+
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
-
+
- name: Configure C++ build
run: cd cpp/build && cmake .. -DGENERATE=true
-
+
- name: Build C++ unit tests
run: cd cpp && cmake --build build --config Release
-
+
- name: Run C++ tests
run: cd cpp && cmake --build build --config Release --target test
-
+
- name: Make dir
run: mkdir -p serialization_test_data/cpp_generated_files
-
+
- name: Copy files
run: cp cpp/build/*/test/*_cpp.sk serialization_test_data/cpp_generated_files
-
+
- name: Run Java tests
run: mvn test -P check-cpp-files
From 341de43f1ee347621020785091d8a7c81344d68f Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Wed, 18 Dec 2024 15:26:32 -0800
Subject: [PATCH 33/88] update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 547df3e9d..b6db7f89e 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@ and, as a result, must be compiled with JDK17 and this dependency:
If your application only relies on the APIs of datasketches-java no special JVM arguments are required.
However, if your application also directly relies on the APIs of the *datasketches-memory* component,
-you may need the additional JVM argument **--enable-preview**.
+you may need the additional JVM argument **--add-modules=jdk.incubator.foreign**.
### Recommended Build Tool
This DataSketches component is structured as a Maven project and Maven is the recommended Build Tool.
From babbe129bd1a994709cbbfe702596117b88d4919 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Wed, 18 Dec 2024 15:54:59 -0800
Subject: [PATCH 34/88] Release Process: update pom to 7.0.0
update the version for the maven-javadoc-plugin and the
versions-maven-plugin
---
pom.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index 4c5532e54..0ab6e9fcc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,7 @@ under the License.
org.apache.datasketches
datasketches-java
- 7.0.0-SNAPSHOT
+ 7.0.0
jar
${project.artifactId}
@@ -128,7 +128,7 @@ under the License.
0.8.12
- 2.17.1
+ 2.18.0
1.0.0
From 5819b40fb53edaaf47538a0787bcf02437fe4e5d Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Wed, 18 Dec 2024 15:58:30 -0800
Subject: [PATCH 35/88] fix maven-javadoc-plugin version
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 0ab6e9fcc..35022e3b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -112,7 +112,7 @@ under the License.
3.5.0
3.2.7
3.4.2
- 3.11.1
+ 3.11.2
3.1.1
3.2.0
3.3.1
From dc232771abcd402b335f906958c335a14c606e78 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Wed, 18 Dec 2024 17:49:20 -0800
Subject: [PATCH 36/88] Correct indentation in GHAW auto-check_cpp_files.yml
---
.github/workflows/auto-check_cpp_files.yml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/auto-check_cpp_files.yml b/.github/workflows/auto-check_cpp_files.yml
index 4b06687e0..068b12f4d 100644
--- a/.github/workflows/auto-check_cpp_files.yml
+++ b/.github/workflows/auto-check_cpp_files.yml
@@ -13,32 +13,32 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- - name: Checkout C++
+ - name: Checkout C++
uses: actions/checkout@v4
with:
repository: apache/datasketches-cpp
path: cpp
- - name: Setup Java
+ - name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- - name: Configure C++ build
+ - name: Configure C++ build
run: cd cpp/build && cmake .. -DGENERATE=true
- - name: Build C++ unit tests
+ - name: Build C++ unit tests
run: cd cpp && cmake --build build --config Release
- - name: Run C++ tests
+ - name: Run C++ tests
run: cd cpp && cmake --build build --config Release --target test
- - name: Make dir
+ - name: Make dir
run: mkdir -p serialization_test_data/cpp_generated_files
- name: Copy files
run: cp cpp/build/*/test/*_cpp.sk serialization_test_data/cpp_generated_files
- - name: Run Java tests
+ - name: Run Java tests
run: mvn test -P check-cpp-files
From 868d33d696bcfef755bc9a605905421e246640f1 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 19 Dec 2024 15:17:49 -0800
Subject: [PATCH 37/88] update pom version on main
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 35022e3b1..c72af4f39 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,7 @@ under the License.
org.apache.datasketches
datasketches-java
- 7.0.0
+ 7.1.0-SNAPSHOT
jar
${project.artifactId}
From 763c58a5fd0ed006a52ae1bdd439efdca8e5dfbd Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Sat, 28 Dec 2024 12:53:14 -0800
Subject: [PATCH 38/88] Fix workflows in main.
---
.github/workflows/auto-jdk-matrix.yml | 100 ++++++++-------
.github/workflows/auto-os-matrix.yml | 118 +++++++++---------
...heck_cpp_files.yml => check_cpp_files.yml} | 7 +-
.github/workflows/codeql-analysis.yml | 83 ++++++++++++
.../{manual-javadoc.yml => javadoc.yml} | 0
.github/workflows/manual-codeql-analysis.yml | 57 ---------
6 files changed, 202 insertions(+), 163 deletions(-)
rename .github/workflows/{auto-check_cpp_files.yml => check_cpp_files.yml} (70%)
create mode 100644 .github/workflows/codeql-analysis.yml
rename .github/workflows/{manual-javadoc.yml => javadoc.yml} (100%)
delete mode 100644 .github/workflows/manual-codeql-analysis.yml
diff --git a/.github/workflows/auto-jdk-matrix.yml b/.github/workflows/auto-jdk-matrix.yml
index f8220bbe2..9312589df 100644
--- a/.github/workflows/auto-jdk-matrix.yml
+++ b/.github/workflows/auto-jdk-matrix.yml
@@ -1,67 +1,71 @@
name: DataSketches-Java Auto JDK Matrix Test & Install
on:
- pull_request:
- push:
- branches: [ master, main ]
- workflow_dispatch:
+ push:
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
+ pull_request:
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ # The branches below must be a subset of the branches above
+ branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
+ workflow_dispatch:
env:
- MAVEN_OPTS: -Xmx4g -Xms1g
+ MAVEN_OPTS: -Xmx4g -Xms1g
jobs:
- build:
- name: Build, Test, Install
- runs-on: ubuntu-latest
+ build:
+ name: Build, Test, Install
+ runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- jdk: [ 17 ]
+ strategy:
+ fail-fast: false
+ matrix:
+ jdk: [ 17 ]
- env:
- JDK_VERSION: ${{ matrix.jdk }}
+ env:
+ JDK_VERSION: ${{ matrix.jdk }}
- steps:
- - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
- uses: actions/checkout@v4
- with:
- persist-credentials: false
+ steps:
+ - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
- - name: Print Current workflow
- run: >
- cat .github/workflows/auto-jdk-matrix.yml
+ - name: Print Current workflow
+ run: >
+ cat .github/workflows/auto-jdk-matrix.yml
- - name: Cache local Maven repository
- uses: actions/cache@v4
- with:
- path: ~/.m2/repository
- key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: build-${{ runner.os }}-maven-
+ - name: Cache local Maven repository
+ uses: actions/cache@v4
+ with:
+ path: ~/.m2/repository
+ key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: build-${{ runner.os }}-maven-
- - name: Install Matrix JDK
- uses: actions/setup-java@v4
- with:
- java-version: ${{ matrix.jdk }}
- distribution: 'temurin'
- java-package: jdk
- architecture: x64
+ - name: Install Matrix JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: ${{ matrix.jdk }}
+ distribution: 'temurin'
+ java-package: jdk
+ architecture: x64
- - name: Echo Java Version
- run: >
- java -version
+ - name: Echo Java Version
+ run: >
+ java -version
- - name: Test
- run: >
- mvn clean test -B
- -Dmaven.javadoc.skip=true
- -Dgpg.skip=true
+ - name: Test
+ run: >
+ mvn clean test -B
+ -Dmaven.javadoc.skip=true
+ -Dgpg.skip=true
- - name: Install
- run: >
- mvn clean install -B
- -DskipTests=true
- -Dgpg.skip=true
+ - name: Install
+ run: >
+ mvn clean install -B
+ -DskipTests=true
+ -Dgpg.skip=true
# Architecture options: x86, x64, armv7, aarch64, ppc64le
# setup-java@v4 has a "with cache" option
diff --git a/.github/workflows/auto-os-matrix.yml b/.github/workflows/auto-os-matrix.yml
index d9f5bc4c5..9fb6f2812 100644
--- a/.github/workflows/auto-os-matrix.yml
+++ b/.github/workflows/auto-os-matrix.yml
@@ -1,77 +1,81 @@
name: DataSketches-Java Auto OS Matrix Test & Install
on:
- pull_request:
- push:
- branches: [ master, main ]
- workflow_dispatch:
+ push:
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
+ pull_request:
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ # The branches below must be a subset of the branches above
+ branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
+ workflow_dispatch:
env:
- MAVEN_OPTS: -Xmx1g -Xms1g
+ MAVEN_OPTS: -Xmx4g -Xms1g
jobs:
- build:
- name: Build, Test, Install
+ build:
+ name: Build, Test, Install
- strategy:
- fail-fast: false
+ strategy:
+ fail-fast: false
- matrix:
- jdk: [ 17 ]
- os: [ windows-latest, ubuntu-latest, macos-latest ]
- include:
- - os: windows-latest
- skip_javadoc: "`-Dmaven`.javadoc`.skip=true"
- skip_gpg: "`-Dgpg`.skip=true"
- - os: ubuntu-latest
- skip_javadoc: -Dmaven.javadoc.skip=true
- skip_gpg: -Dgpg.skip=true
- - os: macos-latest
- skip_javadoc: -Dmaven.javadoc.skip=true
- skip_gpg: -Dgpg.skip=true
+ matrix:
+ jdk: [ 17 ]
+ os: [ windows-latest, ubuntu-latest, macos-latest ]
+ include:
+ - os: windows-latest
+ skip_javadoc: "`-Dmaven`.javadoc`.skip=true"
+ skip_gpg: "`-Dgpg`.skip=true"
+ - os: ubuntu-latest
+ skip_javadoc: -Dmaven.javadoc.skip=true
+ skip_gpg: -Dgpg.skip=true
+ - os: macos-latest
+ skip_javadoc: -Dmaven.javadoc.skip=true
+ skip_gpg: -Dgpg.skip=true
- runs-on: ${{matrix.os}}
+ runs-on: ${{matrix.os}}
- env:
- JDK_VERSION: ${{ matrix.jdk }}
+ env:
+ JDK_VERSION: ${{ matrix.jdk }}
- steps:
- - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
- uses: actions/checkout@v4
- with:
- persist-credentials: false
+ steps:
+ - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
- - name: Cache local Maven repository
- uses: actions/cache@v4
- with:
- path: ~/.m2/repository
- key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: build-${{ runner.os }}-maven-
+ - name: Cache local Maven repository
+ uses: actions/cache@v4
+ with:
+ path: ~/.m2/repository
+ key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: build-${{ runner.os }}-maven-
- - name: Install Matrix JDK
- uses: actions/setup-java@v4
- with:
- java-version: ${{ matrix.jdk }}
- distribution: 'temurin'
- java-package: jdk
- architecture: x64
+ - name: Install Matrix JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: ${{ matrix.jdk }}
+ distribution: 'temurin'
+ java-package: jdk
+ architecture: x64
- - name: Echo Java Version
- run: >
- java -version
+ - name: Echo Java Version
+ run: >
+ java -version
- - name: Test
- run: >
- mvn clean test
- ${{matrix.os.skip_javadoc}}
- ${{matrix.os.skip_gpg}}
+ - name: Test
+ run: >
+ mvn clean test
+ ${{matrix.os.skip_javadoc}}
+ ${{matrix.os.skip_gpg}}
- - name: Install
- run: >
- mvn clean install -B
- ${{matrix.os.skip_javadoc}}
- -D skipTests=true
- ${{matrix.os.skip_gpg}}
+ - name: Install
+ run: >
+ mvn clean install -B
+ ${{matrix.os.skip_javadoc}}
+ -D skipTests=true
+ ${{matrix.os.skip_gpg}}
# Architecture options: x86, x64, armv7, aarch64, ppc64le
# setup-java@v4 has a "with cache" option
diff --git a/.github/workflows/auto-check_cpp_files.yml b/.github/workflows/check_cpp_files.yml
similarity index 70%
rename from .github/workflows/auto-check_cpp_files.yml
rename to .github/workflows/check_cpp_files.yml
index 068b12f4d..4ca9e0aa4 100644
--- a/.github/workflows/auto-check_cpp_files.yml
+++ b/.github/workflows/check_cpp_files.yml
@@ -2,7 +2,12 @@ name: Serialization Compatibility Test
on:
push:
- branches: [ master, main ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
+ pull_request:
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ # The branches below must be a subset of the branches above
+ branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
workflow_dispatch:
jobs:
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 000000000..e6589b243
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,83 @@
+name: "CodeQL"
+
+on:
+ push:
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
+ pull_request:
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ # The branches below must be a subset of the branches above
+ branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
+ workflow_dispatch:
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'java' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+ # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Setup Java
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ cache: 'maven'
+ java-version: '17'
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+ queries: +security-and-quality
+
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+ # Details on CodeQL's query packs refer to link below.
+
+ - name: Custom building using maven
+ run: >
+ mvn clean package -f "pom.xml" -B -V -e
+ -Dfindbugs.skip=true
+ -Dcheckstyle.skip=true
+ -Dpmd.skip=true
+ -Denforcer.skip
+ -Dmaven.javadoc.skip
+ -DskipTests=true
+ -Dmaven.test.skip.exec
+ -Dlicense.skip=true
+ -Dweb.console.skip=true
+ -Dgpg.skip=true
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
+
+
+# CodeQL's Query Packs:
+# https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+
+# Command-line programs to run using the OS shell.
+# See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+
+# Architecture options: x86, x64, armv7, aarch64, ppc64le
+# Lifecycles: validate, compile, test, package, verify, install, deploy
+# -B batch mode, never stops for user input
+# -V show Version without stopping
+# -X debug mode
+# -q quiet, only show errors
+# -e produce execution error messages
\ No newline at end of file
diff --git a/.github/workflows/manual-javadoc.yml b/.github/workflows/javadoc.yml
similarity index 100%
rename from .github/workflows/manual-javadoc.yml
rename to .github/workflows/javadoc.yml
diff --git a/.github/workflows/manual-codeql-analysis.yml b/.github/workflows/manual-codeql-analysis.yml
deleted file mode 100644
index 1b94d13a3..000000000
--- a/.github/workflows/manual-codeql-analysis.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-name: "CodeQL"
-
-on:
- workflow_dispatch:
-
-jobs:
- analyze:
- name: Analyze
- runs-on: ubuntu-latest
- permissions:
- actions: read
- contents: read
- security-events: write
-
- strategy:
- fail-fast: false
- matrix:
- language: [ 'java' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
- # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v4
- with:
- languages: ${{ matrix.language }}
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
-
- # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
- queries: +security-and-quality
-
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v4
-
- # Command-line programs to run using the OS shell.
- # See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
-
- # If the Autobuild fails above, remove it and uncomment the following three lines.
- # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
-
- # - run: |
- # echo "Run, Build Application using script"
- # ./location_of_script_within_repo/buildscript.sh
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v4
- with:
- category: "/language:${{matrix.language}}"
From 4ace77e9fa449825be917610c248bf8edb919d1a Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 2 Jan 2025 10:45:01 -0800
Subject: [PATCH 39/88] change step indentations
---
.github/workflows/auto-jdk-matrix.yml | 66 +++++++++++++--------------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/.github/workflows/auto-jdk-matrix.yml b/.github/workflows/auto-jdk-matrix.yml
index 9312589df..7468a3e0e 100644
--- a/.github/workflows/auto-jdk-matrix.yml
+++ b/.github/workflows/auto-jdk-matrix.yml
@@ -27,45 +27,45 @@ jobs:
JDK_VERSION: ${{ matrix.jdk }}
steps:
- - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
- uses: actions/checkout@v4
- with:
- persist-credentials: false
+ - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
- - name: Print Current workflow
- run: >
- cat .github/workflows/auto-jdk-matrix.yml
+ - name: Print Current workflow
+ run: >
+ cat .github/workflows/auto-jdk-matrix.yml
- - name: Cache local Maven repository
- uses: actions/cache@v4
- with:
- path: ~/.m2/repository
- key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: build-${{ runner.os }}-maven-
+ - name: Cache local Maven repository
+ uses: actions/cache@v4
+ with:
+ path: ~/.m2/repository
+ key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: build-${{ runner.os }}-maven-
- - name: Install Matrix JDK
- uses: actions/setup-java@v4
- with:
- java-version: ${{ matrix.jdk }}
- distribution: 'temurin'
- java-package: jdk
- architecture: x64
+ - name: Install Matrix JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: ${{ matrix.jdk }}
+ distribution: 'temurin'
+ java-package: jdk
+ architecture: x64
- - name: Echo Java Version
- run: >
- java -version
+ - name: Echo Java Version
+ run: >
+ java -version
- - name: Test
- run: >
- mvn clean test -B
- -Dmaven.javadoc.skip=true
- -Dgpg.skip=true
+ - name: Test
+ run: >
+ mvn clean test -B
+ -Dmaven.javadoc.skip=true
+ -Dgpg.skip=true
- - name: Install
- run: >
- mvn clean install -B
- -DskipTests=true
- -Dgpg.skip=true
+ - name: Install
+ run: >
+ mvn clean install -B
+ -DskipTests=true
+ -Dgpg.skip=true
# Architecture options: x86, x64, armv7, aarch64, ppc64le
# setup-java@v4 has a "with cache" option
From f5b99618f24cc048450ef0dc4b20ab99ebf20889 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 2 Jan 2025 13:35:34 -0800
Subject: [PATCH 40/88] repair indentations
---
.github/workflows/auto-jdk-matrix.yml | 68 +++++++++++++--------------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/.github/workflows/auto-jdk-matrix.yml b/.github/workflows/auto-jdk-matrix.yml
index 7468a3e0e..5adbbbe08 100644
--- a/.github/workflows/auto-jdk-matrix.yml
+++ b/.github/workflows/auto-jdk-matrix.yml
@@ -26,46 +26,46 @@ jobs:
env:
JDK_VERSION: ${{ matrix.jdk }}
- steps:
- - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
- uses: actions/checkout@v4
- with:
- persist-credentials: false
+ steps:
+ - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
- - name: Print Current workflow
- run: >
- cat .github/workflows/auto-jdk-matrix.yml
+ - name: Print Current workflow
+ run: >
+ cat .github/workflows/auto-jdk-matrix.yml
- - name: Cache local Maven repository
- uses: actions/cache@v4
- with:
- path: ~/.m2/repository
- key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: build-${{ runner.os }}-maven-
+ - name: Cache local Maven repository
+ uses: actions/cache@v4
+ with:
+ path: ~/.m2/repository
+ key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: build-${{ runner.os }}-maven-
- - name: Install Matrix JDK
- uses: actions/setup-java@v4
- with:
- java-version: ${{ matrix.jdk }}
- distribution: 'temurin'
- java-package: jdk
- architecture: x64
+ - name: Install Matrix JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: ${{ matrix.jdk }}
+ distribution: 'temurin'
+ java-package: jdk
+ architecture: x64
- - name: Echo Java Version
- run: >
- java -version
+ - name: Echo Java Version
+ run: >
+ java -version
- - name: Test
- run: >
- mvn clean test -B
- -Dmaven.javadoc.skip=true
- -Dgpg.skip=true
+ - name: Test
+ run: >
+ mvn clean test -B
+ -Dmaven.javadoc.skip=true
+ -Dgpg.skip=true
- - name: Install
- run: >
- mvn clean install -B
- -DskipTests=true
- -Dgpg.skip=true
+ - name: Install
+ run: >
+ mvn clean install -B
+ -DskipTests=true
+ -Dgpg.skip=true
# Architecture options: x86, x64, armv7, aarch64, ppc64le
# setup-java@v4 has a "with cache" option
From 1fd781f5eb7500e5db5465e15282016da9eddb15 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 2 Jan 2025 16:38:42 -0800
Subject: [PATCH 41/88] fix indents again
---
.github/workflows/auto-jdk-matrix.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/auto-jdk-matrix.yml b/.github/workflows/auto-jdk-matrix.yml
index 5adbbbe08..49c7cf1dc 100644
--- a/.github/workflows/auto-jdk-matrix.yml
+++ b/.github/workflows/auto-jdk-matrix.yml
@@ -23,8 +23,8 @@ jobs:
matrix:
jdk: [ 17 ]
- env:
- JDK_VERSION: ${{ matrix.jdk }}
+ env:
+ JDK_VERSION: ${{ matrix.jdk }}
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
From 35526df5935776f14b4a2fd18019f8e42e4d6683 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 2 Jan 2025 16:52:43 -0800
Subject: [PATCH 42/88] adjust indents & titles
---
.github/workflows/auto-jdk-matrix.yml | 4 +-
.github/workflows/auto-os-matrix.yml | 64 +++++++++++++--------------
2 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/.github/workflows/auto-jdk-matrix.yml b/.github/workflows/auto-jdk-matrix.yml
index 49c7cf1dc..9043932ce 100644
--- a/.github/workflows/auto-jdk-matrix.yml
+++ b/.github/workflows/auto-jdk-matrix.yml
@@ -1,4 +1,4 @@
-name: DataSketches-Java Auto JDK Matrix Test & Install
+name: Auto JDK Matrix Test & Install
on:
push:
@@ -24,7 +24,7 @@ jobs:
jdk: [ 17 ]
env:
- JDK_VERSION: ${{ matrix.jdk }}
+ addJDK_VERSION: ${{ matrix.jdk }}
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
diff --git a/.github/workflows/auto-os-matrix.yml b/.github/workflows/auto-os-matrix.yml
index 9fb6f2812..b56e5aa22 100644
--- a/.github/workflows/auto-os-matrix.yml
+++ b/.github/workflows/auto-os-matrix.yml
@@ -1,4 +1,4 @@
-name: DataSketches-Java Auto OS Matrix Test & Install
+name: Auto OS Matrix Test & Install
on:
push:
@@ -40,42 +40,42 @@ jobs:
JDK_VERSION: ${{ matrix.jdk }}
steps:
- - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
- uses: actions/checkout@v4
- with:
- persist-credentials: false
+ - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
- - name: Cache local Maven repository
- uses: actions/cache@v4
- with:
- path: ~/.m2/repository
- key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: build-${{ runner.os }}-maven-
+ - name: Cache local Maven repository
+ uses: actions/cache@v4
+ with:
+ path: ~/.m2/repository
+ key: build-${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: build-${{ runner.os }}-maven-
- - name: Install Matrix JDK
- uses: actions/setup-java@v4
- with:
- java-version: ${{ matrix.jdk }}
- distribution: 'temurin'
- java-package: jdk
- architecture: x64
+ - name: Install Matrix JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: ${{ matrix.jdk }}
+ distribution: 'temurin'
+ java-package: jdk
+ architecture: x64
- - name: Echo Java Version
- run: >
- java -version
+ - name: Echo Java Version
+ run: >
+ java -version
- - name: Test
- run: >
- mvn clean test
- ${{matrix.os.skip_javadoc}}
- ${{matrix.os.skip_gpg}}
+ - name: Test
+ run: >
+ mvn clean test
+ ${{matrix.os.skip_javadoc}}
+ ${{matrix.os.skip_gpg}}
- - name: Install
- run: >
- mvn clean install -B
- ${{matrix.os.skip_javadoc}}
- -D skipTests=true
- ${{matrix.os.skip_gpg}}
+ - name: Install
+ run: >
+ mvn clean install -B
+ ${{matrix.os.skip_javadoc}}
+ -D skipTests=true
+ ${{matrix.os.skip_gpg}}
# Architecture options: x86, x64, armv7, aarch64, ppc64le
# setup-java@v4 has a "with cache" option
From e412cfd5e67414d905e246f8b2cd83d72994f47b Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 2 Jan 2025 17:04:04 -0800
Subject: [PATCH 43/88] correct indents
---
.github/workflows/check_cpp_files.yml | 2 +-
.github/workflows/codeql-analysis.yml | 60 +++++++++++++--------------
2 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/.github/workflows/check_cpp_files.yml b/.github/workflows/check_cpp_files.yml
index 4ca9e0aa4..00a9e5255 100644
--- a/.github/workflows/check_cpp_files.yml
+++ b/.github/workflows/check_cpp_files.yml
@@ -1,4 +1,4 @@
-name: Serialization Compatibility Test
+name: CPP SerDe Compatibility Test
on:
push:
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index e6589b243..28c17a1f6 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -27,45 +27,45 @@ jobs:
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- - name: Checkout repository
- uses: actions/checkout@v4
+ - name: Checkout repository
+ uses: actions/checkout@v4
- - name: Setup Java
- uses: actions/setup-java@v4
- with:
- distribution: 'temurin'
- cache: 'maven'
- java-version: '17'
+ - name: Setup Java
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ cache: 'maven'
+ java-version: '17'
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v3
- with:
- languages: ${{ matrix.language }}
- queries: +security-and-quality
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+ queries: +security-and-quality
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to link below.
- - name: Custom building using maven
- run: >
- mvn clean package -f "pom.xml" -B -V -e
- -Dfindbugs.skip=true
- -Dcheckstyle.skip=true
- -Dpmd.skip=true
- -Denforcer.skip
- -Dmaven.javadoc.skip
- -DskipTests=true
- -Dmaven.test.skip.exec
- -Dlicense.skip=true
- -Dweb.console.skip=true
- -Dgpg.skip=true
+ - name: Custom building using maven
+ run: >
+ mvn clean package -f "pom.xml" -B -V -e
+ -Dfindbugs.skip=true
+ -Dcheckstyle.skip=true
+ -Dpmd.skip=true
+ -Denforcer.skip
+ -Dmaven.javadoc.skip
+ -DskipTests=true
+ -Dmaven.test.skip.exec
+ -Dlicense.skip=true
+ -Dweb.console.skip=true
+ -Dgpg.skip=true
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v3
- with:
- category: "/language:${{matrix.language}}"
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
# CodeQL's Query Packs:
From 62939a21b8d085a6fa9beff5eaa9f8080aac8e4d Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 2 Jan 2025 17:24:35 -0800
Subject: [PATCH 44/88] fix cat of workflow
---
.github/workflows/javadoc.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml
index 5f6ac6aec..fc1507a2c 100644
--- a/.github/workflows/javadoc.yml
+++ b/.github/workflows/javadoc.yml
@@ -22,7 +22,7 @@ jobs:
- name: Print Current workflow
run: >
- cat .github/workflows/manual-javadoc.yml
+ cat .github/workflows/javadoc.yml
- name: Generate JavaDoc
run: mvn javadoc:javadoc
From fd0ede4f063358ed573f24155ce15adf6e7f6847 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 2 Jan 2025 17:30:42 -0800
Subject: [PATCH 45/88] fix target directory path
---
.github/workflows/javadoc.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml
index fc1507a2c..0381f43b8 100644
--- a/.github/workflows/javadoc.yml
+++ b/.github/workflows/javadoc.yml
@@ -31,6 +31,6 @@ jobs:
uses: JamesIves/github-pages-deploy-action@v4.6.8
with:
token: ${{ secrets.GITHUB_TOKEN }}
- folder: target/site/apidocs
+ folder: target/reports/apidocs
target-folder: docs/${{ github.ref_name }}
branch: gh-pages
From b5d2d04fd36ab7c71fc45e532a2ddc4b29dbe72d Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 2 Jan 2025 18:05:44 -0800
Subject: [PATCH 46/88] fix typo
---
.github/workflows/auto-jdk-matrix.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/auto-jdk-matrix.yml b/.github/workflows/auto-jdk-matrix.yml
index 9043932ce..7e1d26c70 100644
--- a/.github/workflows/auto-jdk-matrix.yml
+++ b/.github/workflows/auto-jdk-matrix.yml
@@ -24,7 +24,7 @@ jobs:
jdk: [ 17 ]
env:
- addJDK_VERSION: ${{ matrix.jdk }}
+ JDK_VERSION: ${{ matrix.jdk }}
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
From 16a00a97c6309b6574889d1b255cbbb8a3bca399 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Fri, 3 Jan 2025 16:53:46 -0800
Subject: [PATCH 47/88] Remove two obsolete files.
Update Sketches Checkstyle.xml
---
tools/CloverConfig.txt | 50 ------------------------------------
tools/SketchesCheckstyle.xml | 15 +++++------
tools/suppressions.xml | 29 ---------------------
3 files changed, 6 insertions(+), 88 deletions(-)
delete mode 100644 tools/CloverConfig.txt
delete mode 100644 tools/suppressions.xml
diff --git a/tools/CloverConfig.txt b/tools/CloverConfig.txt
deleted file mode 100644
index 845fede8c..000000000
--- a/tools/CloverConfig.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-Clover Config for Eclipse:
-
-At Project Level Properties:
-Clover:
- Instrumentation:
- Initstring: Default value
- Output Folder: ...project output dir(s)
- Flush Policy: At JVM shutdown ...
- Misc: Fully qualify ... , Instrument and compile at statement level
- Contexts:
- Check: assert statements
- Add Custom Coverage Context Filter:
- private-constructor: also see link below
- Method
- (.* )?private +[a-zA-Z0-9_$]+ *\( *\).*
- Source Files
- Only look ...
- [check] src/main/java[includes=**/*.java][excludes=]
- [check] src/test/java[includes=**/*.java][excludes=]
- Test Classes
- Assume all source in the specified folders are tests or test utility classes
- [check] src/test/java
-
-At Clover "down-triangle" menu:
- Columns:
- Element
- % TOTAL Coverage
- Uncovered Elements: Custom: %UncoveredElements * TotalElements / 100
- Total Elements
-
-
-
-http://alexruizlog.blogspot.com/2009/04/how-to-make-clover-ignore-private_21.html
\ No newline at end of file
diff --git a/tools/SketchesCheckstyle.xml b/tools/SketchesCheckstyle.xml
index 184a05ad3..53726a2c1 100644
--- a/tools/SketchesCheckstyle.xml
+++ b/tools/SketchesCheckstyle.xml
@@ -49,10 +49,12 @@ under the License.
+
-
+
+
@@ -67,6 +69,7 @@ under the License.
+
@@ -80,13 +83,6 @@ under the License.
-
-
@@ -230,7 +226,8 @@ under the License.
-
+
+
diff --git a/tools/suppressions.xml b/tools/suppressions.xml
deleted file mode 100644
index 91b8833c4..000000000
--- a/tools/suppressions.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
From 54e48e55128282a8a7bf8657a55cb03c413de73e Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Fri, 3 Jan 2025 16:55:46 -0800
Subject: [PATCH 48/88] Add LF at end of file.
---
.github/workflows/codeql-analysis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 28c17a1f6..734fbb60f 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -80,4 +80,4 @@ jobs:
# -V show Version without stopping
# -X debug mode
# -q quiet, only show errors
-# -e produce execution error messages
\ No newline at end of file
+# -e produce execution error messages
From 2d2b69d170ca4b09b1d74b407cecfabda5f2a198 Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Thu, 9 Jan 2025 11:20:15 -0800
Subject: [PATCH 49/88] fixed bit packing
---
.../apache/datasketches/theta/BitPacking.java | 4 +-
.../datasketches/theta/BitPackingTest.java | 92 ++++++++++---------
2 files changed, 49 insertions(+), 47 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/theta/BitPacking.java b/src/main/java/org/apache/datasketches/theta/BitPacking.java
index ca70dafa2..de914f908 100644
--- a/src/main/java/org/apache/datasketches/theta/BitPacking.java
+++ b/src/main/java/org/apache/datasketches/theta/BitPacking.java
@@ -482,7 +482,7 @@ static void packBits13(final long[] values, final int i, final byte[] buf, int o
buf[off++] = (byte) (values[i + 3] >>> 4);
- buf[off] = (byte) (values[i + 3] >>> 4);
+ buf[off] = (byte) (values[i + 3] << 4);
buf[off++] |= values[i + 4] >>> 9;
buf[off++] = (byte) (values[i + 4] >>> 1);
@@ -4449,7 +4449,7 @@ static void unpackBits35(final long[] values, final int i, final byte[] buf, int
values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
- values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 2) << 33;
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 33;
values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 25;
values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 17;
values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 9;
diff --git a/src/test/java/org/apache/datasketches/theta/BitPackingTest.java b/src/test/java/org/apache/datasketches/theta/BitPackingTest.java
index 152bee039..3ed6062e7 100644
--- a/src/test/java/org/apache/datasketches/theta/BitPackingTest.java
+++ b/src/test/java/org/apache/datasketches/theta/BitPackingTest.java
@@ -31,60 +31,62 @@ public class BitPackingTest {
@Test
public void packUnpackBits() {
- for (int bits = 1; bits <= 63; bits++) {
- final long mask = (1 << bits) - 1;
- long[] input = new long[8];
- final long golden64 = Util.INVERSE_GOLDEN_U64;
- long value = 0xaa55aa55aa55aa55L; // arbitrary starting value
- for (int i = 0; i < 8; ++i) {
- input[i] = value & mask;
- value += golden64;
- }
- byte[] bytes = new byte[8 * Long.BYTES];
- int bitOffset = 0;
- int bufOffset = 0;
- for (int i = 0; i < 8; ++i) {
- BitPacking.packBits(input[i], bits, bytes, bufOffset, bitOffset);
- bufOffset += (bitOffset + bits) >>> 3;
- bitOffset = (bitOffset + bits) & 7;
- }
+ long value = 0xaa55aa55aa55aa55L; // arbitrary starting value
+ for (int n = 0; n < 100; n++) {
+ for (int bits = 1; bits <= 63; bits++) {
+ final long mask = (1 << bits) - 1;
+ long[] input = new long[8];
+ for (int i = 0; i < 8; ++i) {
+ input[i] = value & mask;
+ value += Util.INVERSE_GOLDEN_U64;
+ }
+ byte[] bytes = new byte[8 * Long.BYTES];
+ int bitOffset = 0;
+ int bufOffset = 0;
+ for (int i = 0; i < 8; ++i) {
+ BitPacking.packBits(input[i], bits, bytes, bufOffset, bitOffset);
+ bufOffset += (bitOffset + bits) >>> 3;
+ bitOffset = (bitOffset + bits) & 7;
+ }
- long[] output = new long[8];
- bitOffset = 0;
- bufOffset = 0;
- for (int i = 0; i < 8; ++i) {
- BitPacking.unpackBits(output, i, bits, bytes, bufOffset, bitOffset);
- bufOffset += (bitOffset + bits) >>> 3;
- bitOffset = (bitOffset + bits) & 7;
- }
- for (int i = 0; i < 8; ++i) {
- assertEquals(output[i], input[i]);
+ long[] output = new long[8];
+ bitOffset = 0;
+ bufOffset = 0;
+ for (int i = 0; i < 8; ++i) {
+ BitPacking.unpackBits(output, i, bits, bytes, bufOffset, bitOffset);
+ bufOffset += (bitOffset + bits) >>> 3;
+ bitOffset = (bitOffset + bits) & 7;
+ }
+ for (int i = 0; i < 8; ++i) {
+ assertEquals(output[i], input[i]);
+ }
}
}
}
@Test
public void packUnpackBlocks() {
- for (int bits = 1; bits <= 63; bits++) {
- if (enablePrinting) { System.out.println("bits " + bits); }
- final long mask = (1L << bits) - 1;
- long[] input = new long[8];
- final long golden64 = Util.INVERSE_GOLDEN_U64;
- long value = 0xaa55aa55aa55aa55L; // arbitrary starting value
- for (int i = 0; i < 8; ++i) {
- input[i] = value & mask;
- value += golden64;
- }
- byte[] bytes = new byte[8 * Long.BYTES];
- BitPacking.packBitsBlock8(input, 0, bytes, 0, bits);
- if (enablePrinting) { hexDump(bytes); }
+ long value = 0xaa55aa55aa55aa55L; // arbitrary starting value
+ for (int n = 0; n < 100; n++) {
+ for (int bits = 1; bits <= 63; bits++) {
+ if (enablePrinting) { System.out.println("bits " + bits); }
+ final long mask = (1L << bits) - 1;
+ long[] input = new long[8];
+ for (int i = 0; i < 8; ++i) {
+ input[i] = value & mask;
+ value += Util.INVERSE_GOLDEN_U64;
+ }
+ byte[] bytes = new byte[8 * Long.BYTES];
+ BitPacking.packBitsBlock8(input, 0, bytes, 0, bits);
+ if (enablePrinting) { hexDump(bytes); }
- long[] output = new long[8];
- BitPacking.unpackBitsBlock8(output, 0, bytes, 0, bits);
+ long[] output = new long[8];
+ BitPacking.unpackBitsBlock8(output, 0, bytes, 0, bits);
- for (int i = 0; i < 8; ++i) {
- if (enablePrinting) { System.out.println("checking value " + i); }
- assertEquals(output[i], input[i]);
+ for (int i = 0; i < 8; ++i) {
+ if (enablePrinting) { System.out.println("checking value " + i); }
+ assertEquals(output[i], input[i]);
+ }
}
}
}
From b1122dd005aeed872edc04dcdf9584a659e0dfa4 Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Fri, 10 Jan 2025 10:47:12 -0800
Subject: [PATCH 50/88] better error messages
---
src/main/java/org/apache/datasketches/theta/BitPacking.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/theta/BitPacking.java b/src/main/java/org/apache/datasketches/theta/BitPacking.java
index de914f908..99bcfb105 100644
--- a/src/main/java/org/apache/datasketches/theta/BitPacking.java
+++ b/src/main/java/org/apache/datasketches/theta/BitPacking.java
@@ -152,7 +152,7 @@ static void packBitsBlock8(final long[] values, final int i, final byte[] buf, f
case 61: packBits61(values, i, buf, off); break;
case 62: packBits62(values, i, buf, off); break;
case 63: packBits63(values, i, buf, off); break;
- default: throw new SketchesArgumentException("wrong number of bits " + bits);
+ default: throw new SketchesArgumentException("wrong number of bits in packBitsBlock8: " + bits);
}
}
@@ -221,7 +221,7 @@ static void unpackBitsBlock8(final long[] values, final int i, final byte[] buf,
case 61: unpackBits61(values, i, buf, off); break;
case 62: unpackBits62(values, i, buf, off); break;
case 63: unpackBits63(values, i, buf, off); break;
- default: throw new SketchesArgumentException("wrong number of bits " + bits);
+ default: throw new SketchesArgumentException("wrong number of bits unpackBitsBlock8: " + bits);
}
}
From 2d2579ed20a17d98482b07c728dc2738f3c38de1 Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Fri, 10 Jan 2025 10:47:58 -0800
Subject: [PATCH 51/88] more rounds of pseudo-random data
---
.../java/org/apache/datasketches/theta/BitPackingTest.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/test/java/org/apache/datasketches/theta/BitPackingTest.java b/src/test/java/org/apache/datasketches/theta/BitPackingTest.java
index 3ed6062e7..a961bffc0 100644
--- a/src/test/java/org/apache/datasketches/theta/BitPackingTest.java
+++ b/src/test/java/org/apache/datasketches/theta/BitPackingTest.java
@@ -32,7 +32,7 @@ public class BitPackingTest {
@Test
public void packUnpackBits() {
long value = 0xaa55aa55aa55aa55L; // arbitrary starting value
- for (int n = 0; n < 100; n++) {
+ for (int n = 0; n < 10000; n++) {
for (int bits = 1; bits <= 63; bits++) {
final long mask = (1 << bits) - 1;
long[] input = new long[8];
@@ -67,7 +67,7 @@ public void packUnpackBits() {
@Test
public void packUnpackBlocks() {
long value = 0xaa55aa55aa55aa55L; // arbitrary starting value
- for (int n = 0; n < 100; n++) {
+ for (int n = 0; n < 10000; n++) {
for (int bits = 1; bits <= 63; bits++) {
if (enablePrinting) { System.out.println("bits " + bits); }
final long mask = (1L << bits) - 1;
From 545427946b8744450ccca0f0218d88d1042c86de Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Mon, 13 Jan 2025 18:56:49 -0800
Subject: [PATCH 52/88] run javadoc action on push to main
---
.github/workflows/javadoc.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml
index 0381f43b8..ff724afaa 100644
--- a/.github/workflows/javadoc.yml
+++ b/.github/workflows/javadoc.yml
@@ -1,6 +1,8 @@
name: JavaDoc
on:
+ puah:
+ branches: main
workflow_dispatch:
jobs:
From 5bc58655705ec793a6f54c31178034ee90122703 Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Mon, 13 Jan 2025 19:14:43 -0800
Subject: [PATCH 53/88] typo fix
---
.github/workflows/javadoc.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml
index ff724afaa..bd5903836 100644
--- a/.github/workflows/javadoc.yml
+++ b/.github/workflows/javadoc.yml
@@ -1,7 +1,7 @@
name: JavaDoc
on:
- puah:
+ push:
branches: main
workflow_dispatch:
From 3b20aebe013c93536cf3ada5f21d4689a4789bac Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Tue, 14 Jan 2025 14:11:25 -0800
Subject: [PATCH 54/88] removed pattern that seems to be problematic
---
.github/workflows/check_cpp_files.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/check_cpp_files.yml b/.github/workflows/check_cpp_files.yml
index 00a9e5255..feac7a55a 100644
--- a/.github/workflows/check_cpp_files.yml
+++ b/.github/workflows/check_cpp_files.yml
@@ -2,10 +2,10 @@ name: CPP SerDe Compatibility Test
on:
push:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
pull_request:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
# The branches below must be a subset of the branches above
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
workflow_dispatch:
From 731a251cf43bb4d88bed78036c1efb4492f705af Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Tue, 14 Jan 2025 16:36:50 -0800
Subject: [PATCH 55/88] fix workflows ignore_paths
---
.github/workflows/auto-jdk-matrix.yml | 4 ++--
.github/workflows/auto-os-matrix.yml | 4 ++--
.github/workflows/check_cpp_files.yml | 4 ++--
.github/workflows/codeql-analysis.yml | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/auto-jdk-matrix.yml b/.github/workflows/auto-jdk-matrix.yml
index 7e1d26c70..8c20cc742 100644
--- a/.github/workflows/auto-jdk-matrix.yml
+++ b/.github/workflows/auto-jdk-matrix.yml
@@ -2,10 +2,10 @@ name: Auto JDK Matrix Test & Install
on:
push:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
pull_request:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
# The branches below must be a subset of the branches above
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
workflow_dispatch:
diff --git a/.github/workflows/auto-os-matrix.yml b/.github/workflows/auto-os-matrix.yml
index b56e5aa22..65be62f98 100644
--- a/.github/workflows/auto-os-matrix.yml
+++ b/.github/workflows/auto-os-matrix.yml
@@ -2,10 +2,10 @@ name: Auto OS Matrix Test & Install
on:
push:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
pull_request:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
# The branches below must be a subset of the branches above
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
workflow_dispatch:
diff --git a/.github/workflows/check_cpp_files.yml b/.github/workflows/check_cpp_files.yml
index 00a9e5255..feac7a55a 100644
--- a/.github/workflows/check_cpp_files.yml
+++ b/.github/workflows/check_cpp_files.yml
@@ -2,10 +2,10 @@ name: CPP SerDe Compatibility Test
on:
push:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
pull_request:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
# The branches below must be a subset of the branches above
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
workflow_dispatch:
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 734fbb60f..1102d3149 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -2,10 +2,10 @@ name: "CodeQL"
on:
push:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
pull_request:
- paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/.*', '**/LICENSE', '**/NOTICE' ]
+ paths-ignore: [ '**/*.html', '**/*.md', '**/*.txt', '**/*.xml', '**/*.yaml', '**/*.yml', '**/LICENSE', '**/NOTICE' ]
# The branches below must be a subset of the branches above
branches: [ 'main', '[0-9]+.[0-9]+.[Xx]' ]
workflow_dispatch:
From 982afa409c16c8218950a27732bf2ec5c4ed45df Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Tue, 14 Jan 2025 17:58:21 -0800
Subject: [PATCH 56/88] update notice
---
NOTICE | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/NOTICE b/NOTICE
index 8381c8de1..2ac24f2d3 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,9 +1,9 @@
Apache DataSketches Java
-Copyright 2024 The Apache Software Foundation
+Copyright 2025 The Apache Software Foundation
Copyright 2015-2018 Yahoo Inc.
Copyright 2019-2020 Verizon Media
-Copyright 2021 Yahoo Inc.
+Copyright 2021- Yahoo Inc.
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
From b70332aaf325e32f90f417f8c7579fccb58ec99a Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Fri, 17 Jan 2025 13:52:46 -0800
Subject: [PATCH 57/88] removed unused imports
---
.../datasketches/filters/bloomfilter/BloomFilterTest.java | 3 ---
.../java/org/apache/datasketches/hll/DirectAuxHashMapTest.java | 2 --
.../java/org/apache/datasketches/hll/DirectCouponListTest.java | 1 -
.../java/org/apache/datasketches/quantiles/DebugUnionTest.java | 2 --
.../quantiles/DirectQuantilesMemoryRequestTest.java | 2 --
.../java/org/apache/datasketches/theta/CompactSketchTest.java | 3 ---
.../apache/datasketches/theta/HeapifyWrapSerVer1and2Test.java | 3 ---
7 files changed, 16 deletions(-)
diff --git a/src/test/java/org/apache/datasketches/filters/bloomfilter/BloomFilterTest.java b/src/test/java/org/apache/datasketches/filters/bloomfilter/BloomFilterTest.java
index 25bef3643..7d72fae2f 100644
--- a/src/test/java/org/apache/datasketches/filters/bloomfilter/BloomFilterTest.java
+++ b/src/test/java/org/apache/datasketches/filters/bloomfilter/BloomFilterTest.java
@@ -24,12 +24,9 @@
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.assertTrue;
-import java.nio.ByteOrder;
-
import org.apache.datasketches.common.Family;
import org.apache.datasketches.common.SketchesArgumentException;
import org.apache.datasketches.common.SketchesReadOnlyException;
-import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
import org.testng.annotations.Test;
diff --git a/src/test/java/org/apache/datasketches/hll/DirectAuxHashMapTest.java b/src/test/java/org/apache/datasketches/hll/DirectAuxHashMapTest.java
index c913af378..75504bc83 100644
--- a/src/test/java/org/apache/datasketches/hll/DirectAuxHashMapTest.java
+++ b/src/test/java/org/apache/datasketches/hll/DirectAuxHashMapTest.java
@@ -35,8 +35,6 @@
import org.apache.datasketches.memory.WritableMemory;
import org.testng.annotations.Test;
-import jdk.incubator.foreign.ResourceScope;
-
/**
* @author Lee Rhodes
*/
diff --git a/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java b/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java
index 09eebabf7..1b00e0301 100644
--- a/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java
+++ b/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java
@@ -29,7 +29,6 @@
import jdk.incubator.foreign.ResourceScope;
-import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
diff --git a/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java b/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java
index 636105ef8..e51be4b20 100644
--- a/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java
@@ -23,14 +23,12 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
-import java.nio.ByteOrder;
import java.util.HashSet;
import org.testng.annotations.Test;
import jdk.incubator.foreign.ResourceScope;
-import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.WritableMemory;
import org.apache.datasketches.quantilescommon.QuantilesDoublesSketchIterator;
diff --git a/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java b/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java
index d896bbefa..5195f4187 100644
--- a/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java
@@ -32,8 +32,6 @@
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
-import jdk.incubator.foreign.ResourceScope;
-
/**
* The concept for these tests is that the "MemoryManager" classes below are proxies for the
* implementation that owns the native memory allocations, thus is responsible for
diff --git a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
index 188dbf427..e0f79087b 100644
--- a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
+++ b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
@@ -26,11 +26,8 @@
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
-import java.nio.ByteOrder;
-
import org.apache.datasketches.common.Family;
import org.apache.datasketches.common.SketchesArgumentException;
-import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
import org.testng.annotations.Test;
diff --git a/src/test/java/org/apache/datasketches/theta/HeapifyWrapSerVer1and2Test.java b/src/test/java/org/apache/datasketches/theta/HeapifyWrapSerVer1and2Test.java
index c0cff6eb2..3d4e20fe7 100644
--- a/src/test/java/org/apache/datasketches/theta/HeapifyWrapSerVer1and2Test.java
+++ b/src/test/java/org/apache/datasketches/theta/HeapifyWrapSerVer1and2Test.java
@@ -23,15 +23,12 @@
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
-import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
import org.apache.datasketches.thetacommon.ThetaUtil;
import org.apache.datasketches.tuple.Util;
import org.testng.annotations.Test;
-import jdk.incubator.foreign.ResourceScope;
-
@SuppressWarnings("resource")
public class HeapifyWrapSerVer1and2Test {
private static final short defaultSeedHash = Util.computeSeedHash(ThetaUtil.DEFAULT_UPDATE_SEED);
From adff89079a8439ce18ab373a34ab1730a8aa8f07 Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Sun, 26 Jan 2025 13:26:35 -0800
Subject: [PATCH 58/88] use iteration in set ops, wrap compressed sketch and
unpack in iterator
---
.../apache/datasketches/theta/AnotBimpl.java | 34 ++++++++---
.../datasketches/theta/CompactOperations.java | 2 +-
.../datasketches/theta/CompactSketch.java | 18 +++---
.../theta/DirectCompactSketch.java | 12 +---
.../datasketches/theta/IntersectionImpl.java | 59 +++++++++++--------
.../datasketches/theta/PreambleUtil.java | 3 +
.../org/apache/datasketches/theta/Sketch.java | 13 ++--
.../apache/datasketches/theta/UnionImpl.java | 55 ++++-------------
8 files changed, 92 insertions(+), 104 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/theta/AnotBimpl.java b/src/main/java/org/apache/datasketches/theta/AnotBimpl.java
index e7b2c99eb..6d4c54fd8 100644
--- a/src/main/java/org/apache/datasketches/theta/AnotBimpl.java
+++ b/src/main/java/org/apache/datasketches/theta/AnotBimpl.java
@@ -20,8 +20,11 @@
package org.apache.datasketches.theta;
import static org.apache.datasketches.common.Util.exactLog2OfLong;
-import static org.apache.datasketches.thetacommon.HashOperations.convertToHashTable;
+import static org.apache.datasketches.thetacommon.HashOperations.checkThetaCorruption;
+import static org.apache.datasketches.thetacommon.HashOperations.continueCondition;
import static org.apache.datasketches.thetacommon.HashOperations.hashSearch;
+import static org.apache.datasketches.thetacommon.HashOperations.hashSearchOrInsert;
+import static org.apache.datasketches.thetacommon.HashOperations.minLgHashTableSize;
import java.util.Arrays;
@@ -124,7 +127,7 @@ public CompactSketch aNotB(final Sketch skA, final Sketch skB, final boolean dst
if (skB.isEmpty()) {
return skA.compact(dstOrdered, dstMem);
- }
+ }
ThetaUtil.checkSeedHashes(skB.getSeedHash(), seedHash_);
//Both skA & skB are not empty
@@ -162,14 +165,12 @@ private static long[] getResultHashArr( //returns a new array
final long[] hashArrA,
final Sketch skB) {
- //Rebuild/get hashtable of skB
+ // Rebuild or get hashtable of skB
final long[] hashTableB; //read only
- final long[] thetaCache = skB.getCache();
- final int countB = skB.getRetainedEntries(true);
if (skB instanceof CompactSketch) {
- hashTableB = convertToHashTable(thetaCache, countB, minThetaLong, ThetaUtil.REBUILD_THRESHOLD);
+ hashTableB = convertToHashTable(skB, minThetaLong, ThetaUtil.REBUILD_THRESHOLD);
} else {
- hashTableB = thetaCache;
+ hashTableB = skB.getCache();
}
//build temporary result arrays of skA
@@ -191,6 +192,25 @@ private static long[] getResultHashArr( //returns a new array
return Arrays.copyOfRange(tmpHashArrA, 0, nonMatches);
}
+ private static long[] convertToHashTable(
+ final Sketch sketch,
+ final long thetaLong,
+ final double rebuildThreshold) {
+ final int lgArrLongs = minLgHashTableSize(sketch.getRetainedEntries(true), rebuildThreshold);
+ final int arrLongs = 1 << lgArrLongs;
+ final long[] hashTable = new long[arrLongs];
+ checkThetaCorruption(thetaLong);
+ HashIterator it = sketch.iterator();
+ while (it.next()) {
+ final long hash = it.get();
+ if (continueCondition(thetaLong, hash) ) {
+ continue;
+ }
+ hashSearchOrInsert(hashTable, lgArrLongs, hash);
+ }
+ return hashTable;
+ }
+
private void reset() {
thetaLong_ = Long.MAX_VALUE;
empty_ = true;
diff --git a/src/main/java/org/apache/datasketches/theta/CompactOperations.java b/src/main/java/org/apache/datasketches/theta/CompactOperations.java
index a8066314d..2b52f59fa 100644
--- a/src/main/java/org/apache/datasketches/theta/CompactOperations.java
+++ b/src/main/java/org/apache/datasketches/theta/CompactOperations.java
@@ -161,7 +161,7 @@ static CompactSketch memoryToCompact(
final long hash = srcMem.getLong(srcPreLongs << 3);
final SingleItemSketch sis = new SingleItemSketch(hash, srcSeedHash);
if (dstMem != null) {
- dstMem.putByteArray(0, sis.toByteArray(),0, 16);
+ dstMem.putByteArray(0, sis.toByteArray(), 0, 16);
return new DirectCompactSketch(dstMem);
} else { //heap
return sis;
diff --git a/src/main/java/org/apache/datasketches/theta/CompactSketch.java b/src/main/java/org/apache/datasketches/theta/CompactSketch.java
index 1426368f1..688ad2746 100644
--- a/src/main/java/org/apache/datasketches/theta/CompactSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/CompactSketch.java
@@ -32,6 +32,7 @@
import static org.apache.datasketches.theta.PreambleUtil.extractEntryBitsV4;
import static org.apache.datasketches.theta.PreambleUtil.extractNumEntriesBytesV4;
import static org.apache.datasketches.theta.PreambleUtil.extractThetaLongV4;
+import static org.apache.datasketches.theta.PreambleUtil.wholeBytesToHoldBits;
import static org.apache.datasketches.theta.SingleItemSketch.otherCheckForSingleItem;
import org.apache.datasketches.common.Family;
@@ -189,7 +190,8 @@ private static CompactSketch wrap(final Memory srcMem, final long seed, final bo
if (serVer == 4) {
// not wrapping the compressed format since currently we cannot take advantage of
// decompression during iteration because set operations reach into memory directly
- return heapifyV4(srcMem, seed, enforceSeed);
+ return DirectCompactCompressedSketch.wrapInstance(srcMem,
+ enforceSeed ? seedHash : (short) extractSeedHash(srcMem));
}
else if (serVer == 3) {
if (PreambleUtil.isEmptyFlag(srcMem)) {
@@ -274,10 +276,6 @@ private int computeMinLeadingZeros() {
return Long.numberOfLeadingZeros(ored);
}
- private static int wholeBytesToHoldBits(final int bits) {
- return (bits >>> 3) + ((bits & 7) > 0 ? 1 : 0);
- }
-
private byte[] toByteArrayV4() {
final int preambleLongs = isEstimationMode() ? 2 : 1;
final int entryBits = 64 - computeMinLeadingZeros();
@@ -286,8 +284,8 @@ private byte[] toByteArrayV4() {
// store num_entries as whole bytes since whole-byte blocks will follow (most probably)
final int numEntriesBytes = wholeBytesToHoldBits(32 - Integer.numberOfLeadingZeros(getRetainedEntries()));
- final int size = preambleLongs * Long.BYTES + numEntriesBytes + wholeBytesToHoldBits(compressedBits);
- final byte[] bytes = new byte[size];
+ final int sizeBytes = preambleLongs * Long.BYTES + numEntriesBytes + wholeBytesToHoldBits(compressedBits);
+ final byte[] bytes = new byte[sizeBytes];
final WritableMemory mem = WritableMemory.writableWrap(bytes);
int offsetBytes = 0;
mem.putByte(offsetBytes++, (byte) preambleLongs);
@@ -334,12 +332,10 @@ private byte[] toByteArrayV4() {
private static CompactSketch heapifyV4(final Memory srcMem, final long seed, final boolean enforceSeed) {
final int preLongs = extractPreLongs(srcMem);
- final int flags = extractFlags(srcMem);
final int entryBits = extractEntryBitsV4(srcMem);
final int numEntriesBytes = extractNumEntriesBytesV4(srcMem);
final short seedHash = (short) extractSeedHash(srcMem);
- final boolean isEmpty = (flags & EMPTY_FLAG_MASK) > 0;
- if (enforceSeed && !isEmpty) { PreambleUtil.checkMemorySeedHash(srcMem, seed); }
+ if (enforceSeed) { PreambleUtil.checkMemorySeedHash(srcMem, seed); }
int offsetBytes = 8;
long theta = Long.MAX_VALUE;
if (preLongs > 1) {
@@ -374,7 +370,7 @@ private static CompactSketch heapifyV4(final Memory srcMem, final long seed, fin
entries[i] += previous;
previous = entries[i];
}
- return new HeapCompactSketch(entries, isEmpty, seedHash, numEntries, theta, true);
+ return new HeapCompactSketch(entries, false, seedHash, numEntries, theta, true);
}
}
diff --git a/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java b/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java
index 0f69ec3c2..1714d2161 100644
--- a/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java
@@ -86,11 +86,7 @@ public int getCurrentBytes() {
@Override
public double getEstimate() {
- if (otherCheckForSingleItem(mem_)) { return 1; }
- final int preLongs = extractPreLongs(mem_);
- final int curCount = (preLongs == 1) ? 0 : extractCurCount(mem_);
- final long thetaLong = (preLongs > 2) ? extractThetaLong(mem_) : Long.MAX_VALUE;
- return Sketch.estimate(thetaLong, curCount);
+ return Sketch.estimate(getThetaLong(), getRetainedEntries());
}
@Override
@@ -142,10 +138,8 @@ public HashIterator iterator() {
@Override
public byte[] toByteArray() {
- final int curCount = getRetainedEntries(true);
- checkIllegalCurCountAndEmpty(isEmpty(), curCount);
- final int preLongs = extractPreLongs(mem_);
- final int outBytes = (curCount + preLongs) << 3;
+ checkIllegalCurCountAndEmpty(isEmpty(), getRetainedEntries());
+ final int outBytes = getCurrentBytes();
final byte[] byteArrOut = new byte[outBytes];
mem_.getByteArray(0, byteArrOut, 0, outBytes);
return byteArrOut;
diff --git a/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java b/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java
index fc81d1124..3404a0b11 100644
--- a/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java
+++ b/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java
@@ -288,7 +288,7 @@ else if (curCount_ < 0 && sketchInEntries > 0) {
else { //On the heap, allocate a HT
hashTable_ = new long[1 << lgArrLongs_];
}
- moveDataToTgt(sketchIn.getCache(), curCount_);
+ moveDataToTgt(sketchIn);
} //end of state 5
//state 7
@@ -434,8 +434,6 @@ long getThetaLong() {
private void performIntersect(final Sketch sketchIn) {
// curCount and input data are nonzero, match against HT
assert curCount_ > 0 && !empty_;
- final long[] cacheIn = sketchIn.getCache();
- final int arrLongsIn = cacheIn.length;
final long[] hashTable;
if (wmem_ != null) {
final int htLen = 1 << lgArrLongs_;
@@ -448,27 +446,16 @@ private void performIntersect(final Sketch sketchIn) {
final long[] matchSet = new long[ min(curCount_, sketchIn.getRetainedEntries(true)) ];
int matchSetCount = 0;
- if (sketchIn.isOrdered()) {
- //ordered compact, which enables early stop
- for (int i = 0; i < arrLongsIn; i++ ) {
- final long hashIn = cacheIn[i];
- //if (hashIn <= 0L) continue; //<= 0 should not happen
- if (hashIn >= thetaLong_) {
- break; //early stop assumes that hashes in input sketch are ordered!
- }
+ HashIterator it = sketchIn.iterator();
+ while (it.next()) {
+ final long hashIn = it.get();
+ if (hashIn < thetaLong_) {
final int foundIdx = hashSearch(hashTable, lgArrLongs_, hashIn);
- if (foundIdx == -1) { continue; }
- matchSet[matchSetCount++] = hashIn;
- }
- }
- else {
- //either unordered compact or hash table
- for (int i = 0; i < arrLongsIn; i++ ) {
- final long hashIn = cacheIn[i];
- if (hashIn <= 0L || hashIn >= thetaLong_) { continue; }
- final int foundIdx = hashSearch(hashTable, lgArrLongs_, hashIn);
- if (foundIdx == -1) { continue; }
- matchSet[matchSetCount++] = hashIn;
+ if (foundIdx != -1) {
+ matchSet[matchSetCount++] = hashIn;
+ }
+ } else {
+ if (sketchIn.isOrdered()) { break; } // early stop
}
}
//reduce effective array size to minimum
@@ -515,6 +502,32 @@ private void moveDataToTgt(final long[] arr, final int count) {
assert tmpCnt == count : "Intersection Count Check: got: " + tmpCnt + ", expected: " + count;
}
+ private void moveDataToTgt(final Sketch sketch) {
+ int count = sketch.getRetainedEntries();
+ int tmpCnt = 0;
+ if (wmem_ != null) { //Off Heap puts directly into mem
+ final int preBytes = CONST_PREAMBLE_LONGS << 3;
+ final int lgArrLongs = lgArrLongs_;
+ final long thetaLong = thetaLong_;
+ HashIterator it = sketch.iterator();
+ while (it.next()) {
+ final long hash = it.get();
+ if (continueCondition(thetaLong, hash)) { continue; }
+ hashInsertOnlyMemory(wmem_, lgArrLongs, hash, preBytes);
+ tmpCnt++;
+ }
+ } else { //On Heap. Assumes HT exists and is large enough
+ HashIterator it = sketch.iterator();
+ while (it.next()) {
+ final long hash = it.get();
+ if (continueCondition(thetaLong_, hash)) { continue; }
+ hashInsertOnly(hashTable_, lgArrLongs_, hash);
+ tmpCnt++;
+ }
+ }
+ assert tmpCnt == count : "Intersection Count Check: got: " + tmpCnt + ", expected: " + count;
+ }
+
private void hardReset() {
resetCommon();
if (wmem_ != null) {
diff --git a/src/main/java/org/apache/datasketches/theta/PreambleUtil.java b/src/main/java/org/apache/datasketches/theta/PreambleUtil.java
index e1d9262e6..ec0bc1268 100644
--- a/src/main/java/org/apache/datasketches/theta/PreambleUtil.java
+++ b/src/main/java/org/apache/datasketches/theta/PreambleUtil.java
@@ -524,4 +524,7 @@ private static void throwNotBigEnough(final long cap, final int required) {
+ ", Required: " + required);
}
+ static int wholeBytesToHoldBits(final int bits) {
+ return (bits >>> 3) + ((bits & 7) > 0 ? 1 : 0);
+ }
}
diff --git a/src/main/java/org/apache/datasketches/theta/Sketch.java b/src/main/java/org/apache/datasketches/theta/Sketch.java
index 89618bc23..6583e2dbf 100644
--- a/src/main/java/org/apache/datasketches/theta/Sketch.java
+++ b/src/main/java/org/apache/datasketches/theta/Sketch.java
@@ -451,9 +451,8 @@ public String toString(final boolean sketchSummary, final boolean dataDetail, fi
final boolean hexMode) {
final StringBuilder sb = new StringBuilder();
- final long[] cache = getCache();
int nomLongs = 0;
- int arrLongs = cache.length;
+ int arrLongs = 0;
float p = 0;
int rf = 0;
final boolean updateSketch = this instanceof UpdateSketch;
@@ -473,12 +472,10 @@ public String toString(final boolean sketchSummary, final boolean dataDetail, fi
final int w = width > 0 ? width : 8; // default is 8 wide
if (curCount > 0) {
sb.append("### SKETCH DATA DETAIL");
- for (int i = 0, j = 0; i < arrLongs; i++ ) {
- final long h;
- h = cache[i];
- if (h <= 0 || h >= thetaLong) {
- continue;
- }
+ HashIterator it = iterator();
+ int j = 0;
+ while (it.next()) {
+ final long h = it.get();
if (j % w == 0) {
sb.append(LS).append(String.format(" %6d", j + 1));
}
diff --git a/src/main/java/org/apache/datasketches/theta/UnionImpl.java b/src/main/java/org/apache/datasketches/theta/UnionImpl.java
index bac05de74..4fee6a9c5 100644
--- a/src/main/java/org/apache/datasketches/theta/UnionImpl.java
+++ b/src/main/java/org/apache/datasketches/theta/UnionImpl.java
@@ -320,46 +320,17 @@ public void union(final Sketch sketchIn) {
}
//sketchIn is valid and not empty
ThetaUtil.checkSeedHashes(expectedSeedHash_, sketchIn.getSeedHash());
- if (sketchIn instanceof SingleItemSketch) {
- gadget_.hashUpdate(sketchIn.getCache()[0]);
- return;
- }
Sketch.checkSketchAndMemoryFlags(sketchIn);
unionThetaLong_ = min(min(unionThetaLong_, sketchIn.getThetaLong()), gadget_.getThetaLong()); //Theta rule
unionEmpty_ = false;
- final int curCountIn = sketchIn.getRetainedEntries(true);
- if (curCountIn > 0) {
- if (sketchIn.isOrdered() && (sketchIn instanceof CompactSketch)) { //Use early stop
- //Ordered, thus compact
- if (sketchIn.hasMemory()) {
- final Memory skMem = sketchIn.getMemory();
- final int preambleLongs = skMem.getByte(PREAMBLE_LONGS_BYTE) & 0X3F;
- for (int i = 0; i < curCountIn; i++ ) {
- final int offsetBytes = preambleLongs + i << 3;
- final long hashIn = skMem.getLong(offsetBytes);
- if (hashIn >= unionThetaLong_) { break; } // "early stop"
- gadget_.hashUpdate(hashIn); //backdoor update, hash function is bypassed
- }
- }
- else { //sketchIn is on the Java Heap or has array
- final long[] cacheIn = sketchIn.getCache(); //not a copy!
- for (int i = 0; i < curCountIn; i++ ) {
- final long hashIn = cacheIn[i];
- if (hashIn >= unionThetaLong_) { break; } // "early stop"
- gadget_.hashUpdate(hashIn); //backdoor update, hash function is bypassed
- }
- }
- } //End ordered, compact
- else { //either not-ordered compact or Hash Table form. A HT may have dirty values.
- final long[] cacheIn = sketchIn.getCache(); //if off-heap this will be a copy
- final int arrLongs = cacheIn.length;
- for (int i = 0, c = 0; i < arrLongs && c < curCountIn; i++ ) {
- final long hashIn = cacheIn[i];
- if (hashIn <= 0L || hashIn >= unionThetaLong_) { continue; } //rejects dirty values
- gadget_.hashUpdate(hashIn); //backdoor update, hash function is bypassed
- c++; //ensures against invalid state inside the incoming sketch
- }
+ HashIterator it = sketchIn.iterator();
+ while (it.next()) {
+ final long hash = it.get();
+ if (hash < unionThetaLong_ && hash < gadget_.getThetaLong()) {
+ gadget_.hashUpdate(hash); // backdoor update, hash function is bypassed
+ } else {
+ if (sketchIn.isOrdered()) { break; }
}
}
unionThetaLong_ = min(unionThetaLong_, gadget_.getThetaLong()); //Theta rule with gadget
@@ -379,11 +350,8 @@ public void union(final Memory skMem) {
final int fam = extractFamilyID(skMem);
if (serVer == 4) { // compressed ordered compact
- // performance can be improved by decompression while performing the union
- // potentially only partial decompression might be needed
ThetaUtil.checkSeedHashes(expectedSeedHash_, (short) extractSeedHash(skMem));
- final CompactSketch csk = CompactSketch.wrap(skMem);
- union(csk);
+ union(CompactSketch.wrap(skMem));
return;
}
if (serVer == 3) { //The OpenSource sketches (Aug 4, 2015) starts with serVer = 3
@@ -396,16 +364,13 @@ public void union(final Memory skMem) {
}
if (serVer == 2) { //older Sketch, which is compact and ordered
ThetaUtil.checkSeedHashes(expectedSeedHash_, (short)extractSeedHash(skMem));
- final CompactSketch csk = ForwardCompatibility.heapify2to3(skMem, expectedSeedHash_);
- union(csk);
+ union(ForwardCompatibility.heapify2to3(skMem, expectedSeedHash_));
return;
}
if (serVer == 1) { //much older Sketch, which is compact and ordered, no seedHash
- final CompactSketch csk = ForwardCompatibility.heapify1to3(skMem, expectedSeedHash_);
- union(csk);
+ union(ForwardCompatibility.heapify1to3(skMem, expectedSeedHash_));
return;
}
-
throw new SketchesArgumentException("SerVer is unknown: " + serVer);
}
From a0f1fd6b44e354f62054b5bca76c12c62d47af50 Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Sun, 26 Jan 2025 13:33:41 -0800
Subject: [PATCH 59/88] wrapped compressed sketch
---
.../theta/DirectCompactCompressedSketch.java | 134 ++++++++++++++++++
.../MemoryCompactCompressedHashIterator.java | 107 ++++++++++++++
2 files changed, 241 insertions(+)
create mode 100644 src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java
create mode 100644 src/main/java/org/apache/datasketches/theta/MemoryCompactCompressedHashIterator.java
diff --git a/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java b/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java
new file mode 100644
index 000000000..65b7f877e
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta;
+
+import static org.apache.datasketches.theta.PreambleUtil.extractEntryBitsV4;
+import static org.apache.datasketches.theta.PreambleUtil.extractNumEntriesBytesV4;
+import static org.apache.datasketches.theta.PreambleUtil.extractPreLongs;
+import static org.apache.datasketches.theta.PreambleUtil.extractSeedHash;
+import static org.apache.datasketches.theta.PreambleUtil.extractThetaLongV4;
+import static org.apache.datasketches.theta.PreambleUtil.wholeBytesToHoldBits;
+
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableMemory;
+import org.apache.datasketches.thetacommon.ThetaUtil;
+
+/**
+ * An off-heap (Direct), compact, compressed, read-only sketch. It is not empty, not a single item and ordered.
+ *
+ * This sketch can only be associated with a Serialization Version 4 format binary image.
+ *
+ * This implementation uses data in a given Memory that is owned and managed by the caller.
+ * This Memory can be off-heap, which if managed properly will greatly reduce the need for
+ * the JVM to perform garbage collection.
+ */
+class DirectCompactCompressedSketch extends DirectCompactSketch {
+ /**
+ * Construct this sketch with the given memory.
+ * @param mem Read-only Memory object with the order bit properly set.
+ */
+ DirectCompactCompressedSketch(final Memory mem) {
+ super(mem);
+ }
+
+ /**
+ * Wraps the given Memory, which must be a SerVer 4 compressed CompactSketch image.
+ * Must check the validity of the Memory before calling. The order bit must be set properly.
+ * @param srcMem See Memory
+ * @param seedHash The update seedHash.
+ * See Seed Hash.
+ * @return this sketch
+ */
+ static DirectCompactCompressedSketch wrapInstance(final Memory srcMem, final short seedHash) {
+ ThetaUtil.checkSeedHashes((short) extractSeedHash(srcMem), seedHash);
+ return new DirectCompactCompressedSketch(srcMem);
+ }
+
+ //Sketch Overrides
+
+ @Override
+ public CompactSketch compact(final boolean dstOrdered, final WritableMemory dstMem) {
+ if (dstMem != null) {
+ mem_.copyTo(0, dstMem, 0, getCurrentBytes());
+ return new DirectCompactSketch(dstMem);
+ }
+ return CompactSketch.heapify(mem_);
+ }
+
+ @Override
+ public int getCurrentBytes() {
+ final int preLongs = extractPreLongs(mem_);
+ final int entryBits = extractEntryBitsV4(mem_);
+ final int numEntriesBytes = extractNumEntriesBytesV4(mem_);
+ return preLongs * Long.BYTES + numEntriesBytes + wholeBytesToHoldBits(getRetainedEntries() * entryBits);
+ }
+
+ @Override
+ public int getRetainedEntries(final boolean valid) { //compact is always valid
+ final int preLongs = extractPreLongs(mem_);
+ final int numEntriesBytes = extractNumEntriesBytesV4(mem_);
+ int offsetBytes = preLongs > 1 ? 16 : 8;
+ int numEntries = 0;
+ for (int i = 0; i < numEntriesBytes; i++) {
+ numEntries |= Byte.toUnsignedInt(mem_.getByte(offsetBytes++)) << (i << 3);
+ }
+ return numEntries;
+ }
+
+ @Override
+ public long getThetaLong() {
+ final int preLongs = extractPreLongs(mem_);
+ return (preLongs > 1) ? extractThetaLongV4(mem_) : Long.MAX_VALUE;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public boolean isOrdered() {
+ return true;
+ }
+
+ @Override
+ public HashIterator iterator() {
+ return new MemoryCompactCompressedHashIterator(
+ mem_,
+ (extractPreLongs(mem_) > 1 ? 16 : 8) + extractNumEntriesBytesV4(mem_),
+ extractEntryBitsV4(mem_),
+ getRetainedEntries()
+ );
+ }
+
+ //restricted methods
+
+ @Override
+ long[] getCache() {
+ final int numEntries = getRetainedEntries();
+ final long[] cache = new long[numEntries];
+ int i = 0;
+ HashIterator it = iterator();
+ while (it.next()) {
+ cache[i++] = it.get();
+ }
+ return cache;
+ }
+}
diff --git a/src/main/java/org/apache/datasketches/theta/MemoryCompactCompressedHashIterator.java b/src/main/java/org/apache/datasketches/theta/MemoryCompactCompressedHashIterator.java
new file mode 100644
index 000000000..b743302a5
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta/MemoryCompactCompressedHashIterator.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta;
+
+import static org.apache.datasketches.theta.PreambleUtil.wholeBytesToHoldBits;
+
+import org.apache.datasketches.memory.Memory;
+
+/**
+ * @author Lee Rhodes
+ */
+class MemoryCompactCompressedHashIterator implements HashIterator {
+ private Memory mem;
+ private int offset;
+ private int entryBits;
+ private int numEntries;
+ private int index;
+ private long previous;
+ private int offsetBits;
+ private long[] buffer;
+ private byte[] bytes;
+ private boolean isBlockMode;
+ private boolean isFirstUnpack1;
+
+ MemoryCompactCompressedHashIterator(
+ final Memory mem,
+ final int offset,
+ final int entryBits,
+ final int numEntries
+ ) {
+ this.mem = mem;
+ this.offset = offset;
+ this.entryBits = entryBits;
+ this.numEntries = numEntries;
+ index = -1;
+ previous = 0;
+ offsetBits = 0;
+ buffer = new long[8];
+ bytes = new byte[entryBits];
+ isBlockMode = numEntries >= 8;
+ isFirstUnpack1 = true;
+ }
+
+ @Override
+ public long get() {
+ return buffer[index & 7];
+ }
+
+ @Override
+ public boolean next() {
+ if (++index == numEntries) { return false; }
+ if (isBlockMode) {
+ if ((index & 7) == 0) {
+ if (numEntries - index >= 8) {
+ unpack8();
+ } else {
+ isBlockMode = false;
+ unpack1();
+ }
+ }
+ } else {
+ unpack1();
+ }
+ return true;
+ }
+
+ private void unpack1() {
+ if (isFirstUnpack1) {
+ mem.getByteArray(offset, bytes, 0, wholeBytesToHoldBits((numEntries - index) * entryBits));
+ offset = 0;
+ isFirstUnpack1 = false;
+ }
+ final int i = index & 7;
+ BitPacking.unpackBits(buffer, i, entryBits, bytes, offset, offsetBits);
+ offset += (offsetBits + entryBits) >>> 3;
+ offsetBits = (offsetBits + entryBits) & 7;
+ buffer[i] += previous;
+ previous = buffer[i];
+ }
+
+ private void unpack8() {
+ mem.getByteArray(offset, bytes, 0, entryBits);
+ BitPacking.unpackBitsBlock8(buffer, 0, bytes, 0, entryBits);
+ offset += entryBits;
+ for (int i = 0; i < 8; i++) {
+ buffer[i] += previous;
+ previous = buffer[i];
+ }
+ }
+}
From 2698f0d3bed93068514511455a6672549870e67d Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Mon, 27 Jan 2025 09:45:06 -0800
Subject: [PATCH 60/88] restored special treatment of single item sketch
---
src/main/java/org/apache/datasketches/theta/UnionImpl.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/apache/datasketches/theta/UnionImpl.java b/src/main/java/org/apache/datasketches/theta/UnionImpl.java
index 4fee6a9c5..9b98a9503 100644
--- a/src/main/java/org/apache/datasketches/theta/UnionImpl.java
+++ b/src/main/java/org/apache/datasketches/theta/UnionImpl.java
@@ -22,7 +22,6 @@
import static java.lang.Math.min;
import static org.apache.datasketches.theta.PreambleUtil.COMPACT_FLAG_MASK;
import static org.apache.datasketches.theta.PreambleUtil.ORDERED_FLAG_MASK;
-import static org.apache.datasketches.theta.PreambleUtil.PREAMBLE_LONGS_BYTE;
import static org.apache.datasketches.theta.PreambleUtil.UNION_THETA_LONG;
import static org.apache.datasketches.theta.PreambleUtil.clearEmpty;
import static org.apache.datasketches.theta.PreambleUtil.extractCurCount;
@@ -320,6 +319,10 @@ public void union(final Sketch sketchIn) {
}
//sketchIn is valid and not empty
ThetaUtil.checkSeedHashes(expectedSeedHash_, sketchIn.getSeedHash());
+ if (sketchIn instanceof SingleItemSketch) {
+ gadget_.hashUpdate(sketchIn.getCache()[0]);
+ return;
+ }
Sketch.checkSketchAndMemoryFlags(sketchIn);
unionThetaLong_ = min(min(unionThetaLong_, sketchIn.getThetaLong()), gadget_.getThetaLong()); //Theta rule
From 29895b3d053bb3401cfe3139c5d296c3812f32af Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Mon, 27 Jan 2025 16:13:04 -0800
Subject: [PATCH 61/88] addressed review points
---
.../org/apache/datasketches/theta/AnotBimpl.java | 2 +-
.../theta/DirectCompactCompressedSketch.java | 14 ++++++++++----
.../datasketches/theta/IntersectionImpl.java | 5 +++--
.../org/apache/datasketches/theta/UnionImpl.java | 5 +++--
4 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/theta/AnotBimpl.java b/src/main/java/org/apache/datasketches/theta/AnotBimpl.java
index 6d4c54fd8..cc076fd85 100644
--- a/src/main/java/org/apache/datasketches/theta/AnotBimpl.java
+++ b/src/main/java/org/apache/datasketches/theta/AnotBimpl.java
@@ -200,7 +200,7 @@ private static long[] convertToHashTable(
final int arrLongs = 1 << lgArrLongs;
final long[] hashTable = new long[arrLongs];
checkThetaCorruption(thetaLong);
- HashIterator it = sketch.iterator();
+ final HashIterator it = sketch.iterator();
while (it.next()) {
final long hash = it.get();
if (continueCondition(thetaLong, hash) ) {
diff --git a/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java b/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java
index 65b7f877e..d7e05ca2e 100644
--- a/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java
@@ -42,7 +42,7 @@
class DirectCompactCompressedSketch extends DirectCompactSketch {
/**
* Construct this sketch with the given memory.
- * @param mem Read-only Memory object with the order bit properly set.
+ * @param mem Read-only Memory object.
*/
DirectCompactCompressedSketch(final Memory mem) {
super(mem);
@@ -50,7 +50,7 @@ class DirectCompactCompressedSketch extends DirectCompactSketch {
/**
* Wraps the given Memory, which must be a SerVer 4 compressed CompactSketch image.
- * Must check the validity of the Memory before calling. The order bit must be set properly.
+ * Must check the validity of the Memory before calling.
* @param srcMem See Memory
* @param seedHash The update seedHash.
* See Seed Hash.
@@ -80,11 +80,17 @@ public int getCurrentBytes() {
return preLongs * Long.BYTES + numEntriesBytes + wholeBytesToHoldBits(getRetainedEntries() * entryBits);
}
+ private static final int START_PACKED_DATA_EXACT_MODE = 8;
+ private static final int START_PACKED_DATA_ESTIMATION_MODE = 16;
+
@Override
public int getRetainedEntries(final boolean valid) { //compact is always valid
- final int preLongs = extractPreLongs(mem_);
+ // number of entries is stored using variable length encoding
+ // most significant bytes with all zeros are not stored
+ // one byte in the preamble has the number of non-zero bytes used
+ final int preLongs = extractPreLongs(mem_); // if > 1 then the second long has theta
final int numEntriesBytes = extractNumEntriesBytesV4(mem_);
- int offsetBytes = preLongs > 1 ? 16 : 8;
+ int offsetBytes = preLongs > 1 ? START_PACKED_DATA_ESTIMATION_MODE : START_PACKED_DATA_EXACT_MODE;
int numEntries = 0;
for (int i = 0; i < numEntriesBytes; i++) {
numEntries |= Byte.toUnsignedInt(mem_.getByte(offsetBytes++)) << (i << 3);
diff --git a/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java b/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java
index 3404a0b11..b1be73c74 100644
--- a/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java
+++ b/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java
@@ -446,7 +446,8 @@ private void performIntersect(final Sketch sketchIn) {
final long[] matchSet = new long[ min(curCount_, sketchIn.getRetainedEntries(true)) ];
int matchSetCount = 0;
- HashIterator it = sketchIn.iterator();
+ final boolean isOrdered = sketchIn.isOrdered();
+ final HashIterator it = sketchIn.iterator();
while (it.next()) {
final long hashIn = it.get();
if (hashIn < thetaLong_) {
@@ -455,7 +456,7 @@ private void performIntersect(final Sketch sketchIn) {
matchSet[matchSetCount++] = hashIn;
}
} else {
- if (sketchIn.isOrdered()) { break; } // early stop
+ if (isOrdered) { break; } // early stop
}
}
//reduce effective array size to minimum
diff --git a/src/main/java/org/apache/datasketches/theta/UnionImpl.java b/src/main/java/org/apache/datasketches/theta/UnionImpl.java
index 9b98a9503..d5ae6071a 100644
--- a/src/main/java/org/apache/datasketches/theta/UnionImpl.java
+++ b/src/main/java/org/apache/datasketches/theta/UnionImpl.java
@@ -327,13 +327,14 @@ public void union(final Sketch sketchIn) {
unionThetaLong_ = min(min(unionThetaLong_, sketchIn.getThetaLong()), gadget_.getThetaLong()); //Theta rule
unionEmpty_ = false;
- HashIterator it = sketchIn.iterator();
+ final boolean isOrdered = sketchIn.isOrdered();
+ final HashIterator it = sketchIn.iterator();
while (it.next()) {
final long hash = it.get();
if (hash < unionThetaLong_ && hash < gadget_.getThetaLong()) {
gadget_.hashUpdate(hash); // backdoor update, hash function is bypassed
} else {
- if (sketchIn.isOrdered()) { break; }
+ if (isOrdered) { break; }
}
}
unionThetaLong_ = min(unionThetaLong_, gadget_.getThetaLong()); //Theta rule with gadget
From 2f2e5e592dfcc810a552e6917b1fdd7cdf665025 Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Mon, 27 Jan 2025 19:41:40 -0800
Subject: [PATCH 62/88] test equivalence of packing blocks and single values
---
.../datasketches/theta/BitPackingTest.java | 65 +++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/src/test/java/org/apache/datasketches/theta/BitPackingTest.java b/src/test/java/org/apache/datasketches/theta/BitPackingTest.java
index a961bffc0..c155bef77 100644
--- a/src/test/java/org/apache/datasketches/theta/BitPackingTest.java
+++ b/src/test/java/org/apache/datasketches/theta/BitPackingTest.java
@@ -40,6 +40,7 @@ public void packUnpackBits() {
input[i] = value & mask;
value += Util.INVERSE_GOLDEN_U64;
}
+
byte[] bytes = new byte[8 * Long.BYTES];
int bitOffset = 0;
int bufOffset = 0;
@@ -57,6 +58,7 @@ public void packUnpackBits() {
bufOffset += (bitOffset + bits) >>> 3;
bitOffset = (bitOffset + bits) & 7;
}
+
for (int i = 0; i < 8; ++i) {
assertEquals(output[i], input[i]);
}
@@ -76,6 +78,7 @@ public void packUnpackBlocks() {
input[i] = value & mask;
value += Util.INVERSE_GOLDEN_U64;
}
+
byte[] bytes = new byte[8 * Long.BYTES];
BitPacking.packBitsBlock8(input, 0, bytes, 0, bits);
if (enablePrinting) { hexDump(bytes); }
@@ -91,6 +94,68 @@ public void packUnpackBlocks() {
}
}
+ @Test
+ public void packBitsUnpackBlocks() {
+ long value = 0; // arbitrary starting value
+ for (int n = 0; n < 10000; n++) {
+ for (int bits = 1; bits <= 63; bits++) {
+ final long mask = (1 << bits) - 1;
+ long[] input = new long[8];
+ for (int i = 0; i < 8; ++i) {
+ input[i] = value & mask;
+ value += Util.INVERSE_GOLDEN_U64;
+ }
+
+ byte[] bytes = new byte[8 * Long.BYTES];
+ int bitOffset = 0;
+ int bufOffset = 0;
+ for (int i = 0; i < 8; ++i) {
+ BitPacking.packBits(input[i], bits, bytes, bufOffset, bitOffset);
+ bufOffset += (bitOffset + bits) >>> 3;
+ bitOffset = (bitOffset + bits) & 7;
+ }
+
+ long[] output = new long[8];
+ BitPacking.unpackBitsBlock8(output, 0, bytes, 0, bits);
+
+ for (int i = 0; i < 8; ++i) {
+ assertEquals(output[i], input[i]);
+ }
+ }
+ }
+ }
+
+ @Test
+ public void packBlocksUnpackBits() {
+ long value = 123L; // arbitrary starting value
+ for (int n = 0; n < 10000; n++) {
+ for (int bits = 1; bits <= 63; bits++) {
+ final long mask = (1 << bits) - 1;
+ long[] input = new long[8];
+ for (int i = 0; i < 8; ++i) {
+ input[i] = value & mask;
+ value += Util.INVERSE_GOLDEN_U64;
+ }
+
+ byte[] bytes = new byte[8 * Long.BYTES];
+ BitPacking.packBitsBlock8(input, 0, bytes, 0, bits);
+
+ long[] output = new long[8];
+ int bitOffset = 0;
+ int bufOffset = 0;
+ for (int i = 0; i < 8; ++i) {
+ BitPacking.unpackBits(output, i, bits, bytes, bufOffset, bitOffset);
+ bufOffset += (bitOffset + bits) >>> 3;
+ bitOffset = (bitOffset + bits) & 7;
+ }
+
+ for (int i = 0; i < 8; ++i) {
+ assertEquals(output[i], input[i]);
+ }
+ }
+ }
+ }
+
void hexDump(byte[] bytes) {
for (int i = 0; i < bytes.length; i++) {
System.out.print(String.format("%02x ", bytes[i]));
From a0b86ee3cd4f01bd36a5f4e426f4df0d335cd943 Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Wed, 29 Jan 2025 12:05:30 -0800
Subject: [PATCH 63/88] cleanup
---
.../java/org/apache/datasketches/theta/CompactSketch.java | 7 +++++--
.../datasketches/theta/DirectCompactCompressedSketch.java | 3 ++-
.../org/apache/datasketches/theta/DirectCompactSketch.java | 5 -----
.../org/apache/datasketches/theta/HeapCompactSketch.java | 5 -----
.../theta/MemoryCompactCompressedHashIterator.java | 4 ++--
5 files changed, 9 insertions(+), 15 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/theta/CompactSketch.java b/src/main/java/org/apache/datasketches/theta/CompactSketch.java
index 688ad2746..7a366fe0b 100644
--- a/src/main/java/org/apache/datasketches/theta/CompactSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/CompactSketch.java
@@ -188,8 +188,6 @@ private static CompactSketch wrap(final Memory srcMem, final long seed, final bo
final short seedHash = ThetaUtil.computeSeedHash(seed);
if (serVer == 4) {
- // not wrapping the compressed format since currently we cannot take advantage of
- // decompression during iteration because set operations reach into memory directly
return DirectCompactCompressedSketch.wrapInstance(srcMem,
enforceSeed ? seedHash : (short) extractSeedHash(srcMem));
}
@@ -251,6 +249,11 @@ public boolean isCompact() {
return true;
}
+ @Override
+ public double getEstimate() {
+ return Sketch.estimate(getThetaLong(), getRetainedEntries());
+ }
+
/**
* gets the sketch as a compressed byte array
* @return the sketch as a compressed byte array
diff --git a/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java b/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java
index d7e05ca2e..6c83add87 100644
--- a/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java
@@ -118,7 +118,8 @@ public boolean isOrdered() {
public HashIterator iterator() {
return new MemoryCompactCompressedHashIterator(
mem_,
- (extractPreLongs(mem_) > 1 ? 16 : 8) + extractNumEntriesBytesV4(mem_),
+ (extractPreLongs(mem_) > 1 ? START_PACKED_DATA_ESTIMATION_MODE : START_PACKED_DATA_EXACT_MODE)
+ + extractNumEntriesBytesV4(mem_),
extractEntryBitsV4(mem_),
getRetainedEntries()
);
diff --git a/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java b/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java
index 1714d2161..baedad179 100644
--- a/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java
@@ -84,11 +84,6 @@ public int getCurrentBytes() {
return (preLongs + curCount) << 3;
}
- @Override
- public double getEstimate() {
- return Sketch.estimate(getThetaLong(), getRetainedEntries());
- }
-
@Override
public int getRetainedEntries(final boolean valid) { //compact is always valid
if (otherCheckForSingleItem(mem_)) { return 1; }
diff --git a/src/main/java/org/apache/datasketches/theta/HeapCompactSketch.java b/src/main/java/org/apache/datasketches/theta/HeapCompactSketch.java
index f394e9303..2572ce5d5 100644
--- a/src/main/java/org/apache/datasketches/theta/HeapCompactSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/HeapCompactSketch.java
@@ -87,11 +87,6 @@ public int getCurrentBytes() {
return (preLongs_ + curCount_) << 3;
}
- @Override
- public double getEstimate() {
- return Sketch.estimate(thetaLong_, curCount_);
- }
-
@Override
public int getRetainedEntries(final boolean valid) {
return curCount_;
diff --git a/src/main/java/org/apache/datasketches/theta/MemoryCompactCompressedHashIterator.java b/src/main/java/org/apache/datasketches/theta/MemoryCompactCompressedHashIterator.java
index b743302a5..d5f37de96 100644
--- a/src/main/java/org/apache/datasketches/theta/MemoryCompactCompressedHashIterator.java
+++ b/src/main/java/org/apache/datasketches/theta/MemoryCompactCompressedHashIterator.java
@@ -23,8 +23,8 @@
import org.apache.datasketches.memory.Memory;
-/**
- * @author Lee Rhodes
+/*
+ * This is to uncompress serial version 4 sketch incrementally
*/
class MemoryCompactCompressedHashIterator implements HashIterator {
private Memory mem;
From bde0b6f2689ea671b7a2f72c1ecdf028565e3f9c Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Tue, 4 Feb 2025 16:15:20 -0800
Subject: [PATCH 64/88] wrap(byte[])
---
.../BytesCompactCompressedHashIterator.java | 93 ++++++++++
.../theta/BytesCompactHashIterator.java | 53 ++++++
.../datasketches/theta/CompactSketch.java | 54 ++++++
.../theta/DirectCompactSketch.java | 4 +-
.../theta/WrappedCompactCompressedSketch.java | 111 ++++++++++++
.../theta/WrappedCompactSketch.java | 165 ++++++++++++++++++
.../datasketches/theta/CompactSketchTest.java | 34 ++++
7 files changed, 512 insertions(+), 2 deletions(-)
create mode 100644 src/main/java/org/apache/datasketches/theta/BytesCompactCompressedHashIterator.java
create mode 100644 src/main/java/org/apache/datasketches/theta/BytesCompactHashIterator.java
create mode 100644 src/main/java/org/apache/datasketches/theta/WrappedCompactCompressedSketch.java
create mode 100644 src/main/java/org/apache/datasketches/theta/WrappedCompactSketch.java
diff --git a/src/main/java/org/apache/datasketches/theta/BytesCompactCompressedHashIterator.java b/src/main/java/org/apache/datasketches/theta/BytesCompactCompressedHashIterator.java
new file mode 100644
index 000000000..97792da26
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta/BytesCompactCompressedHashIterator.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta;
+
+/*
+ * This is to uncompress serial version 4 sketch incrementally
+ */
+class BytesCompactCompressedHashIterator implements HashIterator {
+ private byte[] bytes;
+ private int offset;
+ private int entryBits;
+ private int numEntries;
+ private int index;
+ private long previous;
+ private int offsetBits;
+ private long[] buffer;
+ private boolean isBlockMode;
+
+ BytesCompactCompressedHashIterator(
+ final byte[] bytes,
+ final int offset,
+ final int entryBits,
+ final int numEntries
+ ) {
+ this.bytes = bytes;
+ this.offset = offset;
+ this.entryBits = entryBits;
+ this.numEntries = numEntries;
+ index = -1;
+ previous = 0;
+ offsetBits = 0;
+ buffer = new long[8];
+ isBlockMode = numEntries >= 8;
+ }
+
+ @Override
+ public long get() {
+ return buffer[index & 7];
+ }
+
+ @Override
+ public boolean next() {
+ if (++index == numEntries) { return false; }
+ if (isBlockMode) {
+ if ((index & 7) == 0) {
+ if (numEntries - index >= 8) {
+ unpack8();
+ } else {
+ isBlockMode = false;
+ unpack1();
+ }
+ }
+ } else {
+ unpack1();
+ }
+ return true;
+ }
+
+ private void unpack1() {
+ final int i = index & 7;
+ BitPacking.unpackBits(buffer, i, entryBits, bytes, offset, offsetBits);
+ offset += (offsetBits + entryBits) >>> 3;
+ offsetBits = (offsetBits + entryBits) & 7;
+ buffer[i] += previous;
+ previous = buffer[i];
+ }
+
+ private void unpack8() {
+ BitPacking.unpackBitsBlock8(buffer, 0, bytes, offset, entryBits);
+ offset += entryBits;
+ for (int i = 0; i < 8; i++) {
+ buffer[i] += previous;
+ previous = buffer[i];
+ }
+ }
+}
diff --git a/src/main/java/org/apache/datasketches/theta/BytesCompactHashIterator.java b/src/main/java/org/apache/datasketches/theta/BytesCompactHashIterator.java
new file mode 100644
index 000000000..20e21da11
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta/BytesCompactHashIterator.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta;
+
+import org.apache.datasketches.common.ByteArrayUtil;
+
+/*
+ * This is to iterate over serial version 3 sketch representation
+ */
+class BytesCompactHashIterator implements HashIterator {
+ final private byte[] bytes;
+ final private int offset;
+ final private int numEntries;
+ private int index;
+
+ BytesCompactHashIterator(
+ final byte[] bytes,
+ final int offset,
+ final int numEntries
+ ) {
+ this.bytes = bytes;
+ this.offset = offset;
+ this.numEntries = numEntries;
+ index = -1;
+ }
+
+ @Override
+ public long get() {
+ return ByteArrayUtil.getLongLE(bytes, offset + index * Long.BYTES);
+ }
+
+ @Override
+ public boolean next() {
+ return ++index < numEntries;
+ }
+}
diff --git a/src/main/java/org/apache/datasketches/theta/CompactSketch.java b/src/main/java/org/apache/datasketches/theta/CompactSketch.java
index 7a366fe0b..b64314168 100644
--- a/src/main/java/org/apache/datasketches/theta/CompactSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/CompactSketch.java
@@ -19,11 +19,15 @@
package org.apache.datasketches.theta;
+import static org.apache.datasketches.common.ByteArrayUtil.getShortLE;
import static org.apache.datasketches.common.Family.idToFamily;
import static org.apache.datasketches.theta.PreambleUtil.COMPACT_FLAG_MASK;
import static org.apache.datasketches.theta.PreambleUtil.EMPTY_FLAG_MASK;
+import static org.apache.datasketches.theta.PreambleUtil.FLAGS_BYTE;
import static org.apache.datasketches.theta.PreambleUtil.ORDERED_FLAG_MASK;
+import static org.apache.datasketches.theta.PreambleUtil.PREAMBLE_LONGS_BYTE;
import static org.apache.datasketches.theta.PreambleUtil.READ_ONLY_FLAG_MASK;
+import static org.apache.datasketches.theta.PreambleUtil.SEED_HASH_SHORT;
import static org.apache.datasketches.theta.PreambleUtil.extractFamilyID;
import static org.apache.datasketches.theta.PreambleUtil.extractFlags;
import static org.apache.datasketches.theta.PreambleUtil.extractPreLongs;
@@ -224,6 +228,56 @@ else if (serVer == 2) {
"Corrupted: Serialization Version " + serVer + " not recognized.");
}
+ public static CompactSketch wrap(final byte[] bytes) {
+ return wrap(bytes, ThetaUtil.DEFAULT_UPDATE_SEED, false);
+ }
+
+ public static CompactSketch wrap(final byte[] bytes, final long expectedSeed) {
+ return wrap(bytes, expectedSeed, true);
+ }
+
+ private static CompactSketch wrap(final byte[] bytes, final long seed, final boolean enforceSeed) {
+ final int serVer = bytes[PreambleUtil.SER_VER_BYTE];
+ final int familyId = bytes[PreambleUtil.FAMILY_BYTE];
+ final Family family = Family.idToFamily(familyId);
+ if (family != Family.COMPACT) {
+ throw new IllegalArgumentException("Corrupted: " + family + " is not Compact!");
+ }
+ final short seedHash = ThetaUtil.computeSeedHash(seed);
+ if (serVer == 4) {
+ return WrappedCompactCompressedSketch.wrapInstance(bytes, seedHash);
+ } else if (serVer == 3) {
+ final int flags = bytes[FLAGS_BYTE];
+ if ((flags & EMPTY_FLAG_MASK) > 0) {
+ return EmptyCompactSketch.getHeapInstance(Memory.wrap(bytes));
+ }
+ final int preLongs = bytes[PREAMBLE_LONGS_BYTE];
+ if (otherCheckForSingleItem(preLongs, serVer, familyId, flags)) {
+ return SingleItemSketch.heapify(Memory.wrap(bytes), enforceSeed ? seedHash : getShortLE(bytes, SEED_HASH_SHORT));
+ }
+ //not empty & not singleItem
+ final boolean compactFlag = (flags & COMPACT_FLAG_MASK) > 0;
+ if (!compactFlag) {
+ throw new SketchesArgumentException(
+ "Corrupted: COMPACT family sketch image must have compact flag set");
+ }
+ final boolean readOnly = (flags & READ_ONLY_FLAG_MASK) > 0;
+ if (!readOnly) {
+ throw new SketchesArgumentException(
+ "Corrupted: COMPACT family sketch image must have Read-Only flag set");
+ }
+ return WrappedCompactSketch.wrapInstance(bytes,
+ enforceSeed ? seedHash : getShortLE(bytes, SEED_HASH_SHORT));
+ } else if (serVer == 1) {
+ return ForwardCompatibility.heapify1to3(Memory.wrap(bytes), seedHash);
+ } else if (serVer == 2) {
+ return ForwardCompatibility.heapify2to3(Memory.wrap(bytes),
+ enforceSeed ? seedHash : getShortLE(bytes, SEED_HASH_SHORT));
+ }
+ throw new SketchesArgumentException(
+ "Corrupted: Serialization Version " + serVer + " not recognized.");
+ }
+
//Sketch Overrides
@Override
diff --git a/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java b/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java
index baedad179..15b03311b 100644
--- a/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/DirectCompactSketch.java
@@ -35,7 +35,7 @@
/**
* An off-heap (Direct), compact, read-only sketch. The internal hash array can be either ordered
- * or unordered.
+ * or unordered. It is not empty, not a single item.
*
* This sketch can only be associated with a Serialization Version 3 format binary image.
*
@@ -57,7 +57,7 @@ class DirectCompactSketch extends CompactSketch {
}
/**
- * Wraps the given Memory, which must be a SerVer 3, ordered, CompactSketch image.
+ * Wraps the given Memory, which must be a SerVer 3, CompactSketch image.
* Must check the validity of the Memory before calling. The order bit must be set properly.
* @param srcMem See Memory
* @param seedHash The update seedHash.
diff --git a/src/main/java/org/apache/datasketches/theta/WrappedCompactCompressedSketch.java b/src/main/java/org/apache/datasketches/theta/WrappedCompactCompressedSketch.java
new file mode 100644
index 000000000..170c98cad
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta/WrappedCompactCompressedSketch.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta;
+
+import static org.apache.datasketches.theta.PreambleUtil.wholeBytesToHoldBits;
+import static org.apache.datasketches.theta.PreambleUtil.ENTRY_BITS_BYTE_V4;
+import static org.apache.datasketches.theta.PreambleUtil.NUM_ENTRIES_BYTES_BYTE_V4;
+import static org.apache.datasketches.theta.PreambleUtil.PREAMBLE_LONGS_BYTE;
+
+import org.apache.datasketches.common.ByteArrayUtil;
+import org.apache.datasketches.thetacommon.ThetaUtil;
+
+/**
+ * Wrapper around a serialized compact compressed read-only sketch. It is not empty, not a single item.
+ *
+ * This sketch can only be associated with a Serialization Version 4 format binary image.
+ */
+class WrappedCompactCompressedSketch extends WrappedCompactSketch {
+
+ /**
+ * Construct this sketch with the given bytes.
+ * @param bytes containing serialized compact compressed sketch.
+ */
+ WrappedCompactCompressedSketch(final byte[] bytes) {
+ super(bytes);
+ }
+
+ /**
+ * Wraps the given bytes, which must be a SerVer 4 compressed CompactSketch image.
+ * @param bytes representation of serialized compressed compact sketch.
+ * @param seedHash The update seedHash.
+ * See Seed Hash.
+ * @return this sketch
+ */
+ static WrappedCompactCompressedSketch wrapInstance(final byte[] bytes, final short seedHash) {
+ ThetaUtil.checkSeedHashes(ByteArrayUtil.getShortLE(bytes, PreambleUtil.SEED_HASH_SHORT), seedHash);
+ return new WrappedCompactCompressedSketch(bytes);
+ }
+
+ //Sketch Overrides
+
+ @Override
+ public int getCurrentBytes() {
+ final int preLongs = bytes_[PREAMBLE_LONGS_BYTE];
+ final int entryBits = bytes_[ENTRY_BITS_BYTE_V4];
+ final int numEntriesBytes = bytes_[NUM_ENTRIES_BYTES_BYTE_V4];
+ return preLongs * Long.BYTES + numEntriesBytes + wholeBytesToHoldBits(getRetainedEntries() * entryBits);
+ }
+
+ private static final int START_PACKED_DATA_EXACT_MODE = 8;
+ private static final int START_PACKED_DATA_ESTIMATION_MODE = 16;
+
+ @Override
+ public int getRetainedEntries(final boolean valid) { //compact is always valid
+ // number of entries is stored using variable length encoding
+ // most significant bytes with all zeros are not stored
+ // one byte in the preamble has the number of non-zero bytes used
+ final int preLongs = bytes_[PREAMBLE_LONGS_BYTE]; // if > 1 then the second long has theta
+ final int numEntriesBytes = bytes_[NUM_ENTRIES_BYTES_BYTE_V4];
+ int offsetBytes = preLongs > 1 ? START_PACKED_DATA_ESTIMATION_MODE : START_PACKED_DATA_EXACT_MODE;
+ int numEntries = 0;
+ for (int i = 0; i < numEntriesBytes; i++) {
+ numEntries |= Byte.toUnsignedInt(bytes_[offsetBytes++]) << (i << 3);
+ }
+ return numEntries;
+ }
+
+ @Override
+ public long getThetaLong() {
+ final int preLongs = bytes_[PREAMBLE_LONGS_BYTE];
+ return (preLongs > 1) ? ByteArrayUtil.getLongLE(bytes_, 8) : Long.MAX_VALUE;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public boolean isOrdered() {
+ return true;
+ }
+
+ @Override
+ public HashIterator iterator() {
+ return new BytesCompactCompressedHashIterator(
+ bytes_,
+ (bytes_[PREAMBLE_LONGS_BYTE] > 1 ? START_PACKED_DATA_ESTIMATION_MODE : START_PACKED_DATA_EXACT_MODE)
+ + bytes_[NUM_ENTRIES_BYTES_BYTE_V4],
+ bytes_[ENTRY_BITS_BYTE_V4],
+ getRetainedEntries()
+ );
+ }
+}
diff --git a/src/main/java/org/apache/datasketches/theta/WrappedCompactSketch.java b/src/main/java/org/apache/datasketches/theta/WrappedCompactSketch.java
new file mode 100644
index 000000000..b1073159b
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta/WrappedCompactSketch.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta;
+
+import static org.apache.datasketches.common.ByteArrayUtil.getIntLE;
+import static org.apache.datasketches.common.ByteArrayUtil.getLongLE;
+import static org.apache.datasketches.common.ByteArrayUtil.getShortLE;
+import static org.apache.datasketches.theta.CompactOperations.memoryToCompact;
+import static org.apache.datasketches.theta.PreambleUtil.EMPTY_FLAG_MASK;
+import static org.apache.datasketches.theta.PreambleUtil.ORDERED_FLAG_MASK;
+import static org.apache.datasketches.theta.PreambleUtil.FLAGS_BYTE;
+import static org.apache.datasketches.theta.PreambleUtil.RETAINED_ENTRIES_INT;
+import static org.apache.datasketches.theta.PreambleUtil.PREAMBLE_LONGS_BYTE;
+import static org.apache.datasketches.theta.PreambleUtil.THETA_LONG;
+import static org.apache.datasketches.theta.PreambleUtil.SEED_HASH_SHORT;
+
+import java.util.Arrays;
+
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableMemory;
+import org.apache.datasketches.thetacommon.ThetaUtil;
+
+/**
+ * Wrapper around a serialized compact read-only sketch. It is not empty, not a single item.
+ *
+ * This sketch can only be associated with a Serialization Version 3 format binary image.
+ */
+class WrappedCompactSketch extends CompactSketch {
+ final byte[] bytes_;
+
+ /**
+ * Construct this sketch with the given bytes.
+ * @param bytes containing serialized compact sketch.
+ */
+ WrappedCompactSketch(final byte[] bytes) {
+ bytes_ = bytes;
+ }
+
+ /**
+ * Wraps the given Memory, which must be a SerVer 3 CompactSketch image.
+ * @param bytes representation of serialized compressed compact sketch.
+ * @param seedHash The update seedHash.
+ * See Seed Hash.
+ * @return this sketch
+ */
+ static WrappedCompactSketch wrapInstance(final byte[] bytes, final short seedHash) {
+ ThetaUtil.checkSeedHashes(getShortLE(bytes, SEED_HASH_SHORT), seedHash);
+ return new WrappedCompactSketch(bytes);
+ }
+
+ //Sketch Overrides
+
+ @Override
+ public CompactSketch compact(final boolean dstOrdered, final WritableMemory dstMem) {
+ return memoryToCompact(Memory.wrap(bytes_), dstOrdered, dstMem);
+ }
+
+ @Override
+ public int getCurrentBytes() {
+ final int preLongs = bytes_[PreambleUtil.PREAMBLE_LONGS_BYTE];
+ final int numEntries = (preLongs == 1) ? 0 : getIntLE(bytes_, RETAINED_ENTRIES_INT);
+ return (preLongs + numEntries) << 3;
+ }
+
+ @Override
+ public int getRetainedEntries(final boolean valid) { //compact is always valid
+ final int preLongs = bytes_[PREAMBLE_LONGS_BYTE];
+ return (preLongs == 1) ? 0 : getIntLE(bytes_, RETAINED_ENTRIES_INT);
+ }
+
+ @Override
+ public long getThetaLong() {
+ final int preLongs = bytes_[PREAMBLE_LONGS_BYTE];
+ return (preLongs > 2) ? getLongLE(bytes_, THETA_LONG) : Long.MAX_VALUE;
+ }
+
+ @Override
+ public boolean hasMemory() {
+ return false;
+ }
+
+ @Override
+ public boolean isDirect() {
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (bytes_[FLAGS_BYTE] & EMPTY_FLAG_MASK) > 0;
+ }
+
+ @Override
+ public boolean isOrdered() {
+ return (bytes_[FLAGS_BYTE] & ORDERED_FLAG_MASK) > 0;
+ }
+
+ @Override
+ public boolean isSameResource(final Memory that) {
+ return false;
+ }
+
+ @Override
+ public HashIterator iterator() {
+ return new BytesCompactHashIterator(
+ bytes_,
+ bytes_[PREAMBLE_LONGS_BYTE] << 3,
+ getRetainedEntries()
+ );
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ return Arrays.copyOf(bytes_, getCurrentBytes());
+ }
+
+ //restricted methods
+
+ @Override
+ long[] getCache() {
+ final long[] cache = new long[getRetainedEntries()];
+ int i = 0;
+ HashIterator it = iterator();
+ while (it.next()) {
+ cache[i++] = it.get();
+ }
+ return cache;
+ }
+
+ @Override
+ int getCompactPreambleLongs() {
+ return bytes_[PREAMBLE_LONGS_BYTE];
+ }
+
+ @Override
+ int getCurrentPreambleLongs() {
+ return bytes_[PREAMBLE_LONGS_BYTE];
+ }
+
+ @Override
+ Memory getMemory() {
+ return null;
+ }
+
+ @Override
+ short getSeedHash() {
+ return getShortLE(bytes_, SEED_HASH_SHORT);
+ }
+}
diff --git a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
index e0f79087b..0b49f2389 100644
--- a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
+++ b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
@@ -587,6 +587,40 @@ public void serializeDeserializeDirectV4() {
}
}
+ @Test
+ public void serializeWrapBytesV3() {
+ UpdateSketch sk = Sketches.updateSketchBuilder().build();
+ for (int i = 0; i < 10000; i++) {
+ sk.update(i);
+ }
+ CompactSketch cs1 = sk.compact();
+ byte[] bytes = cs1.toByteArray();
+ CompactSketch cs2 = new WrappedCompactSketch(bytes);
+ assertEquals(cs1.getRetainedEntries(), cs2.getRetainedEntries());
+ HashIterator it1 = cs1.iterator();
+ HashIterator it2 = cs2.iterator();
+ while (it1.next() && it2.next()) {
+ assertEquals(it2.get(), it2.get());
+ }
+ }
+
+ @Test
+ public void serializeWrapBytesV4() {
+ UpdateSketch sk = Sketches.updateSketchBuilder().build();
+ for (int i = 0; i < 10000; i++) {
+ sk.update(i);
+ }
+ CompactSketch cs1 = sk.compact();
+ byte[] bytes = cs1.toByteArrayCompressed();
+ CompactSketch cs2 = new WrappedCompactCompressedSketch(bytes);
+ assertEquals(cs1.getRetainedEntries(), cs2.getRetainedEntries());
+ HashIterator it1 = cs1.iterator();
+ HashIterator it2 = cs2.iterator();
+ while (it1.next() && it2.next()) {
+ assertEquals(it2.get(), it2.get());
+ }
+ }
+
private static class State {
String classType = null;
int count = 0;
From 8b13d168e917b47db13143cda669c80dd2928047 Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Tue, 4 Feb 2025 18:25:44 -0800
Subject: [PATCH 65/88] test toByteArray()
---
.../datasketches/theta/CompactSketchTest.java | 26 ++++++++++---------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
index 0b49f2389..05a0e8eb5 100644
--- a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
+++ b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
@@ -589,36 +589,38 @@ public void serializeDeserializeDirectV4() {
@Test
public void serializeWrapBytesV3() {
- UpdateSketch sk = Sketches.updateSketchBuilder().build();
+ final UpdateSketch sk = Sketches.updateSketchBuilder().build();
for (int i = 0; i < 10000; i++) {
sk.update(i);
}
- CompactSketch cs1 = sk.compact();
- byte[] bytes = cs1.toByteArray();
- CompactSketch cs2 = new WrappedCompactSketch(bytes);
+ final CompactSketch cs1 = sk.compact();
+ final byte[] bytes = cs1.toByteArray();
+ final CompactSketch cs2 = new WrappedCompactSketch(bytes);
assertEquals(cs1.getRetainedEntries(), cs2.getRetainedEntries());
- HashIterator it1 = cs1.iterator();
- HashIterator it2 = cs2.iterator();
+ final HashIterator it1 = cs1.iterator();
+ final HashIterator it2 = cs2.iterator();
while (it1.next() && it2.next()) {
assertEquals(it2.get(), it2.get());
}
+ assertEquals(bytes, cs2.toByteArray());
}
@Test
public void serializeWrapBytesV4() {
- UpdateSketch sk = Sketches.updateSketchBuilder().build();
+ final UpdateSketch sk = Sketches.updateSketchBuilder().build();
for (int i = 0; i < 10000; i++) {
sk.update(i);
}
- CompactSketch cs1 = sk.compact();
- byte[] bytes = cs1.toByteArrayCompressed();
- CompactSketch cs2 = new WrappedCompactCompressedSketch(bytes);
+ final CompactSketch cs1 = sk.compact();
+ final byte[] bytes = cs1.toByteArrayCompressed();
+ final CompactSketch cs2 = new WrappedCompactCompressedSketch(bytes);
assertEquals(cs1.getRetainedEntries(), cs2.getRetainedEntries());
- HashIterator it1 = cs1.iterator();
- HashIterator it2 = cs2.iterator();
+ final HashIterator it1 = cs1.iterator();
+ final HashIterator it2 = cs2.iterator();
while (it1.next() && it2.next()) {
assertEquals(it2.get(), it2.get());
}
+ assertEquals(bytes, cs2.toByteArray());
}
private static class State {
From 7596110166bac05017f406e9800ecd375bacfc5d Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 6 Feb 2025 14:03:04 -0800
Subject: [PATCH 66/88] Fix misc SuppressWarnings
---
.../org/apache/datasketches/quantilescommon/QuantilesAPI.java | 2 +-
.../datasketches/thetacommon/SetOperationCornerCases.java | 2 +-
.../org/apache/datasketches/tuple/SerializerDeserializer.java | 1 -
3 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/quantilescommon/QuantilesAPI.java b/src/main/java/org/apache/datasketches/quantilescommon/QuantilesAPI.java
index a082fc27a..471ee5570 100644
--- a/src/main/java/org/apache/datasketches/quantilescommon/QuantilesAPI.java
+++ b/src/main/java/org/apache/datasketches/quantilescommon/QuantilesAPI.java
@@ -202,7 +202,7 @@
* @author Kevin Lang
* @author Alexander Saydakov
*/
-@SuppressWarnings("javadoc")
+
public interface QuantilesAPI {
/** The sketch must not be empty for this operation. */
diff --git a/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java b/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java
index d9fda48bb..2457b37fe 100644
--- a/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java
+++ b/src/main/java/org/apache/datasketches/thetacommon/SetOperationCornerCases.java
@@ -28,7 +28,7 @@
* Simplifies and speeds up set operations by resolving specific corner cases.
* @author Lee Rhodes
*/
-@SuppressWarnings("javadoc")
+
public class SetOperationCornerCases {
private static final long MAX = Long.MAX_VALUE;
diff --git a/src/main/java/org/apache/datasketches/tuple/SerializerDeserializer.java b/src/main/java/org/apache/datasketches/tuple/SerializerDeserializer.java
index 9b0ca33cb..a30d47edf 100644
--- a/src/main/java/org/apache/datasketches/tuple/SerializerDeserializer.java
+++ b/src/main/java/org/apache/datasketches/tuple/SerializerDeserializer.java
@@ -31,7 +31,6 @@ public final class SerializerDeserializer {
/**
* Defines the sketch classes that this SerializerDeserializer can handle.
*/
- @SuppressWarnings("javadoc")
public static enum SketchType {
/** QuickSelectSketch */
QuickSelectSketch,
From 3034a347162efdb2fb75c18b231cf0c018920bea Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Sat, 8 Feb 2025 20:48:08 -0800
Subject: [PATCH 67/88] Changes to MurmurHash3v3 to *3v4
---
...ash3v3Test.java => MurmurHash3v4Test.java} | 72 +++++++++----------
1 file changed, 36 insertions(+), 36 deletions(-)
rename src/test/java/org/apache/datasketches/hash/{MurmurHash3v3Test.java => MurmurHash3v4Test.java} (83%)
diff --git a/src/test/java/org/apache/datasketches/hash/MurmurHash3v3Test.java b/src/test/java/org/apache/datasketches/hash/MurmurHash3v4Test.java
similarity index 83%
rename from src/test/java/org/apache/datasketches/hash/MurmurHash3v3Test.java
rename to src/test/java/org/apache/datasketches/hash/MurmurHash3v4Test.java
index 8699a091a..6cd4d624f 100644
--- a/src/test/java/org/apache/datasketches/hash/MurmurHash3v3Test.java
+++ b/src/test/java/org/apache/datasketches/hash/MurmurHash3v4Test.java
@@ -28,13 +28,13 @@
import org.testng.annotations.Test;
import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.internal.MurmurHash3v3;
+import org.apache.datasketches.memory.internal.MurmurHash3v4;
import org.apache.datasketches.memory.WritableMemory;
/**
* @author Lee Rhodes
*/
-public class MurmurHash3v3Test {
+public class MurmurHash3v4Test {
private Random rand = new Random();
private static final int trials = 1 << 20;
@@ -154,33 +154,33 @@ private static final long[] hashV1(byte[] key, long seed) {
}
private static final long[] hashV2(long[] key, long seed) {
- return MurmurHash3v3.hash(key, seed);
+ return MurmurHash3v4.hash(key, seed);
}
private static final long[] hashV2(int[] key2, long seed) {
- return MurmurHash3v3.hash(key2, seed);
+ return MurmurHash3v4.hash(key2, seed);
}
private static final long[] hashV2(char[] key, long seed) {
- return MurmurHash3v3.hash(key, seed);
+ return MurmurHash3v4.hash(key, seed);
}
private static final long[] hashV2(byte[] key, long seed) {
- return MurmurHash3v3.hash(key, seed);
+ return MurmurHash3v4.hash(key, seed);
}
//V2 single primitives
private static final long[] hashV2(long key, long seed, long[] out) {
- return MurmurHash3v3.hash(key, seed, out);
+ return MurmurHash3v4.hash(key, seed, out);
}
// private static final long[] hashV2(double key, long seed, long[] out) {
-// return MurmurHash3v3.hash(key, seed, out);
+// return MurmurHash3v4.hash(key, seed, out);
// }
// private static final long[] hashV2(String key, long seed, long[] out) {
-// return MurmurHash3v3.hash(key, seed, out);
+// return MurmurHash3v4.hash(key, seed, out);
// }
@@ -197,9 +197,9 @@ public void offsetChecks() {
WritableMemory wmem = WritableMemory.allocate(cap);
for (int i = 0; i < cap; i++) { wmem.putByte(i, (byte)(-128 + i)); }
- for (int offset = 0; offset < 16; offset++) {
+ for (int offset = 3; offset < 16; offset++) {
int arrLen = cap - offset;
- hash1 = MurmurHash3v3.hash(wmem, offset, arrLen, seed, hash1);
+ hash1 = MurmurHash3v4.hash(wmem, offset, arrLen, seed, hash1);
byte[] byteArr2 = new byte[arrLen];
wmem.getByteArray(offset, byteArr2, 0, arrLen);
hash2 = MurmurHash3.hash(byteArr2, seed);
@@ -222,8 +222,8 @@ public void byteArrChecks() {
for (int i = 0; i < j; i++) { wmem.putByte(i, (byte) (-128 + i)); }
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v3.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v3.hash(in, seed);
+ hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3v4.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -246,8 +246,8 @@ public void charArrChecks() {
for (int i = 0; i < j; i++) { wmem.putInt(i, i); }
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v3.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v3.hash(in, seed);
+ hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3v4.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -270,8 +270,8 @@ public void intArrChecks() {
for (int i = 0; i < j; i++) { wmem.putInt(i, i); }
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v3.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v3.hash(in, seed);
+ hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3v4.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -294,8 +294,8 @@ public void longArrChecks() {
for (int i = 0; i < j; i++) { wmem.putLong(i, i); }
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v3.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v3.hash(in, seed);
+ hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3v4.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -313,8 +313,8 @@ public void longCheck() {
WritableMemory wmem = WritableMemory.writableWrap(in);
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v3.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v3.hash(in, seed);
+ hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3v4.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -325,57 +325,57 @@ public void checkEmptiesNulls() {
long seed = 123;
long[] hashOut = new long[2];
try {
- MurmurHash3v3.hash(Memory.wrap(new long[0]), 0, 0, seed, hashOut); //mem empty
+ MurmurHash3v4.hash(Memory.wrap(new long[0]), 0, 0, seed, hashOut); //mem empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
String s = "";
- MurmurHash3v3.hash(s, seed, hashOut); //string empty
+ MurmurHash3v4.hash(s, seed, hashOut); //string empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
String s = null;
- MurmurHash3v3.hash(s, seed, hashOut); //string null
+ MurmurHash3v4.hash(s, seed, hashOut); //string null
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
byte[] barr = new byte[0];
- MurmurHash3v3.hash(barr, seed); //byte[] empty
+ MurmurHash3v4.hash(barr, seed); //byte[] empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
byte[] barr = null;
- MurmurHash3v3.hash(barr, seed); //byte[] null
+ MurmurHash3v4.hash(barr, seed); //byte[] null
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
char[] carr = new char[0];
- MurmurHash3v3.hash(carr, seed); //char[] empty
+ MurmurHash3v4.hash(carr, seed); //char[] empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
char[] carr = null;
- MurmurHash3v3.hash(carr, seed); //char[] null
+ MurmurHash3v4.hash(carr, seed); //char[] null
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
int[] iarr = new int[0];
- MurmurHash3v3.hash(iarr, seed); //int[] empty
+ MurmurHash3v4.hash(iarr, seed); //int[] empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
int[] iarr = null;
- MurmurHash3v3.hash(iarr, seed); //int[] null
+ MurmurHash3v4.hash(iarr, seed); //int[] null
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
long[] larr = new long[0];
- MurmurHash3v3.hash(larr, seed); //long[] empty
+ MurmurHash3v4.hash(larr, seed); //long[] empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
long[] larr = null;
- MurmurHash3v3.hash(larr, seed); //long[] null
+ MurmurHash3v4.hash(larr, seed); //long[] null
fail();
} catch (final IllegalArgumentException e) { } //OK
}
@@ -385,9 +385,9 @@ public void checkStringLong() {
long seed = 123;
long[] hashOut = new long[2];
String s = "123";
- assertTrue(MurmurHash3v3.hash(s, seed, hashOut)[0] != 0);
+ assertTrue(MurmurHash3v4.hash(s, seed, hashOut)[0] != 0);
long v = 123;
- assertTrue(MurmurHash3v3.hash(v, seed, hashOut)[0] != 0);
+ assertTrue(MurmurHash3v4.hash(v, seed, hashOut)[0] != 0);
}
@Test
@@ -415,8 +415,8 @@ private static long[] checkDouble(double dbl) {
WritableMemory wmem = WritableMemory.writableWrap(dataArr);
long[] hash1 = MurmurHash3.hash(dataArr, 0);
- hash2 = MurmurHash3v3.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v3.hash(dbl, seed, hash2);
+ hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3v4.hash(dbl, seed, hash2);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
From ecfb4387b7164a1dc1da2495f902692d6589204e Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Sat, 8 Feb 2025 20:49:35 -0800
Subject: [PATCH 68/88] temporary change pom to 6.1.0-SNAPSHOT
---
pom.xml | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/pom.xml b/pom.xml
index c72af4f39..1d829adc4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,7 @@ under the License.
org.apache.datasketches
datasketches-java
- 7.1.0-SNAPSHOT
+ 8.0.0-SNAPSHOT
jar
${project.artifactId}
@@ -83,7 +83,7 @@ under the License.
- 4.1.0
+ 6.1.0-SNAPSHOT
7.10.2
@@ -94,11 +94,11 @@ under the License.
3.6.3
- 17
- --add-modules=jdk.incubator.foreign
+ 21
+ --enable-preview
${java.version}
${java.version}
- -Xmx4g -Duser.language=en -Duser.country=US -Dfile.encoding=UTF-8 ${add-modules}
+ -Xmx4g -Duser.language=en -Duser.country=US -Dfile.encoding=UTF-8 ${jvm-ffm-flag}
UTF-8
${charset.encoding}
${charset.encoding}
@@ -164,7 +164,7 @@ under the License.
${maven-compiler-plugin.version}
- ${add-modules}
+ ${jvm-ffm-flag}
@@ -238,7 +238,7 @@ under the License.
true
public
- ${add-modules}
+ ${jvm-ffm-flag}
@@ -284,7 +284,7 @@ under the License.
maven-surefire-plugin
${maven-surefire-failsafe-plugins.version}
- ${add-modules}
+ ${jvm-ffm-flag}
false
false
true
From f33813370ed9c5c0a171a95190e0f7cfc0f6f56d Mon Sep 17 00:00:00 2001
From: AlexanderSaydakov
Date: Wed, 12 Feb 2025 18:19:00 -0800
Subject: [PATCH 69/88] union(mem) delegates to union(sketch)
---
.../apache/datasketches/theta/UnionImpl.java | 106 +-----------------
1 file changed, 2 insertions(+), 104 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/theta/UnionImpl.java b/src/main/java/org/apache/datasketches/theta/UnionImpl.java
index d5ae6071a..8c5b2f8f0 100644
--- a/src/main/java/org/apache/datasketches/theta/UnionImpl.java
+++ b/src/main/java/org/apache/datasketches/theta/UnionImpl.java
@@ -20,28 +20,17 @@
package org.apache.datasketches.theta;
import static java.lang.Math.min;
-import static org.apache.datasketches.theta.PreambleUtil.COMPACT_FLAG_MASK;
-import static org.apache.datasketches.theta.PreambleUtil.ORDERED_FLAG_MASK;
import static org.apache.datasketches.theta.PreambleUtil.UNION_THETA_LONG;
import static org.apache.datasketches.theta.PreambleUtil.clearEmpty;
-import static org.apache.datasketches.theta.PreambleUtil.extractCurCount;
import static org.apache.datasketches.theta.PreambleUtil.extractFamilyID;
-import static org.apache.datasketches.theta.PreambleUtil.extractFlags;
-import static org.apache.datasketches.theta.PreambleUtil.extractLgArrLongs;
-import static org.apache.datasketches.theta.PreambleUtil.extractPreLongs;
-import static org.apache.datasketches.theta.PreambleUtil.extractSeedHash;
-import static org.apache.datasketches.theta.PreambleUtil.extractSerVer;
-import static org.apache.datasketches.theta.PreambleUtil.extractThetaLong;
import static org.apache.datasketches.theta.PreambleUtil.extractUnionThetaLong;
import static org.apache.datasketches.theta.PreambleUtil.insertUnionThetaLong;
-import static org.apache.datasketches.theta.SingleItemSketch.otherCheckForSingleItem;
import static org.apache.datasketches.thetacommon.QuickSelect.selectExcludingZeros;
import java.nio.ByteBuffer;
import org.apache.datasketches.common.Family;
import org.apache.datasketches.common.ResizeFactor;
-import org.apache.datasketches.common.SketchesArgumentException;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.MemoryRequestServer;
import org.apache.datasketches.memory.WritableMemory;
@@ -347,99 +336,8 @@ public void union(final Sketch sketchIn) {
@Override
public void union(final Memory skMem) {
- if (skMem == null) { return; }
- final int cap = (int) skMem.getCapacity();
- if (cap < 16) { return; } //empty or garbage
- final int serVer = extractSerVer(skMem);
- final int fam = extractFamilyID(skMem);
-
- if (serVer == 4) { // compressed ordered compact
- ThetaUtil.checkSeedHashes(expectedSeedHash_, (short) extractSeedHash(skMem));
- union(CompactSketch.wrap(skMem));
- return;
- }
- if (serVer == 3) { //The OpenSource sketches (Aug 4, 2015) starts with serVer = 3
- if (fam < 1 || fam > 3) {
- throw new SketchesArgumentException(
- "Family must be Alpha, QuickSelect, or Compact: " + Family.idToFamily(fam));
- }
- processVer3(skMem);
- return;
- }
- if (serVer == 2) { //older Sketch, which is compact and ordered
- ThetaUtil.checkSeedHashes(expectedSeedHash_, (short)extractSeedHash(skMem));
- union(ForwardCompatibility.heapify2to3(skMem, expectedSeedHash_));
- return;
- }
- if (serVer == 1) { //much older Sketch, which is compact and ordered, no seedHash
- union(ForwardCompatibility.heapify1to3(skMem, expectedSeedHash_));
- return;
- }
- throw new SketchesArgumentException("SerVer is unknown: " + serVer);
- }
-
- //Has seedHash, p, could have 0 entries & theta < 1.0,
- //could be unordered, ordered, compact, or not compact,
- //could be Alpha, QuickSelect, or Compact.
- private void processVer3(final Memory skMem) {
- final int preLongs = extractPreLongs(skMem);
-
- if (preLongs == 1) {
- if (otherCheckForSingleItem(skMem)) {
- final long hash = skMem.getLong(8);
- gadget_.hashUpdate(hash);
- return;
- }
- return; //empty
- }
- ThetaUtil.checkSeedHashes(expectedSeedHash_, (short)extractSeedHash(skMem));
- final int curCountIn;
- final long thetaLongIn;
-
- if (preLongs == 2) { //exact mode
- curCountIn = extractCurCount(skMem);
- if (curCountIn == 0) { return; } //should be > 0, but if it is 0 return empty anyway.
- thetaLongIn = Long.MAX_VALUE;
- }
-
- else { //prelongs == 3
- //curCount may be 0 (e.g., from intersection); but sketch cannot be empty.
- curCountIn = extractCurCount(skMem);
- thetaLongIn = extractThetaLong(skMem);
- }
-
- unionThetaLong_ = min(min(unionThetaLong_, thetaLongIn), gadget_.getThetaLong()); //theta rule
- unionEmpty_ = false;
- final int flags = extractFlags(skMem);
- final boolean ordered = (flags & ORDERED_FLAG_MASK) != 0;
- if (ordered) { //must be compact
-
- for (int i = 0; i < curCountIn; i++ ) {
- final int offsetBytes = preLongs + i << 3;
- final long hashIn = skMem.getLong(offsetBytes);
- if (hashIn >= unionThetaLong_) { break; } // "early stop"
- gadget_.hashUpdate(hashIn); //backdoor update, hash function is bypassed
- }
- }
-
- else { //not-ordered, could be compact or hash-table form
- final boolean compact = (flags & COMPACT_FLAG_MASK) != 0;
- final int size = compact ? curCountIn : 1 << extractLgArrLongs(skMem);
-
- for (int i = 0; i < size; i++ ) {
- final int offsetBytes = preLongs + i << 3;
- final long hashIn = skMem.getLong(offsetBytes);
- if (hashIn <= 0L || hashIn >= unionThetaLong_) { continue; }
- gadget_.hashUpdate(hashIn); //backdoor update, hash function is bypassed
- }
- }
-
- unionThetaLong_ = min(unionThetaLong_, gadget_.getThetaLong()); //sync thetaLongs
-
- if (gadget_.hasMemory()) {
- final WritableMemory wmem = (WritableMemory)gadget_.getMemory();
- PreambleUtil.insertUnionThetaLong(wmem, unionThetaLong_);
- PreambleUtil.clearEmpty(wmem);
+ if (skMem != null) {
+ union(Sketch.wrap(skMem));
}
}
From 82b155fa907e786889a7697fea22512053c33214 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Mon, 17 Feb 2025 22:30:29 -0800
Subject: [PATCH 70/88] This is the first crack at updating ds-java to Java 21.
Lots of changes.
---
.../datasketches/hash/MurmurHash3Adaptor.java | 479 ------------------
.../datasketches/hash/MurmurHash3FFM21.java | 386 ++++++++++++++
.../datasketches/hll/DirectAuxHashMap.java | 2 +-
.../datasketches/kll/KllDoublesHelper.java | 7 +-
.../datasketches/kll/KllDoublesSketch.java | 2 +-
.../datasketches/kll/KllFloatsHelper.java | 7 +-
.../datasketches/kll/KllFloatsSketch.java | 2 +-
.../apache/datasketches/kll/KllHelper.java | 14 +-
.../datasketches/kll/KllLongsHelper.java | 7 +-
.../datasketches/kll/KllLongsSketch.java | 2 +-
.../quantiles/DirectUpdateDoublesSketch.java | 3 +-
.../quantiles/DirectUpdateDoublesSketchR.java | 2 +-
.../datasketches/quantiles/DoublesSketch.java | 4 +-
.../ConcurrentDirectQuickSelectSketch.java | 4 +-
.../ConcurrentHeapQuickSelectSketch.java | 4 +-
.../theta/DirectQuickSelectSketch.java | 4 +-
.../filters/bloomfilter/BloomFilterTest.java | 26 +-
.../hash/MurmurHash3AdaptorTest.java | 377 --------------
...3v4Test.java => MurmurHash3FFM21Test.java} | 69 ++-
.../hash/MurmurHash3FFM21bTest.java | 419 +++++++++++++++
.../hll/DirectAuxHashMapTest.java | 11 +-
.../hll/DirectCouponListTest.java | 8 +-
.../datasketches/kll/KllItemsSketchTest.java | 13 +-
.../quantiles/DebugUnionTest.java | 7 +-
.../DirectQuantilesMemoryRequestTest.java | 32 +-
.../quantiles/DoublesSketchTest.java | 12 +-
.../quantiles/PreambleUtilTest.java | 11 +-
.../datasketches/theta/CompactSketchTest.java | 6 +-
.../theta/DirectQuickSelectSketchTest.java | 104 ++--
.../theta/HeapifyWrapSerVer1and2Test.java | 106 ++--
.../datasketches/theta/SetOperationTest.java | 10 +-
.../datasketches/theta/UnionImplTest.java | 19 +-
32 files changed, 1068 insertions(+), 1091 deletions(-)
delete mode 100644 src/main/java/org/apache/datasketches/hash/MurmurHash3Adaptor.java
create mode 100644 src/main/java/org/apache/datasketches/hash/MurmurHash3FFM21.java
delete mode 100644 src/test/java/org/apache/datasketches/hash/MurmurHash3AdaptorTest.java
rename src/test/java/org/apache/datasketches/hash/{MurmurHash3v4Test.java => MurmurHash3FFM21Test.java} (83%)
create mode 100644 src/test/java/org/apache/datasketches/hash/MurmurHash3FFM21bTest.java
diff --git a/src/main/java/org/apache/datasketches/hash/MurmurHash3Adaptor.java b/src/main/java/org/apache/datasketches/hash/MurmurHash3Adaptor.java
deleted file mode 100644
index feecdba97..000000000
--- a/src/main/java/org/apache/datasketches/hash/MurmurHash3Adaptor.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.datasketches.hash;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.datasketches.common.Util.ceilingPowerOf2;
-import static org.apache.datasketches.hash.MurmurHash3.hash;
-
-import java.nio.ByteBuffer;
-
-import org.apache.datasketches.common.SketchesArgumentException;
-import org.apache.datasketches.common.SketchesStateException;
-
-/**
- * A general purpose wrapper for the MurmurHash3.
- *
- * - Inputs can be long, long[], int[], char[], byte[], double or String.
- * - Returns null if arrays or String is null or empty.
- * - Provides methods for returning the 128-bit result as either an array of 2 longs or as a byte
- * array of 16 bytes.
- * - Provides modulo, asDouble and asInt functions.
- *
- *
- * @author Lee Rhodes
- */
-public final class MurmurHash3Adaptor {
- private static final long BIT62 = 1L << 62;
- private static final long MAX_LONG = Long.MAX_VALUE;
- private static final long INT_MASK = 0x7FFFFFFFL;
- private static final long PRIME = 9219741426499971445L; //from P. L'Ecuyer and R. Simard
-
- private MurmurHash3Adaptor() {}
-
- /**
- * Hash a long and long seed.
- *
- * @param datum the input long value
- * @param seed A long valued seed.
- * @return The 128-bit hash as a byte[16] in Big Endian order from 2 64-bit longs.
- */
- public static byte[] hashToBytes(final long datum, final long seed) {
- final long[] data = { datum };
- return toByteArray(hash(data, seed));
- }
-
- /**
- * Hash a long[] and long seed.
- *
- * @param data the input long array
- * @param seed A long valued seed.
- * @return The 128-bit hash as a byte[16] in Big Endian order from 2 64-bit longs.
- */
- public static byte[] hashToBytes(final long[] data, final long seed) {
- if ((data == null) || (data.length == 0)) {
- return null;
- }
- return toByteArray(hash(data, seed));
- }
-
- /**
- * Hash an int[] and long seed.
- *
- * @param data the input int array
- * @param seed A long valued seed.
- * @return The 128-bit hash as a byte[16] in Big Endian order from 2 64-bit longs.
- */
- public static byte[] hashToBytes(final int[] data, final long seed) {
- if ((data == null) || (data.length == 0)) {
- return null;
- }
- return toByteArray(hash(data, seed));
- }
-
- /**
- * Hash a char[] and long seed.
- *
- * @param data the input char array
- * @param seed A long valued seed.
- * @return The 128-bit hash as a byte[16] in Big Endian order from 2 64-bit longs.
- */
- public static byte[] hashToBytes(final char[] data, final long seed) {
- if ((data == null) || (data.length == 0)) {
- return null;
- }
- return toByteArray(hash(data, seed));
- }
-
- /**
- * Hash a byte[] and long seed.
- *
- * @param data the input byte array
- * @param seed A long valued seed.
- * @return The 128-bit hash as a byte[16] in Big Endian order from 2 64-bit longs.
- */
- public static byte[] hashToBytes(final byte[] data, final long seed) {
- if ((data == null) || (data.length == 0)) {
- return null;
- }
- return toByteArray(hash(data, seed));
- }
-
- /**
- * Hash a double and long seed.
- *
- * @param datum the input double
- * @param seed A long valued seed.
- * @return The 128-bit hash as a byte[16] in Big Endian order from 2 64-bit longs.
- */
- public static byte[] hashToBytes(final double datum, final long seed) {
- final double d = (datum == 0.0) ? 0.0 : datum; //canonicalize -0.0, 0.0
- final long[] data = { Double.doubleToLongBits(d) }; //canonicalize all NaN forms
- return toByteArray(hash(data, seed));
- }
-
- /**
- * Hash a String and long seed.
- *
- * @param datum the input String
- * @param seed A long valued seed.
- * @return The 128-bit hash as a byte[16] in Big Endian order from 2 64-bit longs.
- */
- public static byte[] hashToBytes(final String datum, final long seed) {
- if ((datum == null) || datum.isEmpty()) {
- return null;
- }
- final byte[] data = datum.getBytes(UTF_8);
- return toByteArray(hash(data, seed));
- }
-
- /**
- * Hash a long and long seed.
- *
- * @param datum the input long
- * @param seed A long valued seed.
- * @return The 128-bit hash as a long[2].
- */
- public static long[] hashToLongs(final long datum, final long seed) {
- final long[] data = { datum };
- return hash(data, seed);
- }
-
- /**
- * Hash a long[] and long seed.
- *
- * @param data the input long array.
- * @param seed A long valued seed.
- * @return The 128-bit hash as a long[2].
- */
- public static long[] hashToLongs(final long[] data, final long seed) {
- if ((data == null) || (data.length == 0)) {
- return null;
- }
- return hash(data, seed);
- }
-
- /**
- * Hash a int[] and long seed.
- *
- * @param data the input int array.
- * @param seed A long valued seed.
- * @return The 128-bit hash as a long[2].
- */
- public static long[] hashToLongs(final int[] data, final long seed) {
- if ((data == null) || (data.length == 0)) {
- return null;
- }
- return hash(data, seed);
- }
-
- /**
- * Hash a char[] and long seed.
- *
- * @param data the input char array.
- * @param seed A long valued seed.
- * @return The 128-bit hash as a long[2].
- */
- public static long[] hashToLongs(final char[] data, final long seed) {
- if ((data == null) || (data.length == 0)) {
- return null;
- }
- return hash(data, seed);
- }
-
- /**
- * Hash a byte[] and long seed.
- *
- * @param data the input byte array.
- * @param seed A long valued seed.
- * @return The 128-bit hash as a long[2].
- */
- public static long[] hashToLongs(final byte[] data, final long seed) {
- if ((data == null) || (data.length == 0)) {
- return null;
- }
- return hash(data, seed);
- }
-
- /**
- * Hash a double and long seed.
- *
- * @param datum the input double.
- * @param seed A long valued seed.
- * @return The 128-bit hash as a long[2].
- */
- public static long[] hashToLongs(final double datum, final long seed) {
- final double d = (datum == 0.0) ? 0.0 : datum; //canonicalize -0.0, 0.0
- final long[] data = { Double.doubleToLongBits(d) };//canonicalize all NaN forms
- return hash(data, seed);
- }
-
- /**
- * Hash a String and long seed.
- *
- * @param datum the input String.
- * @param seed A long valued seed.
- * @return The 128-bit hash as a long[2].
- */
- public static long[] hashToLongs(final String datum, final long seed) {
- if ((datum == null) || datum.isEmpty()) {
- return null;
- }
- final byte[] data = datum.getBytes(UTF_8);
- return hash(data, seed);
- }
-
- //As Integer functions
-
- /**
- * Returns a deterministic uniform random integer between zero (inclusive) and
- * n (exclusive) given the input data.
- * @param data the input long array.
- * @param n The upper exclusive bound of the integers produced. Must be > 1.
- * @return deterministic uniform random integer
- */
- public static int asInt(final long[] data, final int n) {
- if ((data == null) || (data.length == 0)) {
- throw new SketchesArgumentException("Input is null or empty.");
- }
- return asInteger(data, n); //data is long[]
- }
-
- /**
- * Returns a deterministic uniform random integer between zero (inclusive) and
- * n (exclusive) given the input data.
- * @param data the input int array.
- * @param n The upper exclusive bound of the integers produced. Must be > 1.
- * @return deterministic uniform random integer
- */
- public static int asInt(final int[] data, final int n) {
- if ((data == null) || (data.length == 0)) {
- throw new SketchesArgumentException("Input is null or empty.");
- }
- return asInteger(toLongArray(data), n); //data is int[]
- }
-
- /**
- * Returns a deterministic uniform random integer between zero (inclusive) and
- * n (exclusive) given the input data.
- * @param data the input byte array.
- * @param n The upper exclusive bound of the integers produced. Must be > 1.
- * @return deterministic uniform random integer.
- */
- public static int asInt(final byte[] data, final int n) {
- if ((data == null) || (data.length == 0)) {
- throw new SketchesArgumentException("Input is null or empty.");
- }
- return asInteger(toLongArray(data), n); //data is byte[]
- }
-
- /**
- * Returns a deterministic uniform random integer between zero (inclusive) and
- * n (exclusive) given the input datum.
- * @param datum the input long
- * @param n The upper exclusive bound of the integers produced. Must be > 1.
- * @return deterministic uniform random integer
- */
- public static int asInt(final long datum, final int n) {
- final long[] data = { datum };
- return asInteger(data, n); //data is long[]
- }
-
- /**
- * Returns a deterministic uniform random integer between zero (inclusive) and
- * n (exclusive) given the input double.
- * @param datum the given double.
- * @param n The upper exclusive bound of the integers produced. Must be > 1.
- * @return deterministic uniform random integer
- */
- public static int asInt(final double datum, final int n) {
- final double d = (datum == 0.0) ? 0.0 : datum; //canonicalize -0.0, 0.0
- final long[] data = { Double.doubleToLongBits(d) };//canonicalize all NaN forms
- return asInteger(data, n); //data is long[]
- }
-
- /**
- * Returns a deterministic uniform random integer between zero (inclusive) and
- * n (exclusive) given the input datum.
- * @param datum the given String.
- * @param n The upper exclusive bound of the integers produced. Must be > 1.
- * @return deterministic uniform random integer
- */
- public static int asInt(final String datum, final int n) {
- if ((datum == null) || datum.isEmpty()) {
- throw new SketchesArgumentException("Input is null or empty.");
- }
- final byte[] data = datum.getBytes(UTF_8);
- return asInteger(toLongArray(data), n); //data is byte[]
- }
-
- /**
- * Returns a deterministic uniform random integer with a minimum inclusive value of zero and a
- * maximum exclusive value of n given the input data.
- *
- * The integer values produced are only as random as the MurmurHash3 algorithm, which may be
- * adequate for many applications. However, if you are looking for high guarantees of randomness
- * you should turn to more sophisticated random generators such as Mersenne Twister or Well19937c
- * algorithms.
- *
- * @param data The input data (key)
- * @param n The upper exclusive bound of the integers produced. Must be > 1.
- * @return deterministic uniform random integer
- */
- private static int asInteger(final long[] data, final int n) {
- int t;
- int cnt = 0;
- long seed = 0;
- if (n < 2) {
- throw new SketchesArgumentException("Given value of n must be > 1.");
- }
- if (n > (1 << 30)) {
- while (++cnt < 10000) {
- final long[] h = MurmurHash3.hash(data, seed);
- t = (int) (h[0] & INT_MASK);
- if (t < n) {
- return t;
- }
- t = (int) ((h[0] >>> 33));
- if (t < n) {
- return t;
- }
- t = (int) (h[1] & INT_MASK);
- if (t < n) {
- return t;
- }
- t = (int) ((h[1] >>> 33));
- if (t < n) {
- return t;
- }
- seed += PRIME;
- } // end while
- throw new SketchesStateException(
- "Internal Error: Failed to find integer < n within 10000 iterations.");
- }
- final long mask = ceilingPowerOf2(n) - 1;
- while (++cnt < 10000) {
- final long[] h = MurmurHash3.hash(data, seed);
- t = (int) (h[0] & mask);
- if (t < n) {
- return t;
- }
- t = (int) ((h[0] >>> 33) & mask);
- if (t < n) {
- return t;
- }
- t = (int) (h[1] & mask);
- if (t < n) {
- return t;
- }
- t = (int) ((h[1] >>> 33) & mask);
- if (t < n) {
- return t;
- }
- seed += PRIME;
- } // end while
- throw new SketchesStateException(
- "Internal Error: Failed to find integer < n within 10000 iterations.");
- }
-
- /**
- * Returns a uniform random double with a minimum inclusive value of zero and a maximum exclusive
- * value of 1.0.
- *
- *
The double values produced are only as random as the MurmurHash3 algorithm, which may be
- * adequate for many applications. However, if you are looking for high guarantees of randomness
- * you should turn to more sophisticated random generators such as Mersenne Twister or Well
- * algorithms.
- *
- * @param hash The output of the MurmurHash3.
- * @return the uniform random double.
- */
- public static double asDouble(final long[] hash) {
- return (hash[0] >>> 12) * 0x1.0p-52d;
- }
-
- /**
- * Returns the remainder from the modulo division of the 128-bit output of the murmurHash3 by the
- * divisor.
- *
- * @param h0 The lower 64-bits of the 128-bit MurmurHash3 hash.
- * @param h1 The upper 64-bits of the 128-bit MurmurHash3 hash.
- * @param divisor Must be positive and greater than zero.
- * @return the modulo result.
- */
- public static int modulo(final long h0, final long h1, final int divisor) {
- final long d = divisor;
- final long modH0 = (h0 < 0L) ? addRule(mulRule(BIT62, 2L, d), (h0 & MAX_LONG), d) : h0 % d;
- final long modH1 = (h1 < 0L) ? addRule(mulRule(BIT62, 2L, d), (h1 & MAX_LONG), d) : h1 % d;
- final long modTop = mulRule(mulRule(BIT62, 4L, d), modH1, d);
- return (int) addRule(modTop, modH0, d);
- }
-
- /**
- * Returns the remainder from the modulo division of the 128-bit output of the murmurHash3 by the
- * divisor.
- *
- * @param hash The size 2 long array from the MurmurHash3.
- * @param divisor Must be positive and greater than zero.
- * @return the modulo result
- */
- public static int modulo(final long[] hash, final int divisor) {
- return modulo(hash[0], hash[1], divisor);
- }
-
- private static long addRule(final long a, final long b, final long d) {
- return ((a % d) + (b % d)) % d;
- }
-
- private static long mulRule(final long a, final long b, final long d) {
- return ((a % d) * (b % d)) % d;
- }
-
- private static byte[] toByteArray(final long[] hash) { //Assumes Big Endian
- final byte[] bArr = new byte[16];
- final ByteBuffer bb = ByteBuffer.wrap(bArr);
- bb.putLong(hash[0]);
- bb.putLong(hash[1]);
- return bArr;
- }
-
- private static long[] toLongArray(final byte[] data) {
- final int dataLen = data.length;
- final int longLen = (dataLen + 7) / 8;
- final long[] longArr = new long[longLen];
- for (int bi = 0; bi < dataLen; bi++) {
- final int li = bi / 8;
- longArr[li] |= (((long)data[bi]) << ((bi * 8) % 64));
- }
- return longArr;
- }
-
- private static long[] toLongArray(final int[] data) {
- final int dataLen = data.length;
- final int longLen = (dataLen + 1) / 2;
- final long[] longArr = new long[longLen];
- for (int ii = 0; ii < dataLen; ii++) {
- final int li = ii / 2;
- longArr[li] |= (((long)data[ii]) << ((ii * 32) % 64));
- }
- return longArr;
- }
-
-}
diff --git a/src/main/java/org/apache/datasketches/hash/MurmurHash3FFM21.java b/src/main/java/org/apache/datasketches/hash/MurmurHash3FFM21.java
new file mode 100644
index 000000000..a94fd3fd9
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/hash/MurmurHash3FFM21.java
@@ -0,0 +1,386 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.hash;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.ValueLayout;
+import java.util.Objects;
+
+import org.apache.datasketches.memory.Memory;
+
+/**
+ * The MurmurHash3 is a fast, non-cryptographic, 128-bit hash function that has
+ * excellent avalanche and 2-way bit independence properties.
+ *
+ *
Austin Appleby's C++
+ *
+ * MurmurHash3_x64_128(...), final revision 150,
+ * which is in the Public Domain, was the inspiration for this implementation in Java.
+ *
+ * This implementation of the MurmurHash3 allows hashing of a block of on-heap Memory defined by an offset
+ * and length. The calling API also allows the user to supply the small output array of two longs,
+ * so that the entire hash function is static and free of object allocations.
+ *
+ * This implementation produces exactly the same hash result as the
+ * MurmurHash3 function in datasketches-java given compatible inputs.
+ *
+ * This FFM21 version of the implementation leverages the java.lang.foreign package (FFM) of JDK-21 in place of
+ * the Unsafe class.
+ *
+ * @author Lee Rhodes
+ */
+public final class MurmurHash3FFM21 {
+ private static final long C1 = 0x87c37b91114253d5L;
+ private static final long C2 = 0x4cf5ad432745937fL;
+
+ /**
+ * Returns a 128-bit hash of the input.
+ * Provided for compatibility with older version of MurmurHash3,
+ * but empty or null input now throws IllegalArgumentException.
+ * @param in long array
+ * @param seed A long valued seed.
+ * @return the hash
+ * @throws IllegalArgumentException if input is empty or null
+ */
+ public static long[] hash(final long[] in, final long seed) {
+ if ((in == null) || (in.length == 0)) {
+ throw new IllegalArgumentException("Input in is empty or null.");
+ }
+ return hash(MemorySegment.ofArray(in), 0L, in.length << 3, seed, new long[2]);
+ }
+
+ /**
+ * Returns a 128-bit hash of the input.
+ * Provided for compatibility with older version of MurmurHash3,
+ * but empty or null input now throws IllegalArgumentException.
+ * @param in int array
+ * @param seed A long valued seed.
+ * @return the hash
+ * @throws IllegalArgumentException if input is empty or null
+ */
+ public static long[] hash(final int[] in, final long seed) {
+ if ((in == null) || (in.length == 0)) {
+ throw new IllegalArgumentException("Input in is empty or null.");
+ }
+ return hash(MemorySegment.ofArray(in), 0L, in.length << 2, seed, new long[2]);
+ }
+
+ /**
+ * Returns a 128-bit hash of the input.
+ * Provided for compatibility with older version of MurmurHash3,
+ * but empty or null input now throws IllegalArgumentException.
+ * @param in char array
+ * @param seed A long valued seed.
+ * @return the hash
+ * @throws IllegalArgumentException if input is empty or null
+ */
+ public static long[] hash(final char[] in, final long seed) {
+ if ((in == null) || (in.length == 0)) {
+ throw new IllegalArgumentException("Input in is empty or null.");
+ }
+ return hash(MemorySegment.ofArray(in), 0L, in.length << 1, seed, new long[2]);
+ }
+
+ /**
+ * Returns a 128-bit hash of the input.
+ * Provided for compatibility with older version of MurmurHash3,
+ * but empty or null input now throws IllegalArgumentException.
+ * @param in byte array
+ * @param seed A long valued seed.
+ * @return the hash
+ * @throws IllegalArgumentException if input is empty or null
+ */
+ public static long[] hash(final byte[] in, final long seed) {
+ if ((in == null) || (in.length == 0)) {
+ throw new IllegalArgumentException("Input in is empty or null.");
+ }
+ return hash(MemorySegment.ofArray(in), 0L, in.length, seed, new long[2]);
+ }
+
+ //Single primitive inputs
+
+ /**
+ * Returns a 128-bit hash of the input.
+ * Note the entropy of the resulting hash cannot be more than 64 bits.
+ * @param in a long
+ * @param seed A long valued seed.
+ * @param hashOut A long array of size 2
+ * @return the hash
+ */
+ public static long[] hash(final long in, final long seed, final long[] hashOut) {
+ final long h1 = seed ^ mixK1(in);
+ final long h2 = seed;
+ return finalMix128(h1, h2, 8, hashOut);
+ }
+
+ /**
+ * Returns a 128-bit hash of the input.
+ * Note the entropy of the resulting hash cannot be more than 64 bits.
+ * @param in a double
+ * @param seed A long valued seed.
+ * @param hashOut A long array of size 2
+ * @return the hash
+ */
+ public static long[] hash(final double in, final long seed, final long[] hashOut) {
+ final double d = (in == 0.0) ? 0.0 : in; // canonicalize -0.0, 0.0
+ final long k1 = Double.doubleToLongBits(d); // canonicalize all NaN forms
+ final long h1 = seed ^ mixK1(k1);
+ final long h2 = seed;
+ return finalMix128(h1, h2, 8, hashOut);
+ }
+
+ /**
+ * Returns a 128-bit hash of the input.
+ * An empty or null input throws IllegalArgumentException.
+ * @param in a String
+ * @param seed A long valued seed.
+ * @param hashOut A long array of size 2
+ * @return the hash
+ * @throws IllegalArgumentException if input is empty or null
+ */
+ public static long[] hash(final String in, final long seed, final long[] hashOut) {
+ if ((in == null) || (in.length() == 0)) {
+ throw new IllegalArgumentException("Input in is empty or null.");
+ }
+ final byte[] byteArr = in.getBytes(UTF_8);
+ return hash(MemorySegment.ofArray(byteArr), 0L, byteArr.length, seed, hashOut);
+ }
+
+ //The main API calls
+
+ /**
+ * Returns a 128-bit hash of the input as a long array of size 2.
+ *
+ * @param mem The input Memory. Must be non-null and non-empty,
+ * otherwise throws IllegalArgumentException.
+ * @param offsetBytes the starting point within Memory.
+ * @param lengthBytes the total number of bytes to be hashed.
+ * @param seed A long valued seed.
+ * @param hashOut the size 2 long array for the resulting 128-bit hash
+ * @return the hash.
+ */
+ public static long[] hash(final Memory mem, final long offsetBytes, final long lengthBytes,
+ final long seed, final long[] hashOut) {
+ Objects.requireNonNull(mem, "Input Memory is null");
+ final MemorySegment seg = mem.getMemorySegment();
+ return hash(seg, offsetBytes, lengthBytes, seed, hashOut);
+ }
+
+ /**
+ * Returns a 128-bit hash of the input as a long array of size 2.
+ *
+ * @param seg The input MemorySegment. Must be non-null and non-empty,
+ * otherwise throws IllegalArgumentException.
+ * @param offsetBytes the starting point within Memory.
+ * @param lengthBytes the total number of bytes to be hashed.
+ * @param seed A long valued seed.
+ * @param hashOut the size 2 long array for the resulting 128-bit hash
+ * @return the hash.
+ * @throws IllegalArgumentException if input MemorySegment is empty
+ */
+ public static long[] hash(final MemorySegment seg, final long offsetBytes, final long lengthBytes,
+ final long seed, final long[] hashOut) {
+ Objects.requireNonNull(seg, "Input MemorySegment is null");
+ if (seg.byteSize() == 0L) { throw new IllegalArgumentException("Input MemorySegment is empty."); }
+
+ long cumOff = offsetBytes;
+
+ long h1 = seed;
+ long h2 = seed;
+ long rem = lengthBytes;
+
+ // Process the 128-bit blocks (the body) into the hash
+ while (rem >= 16L) {
+ final long k1 = seg.get(ValueLayout.JAVA_LONG_UNALIGNED, cumOff); //0, 16, 32, ...
+ final long k2 = seg.get(ValueLayout.JAVA_LONG_UNALIGNED, cumOff + 8); //8, 24, 40, ...
+ cumOff += 16L;
+ rem -= 16L;
+
+ h1 ^= mixK1(k1);
+ h1 = Long.rotateLeft(h1, 27);
+ h1 += h2;
+ h1 = (h1 * 5) + 0x52dce729L;
+
+ h2 ^= mixK2(k2);
+ h2 = Long.rotateLeft(h2, 31);
+ h2 += h1;
+ h2 = (h2 * 5) + 0x38495ab5L;
+ }
+
+ // Get the tail (if any): 1 to 15 bytes
+ if (rem > 0L) {
+ long k1 = 0;
+ long k2 = 0;
+ switch ((int) rem) {
+ case 15: {
+ k2 ^= (seg.get(ValueLayout.JAVA_BYTE, cumOff + 14) & 0xFFL) << 48;
+ }
+ //$FALL-THROUGH$
+ case 14: {
+ k2 ^= (seg.get(ValueLayout.JAVA_SHORT_UNALIGNED, cumOff + 12) & 0xFFFFL) << 32;
+ k2 ^= seg.get(ValueLayout.JAVA_INT_UNALIGNED, cumOff + 8) & 0xFFFFFFFFL;
+ k1 = seg.get(ValueLayout.JAVA_LONG_UNALIGNED, cumOff);
+ break;
+ }
+
+ case 13: {
+ k2 ^= (seg.get(ValueLayout.JAVA_BYTE, cumOff + 12) & 0xFFL) << 32;
+ }
+ //$FALL-THROUGH$
+ case 12: {
+ k2 ^= seg.get(ValueLayout.JAVA_INT_UNALIGNED, cumOff + 8) & 0xFFFFFFFFL;
+ k1 = seg.get(ValueLayout.JAVA_LONG_UNALIGNED, cumOff);
+ break;
+ }
+
+ case 11: {
+ k2 ^= (seg.get(ValueLayout.JAVA_BYTE, cumOff + 10) & 0xFFL) << 16;
+ }
+ //$FALL-THROUGH$
+ case 10: {
+ k2 ^= seg.get(ValueLayout.JAVA_SHORT_UNALIGNED, cumOff + 8) & 0xFFFFL;
+ k1 = seg.get(ValueLayout.JAVA_LONG_UNALIGNED, cumOff);
+ break;
+ }
+
+ case 9: {
+ k2 ^= seg.get(ValueLayout.JAVA_BYTE, cumOff + 8) & 0xFFL;
+ }
+ //$FALL-THROUGH$
+ case 8: {
+ k1 = seg.get(ValueLayout.JAVA_LONG_UNALIGNED, cumOff);
+ break;
+ }
+
+ case 7: {
+ k1 ^= (seg.get(ValueLayout.JAVA_BYTE, cumOff + 6) & 0xFFL) << 48;
+ }
+ //$FALL-THROUGH$
+ case 6: {
+ k1 ^= (seg.get(ValueLayout.JAVA_SHORT_UNALIGNED, cumOff + 4) & 0xFFFFL) << 32;
+ k1 ^= seg.get(ValueLayout.JAVA_INT_UNALIGNED, cumOff) & 0xFFFFFFFFL;
+ break;
+ }
+
+ case 5: {
+ k1 ^= (seg.get(ValueLayout.JAVA_BYTE, cumOff + 4) & 0xFFL) << 32;
+ }
+ //$FALL-THROUGH$
+ case 4: {
+ k1 ^= seg.get(ValueLayout.JAVA_INT_UNALIGNED, cumOff) & 0xFFFFFFFFL;
+ break;
+ }
+
+ case 3: {
+ k1 ^= (seg.get(ValueLayout.JAVA_BYTE, cumOff + 2) & 0xFFL) << 16;
+ }
+ //$FALL-THROUGH$
+ case 2: {
+ k1 ^= seg.get(ValueLayout.JAVA_SHORT_UNALIGNED, cumOff) & 0xFFFFL;
+ break;
+ }
+
+ case 1: {
+ k1 ^= seg.get(ValueLayout.JAVA_BYTE, cumOff) & 0xFFL;
+ break;
+ }
+ default: break; //can't happen
+ }
+
+ h1 ^= mixK1(k1);
+ h2 ^= mixK2(k2);
+ }
+ return finalMix128(h1, h2, lengthBytes, hashOut);
+ }
+
+ //--Helper methods----------------------------------------------------
+
+ /**
+ * Self mix of k1
+ *
+ * @param k1 input argument
+ * @return mix
+ */
+ private static long mixK1(long k1) {
+ k1 *= C1;
+ k1 = Long.rotateLeft(k1, 31);
+ k1 *= C2;
+ return k1;
+ }
+
+ /**
+ * Self mix of k2
+ *
+ * @param k2 input argument
+ * @return mix
+ */
+ private static long mixK2(long k2) {
+ k2 *= C2;
+ k2 = Long.rotateLeft(k2, 33);
+ k2 *= C1;
+ return k2;
+ }
+
+ /**
+ * Final self mix of h*.
+ *
+ * @param h input to final mix
+ * @return mix
+ */
+ private static long finalMix64(long h) {
+ h ^= h >>> 33;
+ h *= 0xff51afd7ed558ccdL;
+ h ^= h >>> 33;
+ h *= 0xc4ceb9fe1a85ec53L;
+ h ^= h >>> 33;
+ return h;
+ }
+
+ /**
+ * Finalization: Add the length into the hash and mix
+ * @param h1 intermediate hash
+ * @param h2 intermediate hash
+ * @param lengthBytes the length in bytes
+ * @param hashOut the output array of 2 longs
+ * @return hashOut
+ */
+ private static long[] finalMix128(long h1, long h2, final long lengthBytes, final long[] hashOut) {
+ h1 ^= lengthBytes;
+ h2 ^= lengthBytes;
+
+ h1 += h2;
+ h2 += h1;
+
+ h1 = finalMix64(h1);
+ h2 = finalMix64(h2);
+
+ h1 += h2;
+ h2 += h1;
+
+ hashOut[0] = h1;
+ hashOut[1] = h2;
+ return hashOut;
+ }
+
+ private MurmurHash3FFM21() { }
+
+}
diff --git a/src/main/java/org/apache/datasketches/hll/DirectAuxHashMap.java b/src/main/java/org/apache/datasketches/hll/DirectAuxHashMap.java
index 98884f5ea..e6c408f35 100644
--- a/src/main/java/org/apache/datasketches/hll/DirectAuxHashMap.java
+++ b/src/main/java/org/apache/datasketches/hll/DirectAuxHashMap.java
@@ -195,7 +195,7 @@ private static final void grow(final DirectHllArray host, final int oldLgAuxArrI
final WritableMemory newWmem = svr.request(host.wmem, requestBytes);
host.wmem.copyTo(0, newWmem, 0, host.auxStart);
newWmem.clear(host.auxStart, newAuxBytes); //clear space for new aux data
- svr.requestClose(host.wmem, newWmem); //old host.wmem is now invalid
+ svr.requestClose(host.wmem); //old host.wmem is now invalid
host.updateMemory(newWmem);
}
//rehash into larger aux array
diff --git a/src/main/java/org/apache/datasketches/kll/KllDoublesHelper.java b/src/main/java/org/apache/datasketches/kll/KllDoublesHelper.java
index acbecdf07..cb5788a75 100644
--- a/src/main/java/org/apache/datasketches/kll/KllDoublesHelper.java
+++ b/src/main/java/org/apache/datasketches/kll/KllDoublesHelper.java
@@ -207,8 +207,11 @@ static void mergeDoubleImpl(final KllDoublesSketch mySketch, final KllDoublesSke
//MEMORY SPACE MANAGEMENT
if (mySketch.getWritableMemory() != null) {
- final WritableMemory wmem =
- KllHelper.memorySpaceMgmt(mySketch, myNewLevelsArr.length, myNewDoubleItemsArr.length);
+ final WritableMemory oldWmem = mySketch.getWritableMemory();
+ final WritableMemory wmem = KllHelper.memorySpaceMgmt(mySketch, myNewLevelsArr.length, myNewDoubleItemsArr.length);
+ if (!wmem.isSameResource(oldWmem)) {
+ mySketch.getMemoryRequestServer().requestClose(oldWmem);
+ }
mySketch.setWritableMemory(wmem);
}
} //end of updating levels above level 0
diff --git a/src/main/java/org/apache/datasketches/kll/KllDoublesSketch.java b/src/main/java/org/apache/datasketches/kll/KllDoublesSketch.java
index fbe9dbb36..01608ca02 100644
--- a/src/main/java/org/apache/datasketches/kll/KllDoublesSketch.java
+++ b/src/main/java/org/apache/datasketches/kll/KllDoublesSketch.java
@@ -137,7 +137,7 @@ public static KllDoublesSketch wrap(final Memory srcMem) {
Objects.requireNonNull(srcMem, "Parameter 'srcMem' must not be null");
final KllMemoryValidate memVal = new KllMemoryValidate(srcMem, DOUBLES_SKETCH, null);
if (memVal.sketchStructure == UPDATABLE) {
- final MemoryRequestServer memReqSvr = new DefaultMemoryRequestServer(); //dummy
+ final MemoryRequestServer memReqSvr = new DefaultMemoryRequestServer();
return new KllDirectDoublesSketch(memVal.sketchStructure, (WritableMemory)srcMem, memReqSvr, memVal);
} else {
return new KllDirectCompactDoublesSketch(memVal.sketchStructure, srcMem, memVal);
diff --git a/src/main/java/org/apache/datasketches/kll/KllFloatsHelper.java b/src/main/java/org/apache/datasketches/kll/KllFloatsHelper.java
index 69045f78c..1796cac4d 100644
--- a/src/main/java/org/apache/datasketches/kll/KllFloatsHelper.java
+++ b/src/main/java/org/apache/datasketches/kll/KllFloatsHelper.java
@@ -207,8 +207,11 @@ static void mergeFloatImpl(final KllFloatsSketch mySketch, final KllFloatsSketch
//MEMORY SPACE MANAGEMENT
if (mySketch.getWritableMemory() != null) {
- final WritableMemory wmem =
- KllHelper.memorySpaceMgmt(mySketch, myNewLevelsArr.length, myNewFloatItemsArr.length);
+ final WritableMemory oldWmem = mySketch.getWritableMemory();
+ final WritableMemory wmem = KllHelper.memorySpaceMgmt(mySketch, myNewLevelsArr.length, myNewFloatItemsArr.length);
+ if (!wmem.isSameResource(oldWmem)) {
+ mySketch.getMemoryRequestServer().requestClose(oldWmem);
+ }
mySketch.setWritableMemory(wmem);
}
} //end of updating levels above level 0
diff --git a/src/main/java/org/apache/datasketches/kll/KllFloatsSketch.java b/src/main/java/org/apache/datasketches/kll/KllFloatsSketch.java
index b993f9998..cf282c872 100644
--- a/src/main/java/org/apache/datasketches/kll/KllFloatsSketch.java
+++ b/src/main/java/org/apache/datasketches/kll/KllFloatsSketch.java
@@ -137,7 +137,7 @@ public static KllFloatsSketch wrap(final Memory srcMem) {
Objects.requireNonNull(srcMem, "Parameter 'srcMem' must not be null");
final KllMemoryValidate memVal = new KllMemoryValidate(srcMem, FLOATS_SKETCH, null);
if (memVal.sketchStructure == UPDATABLE) {
- final MemoryRequestServer memReqSvr = new DefaultMemoryRequestServer(); //dummy
+ final MemoryRequestServer memReqSvr = new DefaultMemoryRequestServer();
return new KllDirectFloatsSketch(memVal.sketchStructure, (WritableMemory)srcMem, memReqSvr, memVal);
} else {
return new KllDirectCompactFloatsSketch(memVal.sketchStructure, srcMem, memVal);
diff --git a/src/main/java/org/apache/datasketches/kll/KllHelper.java b/src/main/java/org/apache/datasketches/kll/KllHelper.java
index 21188255c..8dd729da7 100644
--- a/src/main/java/org/apache/datasketches/kll/KllHelper.java
+++ b/src/main/java/org/apache/datasketches/kll/KllHelper.java
@@ -52,6 +52,7 @@
import org.apache.datasketches.common.SketchesArgumentException;
import org.apache.datasketches.kll.KllSketch.SketchStructure;
import org.apache.datasketches.kll.KllSketch.SketchType;
+import org.apache.datasketches.memory.MemoryRequestServer;
import org.apache.datasketches.memory.WritableBuffer;
import org.apache.datasketches.memory.WritableMemory;
@@ -353,7 +354,8 @@ static WritableMemory memorySpaceMgmt(
final WritableMemory newWmem;
if (requiredSketchBytes > oldWmem.getCapacity()) { //Acquire new WritableMemory
- newWmem = sketch.getMemoryRequestServer().request(oldWmem, requiredSketchBytes);
+ final MemoryRequestServer memReqSvr = sketch.getMemoryRequestServer();
+ newWmem = memReqSvr.request(oldWmem, requiredSketchBytes);
oldWmem.copyTo(0, newWmem, 0, DATA_START_ADR); //copy preamble (first 20 bytes)
}
else { //Expand or contract in current memory
@@ -617,7 +619,7 @@ else if (sketchType == FLOATS_SKETCH) {
maxFloat = fltSk.getMaxItem();
//assert we are following a certain growth scheme
assert myCurFloatItemsArr.length == myCurTotalItemsCapacity;
- }
+ }
else if (sketchType == LONGS_SKETCH) {
final KllLongsSketch lngSk = (KllLongsSketch) sketch;
myCurLongItemsArr = lngSk.getLongItemsArray();
@@ -668,7 +670,7 @@ else if (sketchType == FLOATS_SKETCH) {
myNewFloatItemsArr = new float[myNewTotalItemsCapacity];
// copy and shift the current items data into the new array
System.arraycopy(myCurFloatItemsArr, 0, myNewFloatItemsArr, deltaItemsCap, myCurTotalItemsCapacity);
- }
+ }
else if (sketchType == LONGS_SKETCH) {
myNewLongItemsArr = new long[myNewTotalItemsCapacity];
// copy and shift the current items data into the new array
@@ -682,7 +684,11 @@ else if (sketchType == LONGS_SKETCH) {
//MEMORY SPACE MANAGEMENT
if (sketch.getWritableMemory() != null) {
+ final WritableMemory oldWmem = sketch.getWritableMemory();
final WritableMemory wmem = memorySpaceMgmt(sketch, myNewLevelsArr.length, myNewTotalItemsCapacity);
+ if (!wmem.isSameResource(oldWmem)) {
+ sketch.getMemoryRequestServer().requestClose(oldWmem);
+ }
sketch.setWritableMemory(wmem);
}
@@ -700,7 +706,7 @@ else if (sketchType == FLOATS_SKETCH) {
fltSk.setMinItem(minFloat);
fltSk.setMaxItem(maxFloat);
fltSk.setFloatItemsArray(myNewFloatItemsArr);
- }
+ }
else if (sketchType == LONGS_SKETCH) {
final KllLongsSketch lngSk = (KllLongsSketch) sketch;
lngSk.setMinItem(minLong);
diff --git a/src/main/java/org/apache/datasketches/kll/KllLongsHelper.java b/src/main/java/org/apache/datasketches/kll/KllLongsHelper.java
index 04fe2cc08..2dc146103 100644
--- a/src/main/java/org/apache/datasketches/kll/KllLongsHelper.java
+++ b/src/main/java/org/apache/datasketches/kll/KllLongsHelper.java
@@ -207,8 +207,11 @@ static void mergeLongsImpl(final KllLongsSketch mySketch, final KllLongsSketch o
//MEMORY SPACE MANAGEMENT
if (mySketch.getWritableMemory() != null) {
- final WritableMemory wmem =
- KllHelper.memorySpaceMgmt(mySketch, myNewLevelsArr.length, myNewLongItemsArray.length);
+ final WritableMemory oldWmem = mySketch.getWritableMemory();
+ final WritableMemory wmem = KllHelper.memorySpaceMgmt(mySketch, myNewLevelsArr.length, myNewLongItemsArray.length);
+ if (!wmem.isSameResource(oldWmem)) {
+ mySketch.getMemoryRequestServer().requestClose(oldWmem);
+ }
mySketch.setWritableMemory(wmem);
}
} //end of updating levels above level 0
diff --git a/src/main/java/org/apache/datasketches/kll/KllLongsSketch.java b/src/main/java/org/apache/datasketches/kll/KllLongsSketch.java
index f5688ad70..827f825f8 100644
--- a/src/main/java/org/apache/datasketches/kll/KllLongsSketch.java
+++ b/src/main/java/org/apache/datasketches/kll/KllLongsSketch.java
@@ -137,7 +137,7 @@ public static KllLongsSketch wrap(final Memory srcMem) {
Objects.requireNonNull(srcMem, "Parameter 'srcMem' must not be null");
final KllMemoryValidate memVal = new KllMemoryValidate(srcMem, LONGS_SKETCH, null);
if (memVal.sketchStructure == UPDATABLE) {
- final MemoryRequestServer memReqSvr = new DefaultMemoryRequestServer(); //dummy
+ final MemoryRequestServer memReqSvr = new DefaultMemoryRequestServer();
return new KllDirectLongsSketch(memVal.sketchStructure, (WritableMemory)srcMem, memReqSvr, memVal);
} else {
return new KllDirectCompactLongsSketch(memVal.sketchStructure, srcMem, memVal);
diff --git a/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketch.java b/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketch.java
index 7a7a7a850..12604ecb3 100644
--- a/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketch.java
+++ b/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketch.java
@@ -266,9 +266,8 @@ private WritableMemory growCombinedMemBuffer(final int itemSpaceNeeded) {
}
final WritableMemory newMem = memReqSvr.request(mem_, needBytes);
-
mem_.copyTo(0, newMem, 0, memBytes);
- memReqSvr.requestClose(mem_, newMem);
+ memReqSvr.requestClose(mem_);
return newMem;
}
diff --git a/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketchR.java b/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketchR.java
index 3e80b3f0f..234170331 100644
--- a/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketchR.java
+++ b/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketchR.java
@@ -146,7 +146,7 @@ int getBaseBufferCount() {
@Override
int getCombinedBufferItemCapacity() {
- return ((int)mem_.getCapacity() - COMBINED_BUFFER) / 8;
+ return Math.max(0, (int)mem_.getCapacity() - COMBINED_BUFFER) / 8;
}
@Override
diff --git a/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java b/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java
index 2fc399f9b..4c9f74286 100644
--- a/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java
+++ b/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java
@@ -460,9 +460,9 @@ public static int getUpdatableStorageBytes(final int k, final long n) {
final int totLevels = computeNumLevelsNeeded(k, n);
if (n <= k) {
final int ceil = Math.max(ceilingPowerOf2((int)n), MIN_K * 2);
- return metaPre + ceil << 3;
+ return (metaPre + ceil) << 3;
}
- return metaPre + (2 + totLevels) * k << 3;
+ return (metaPre + (2 + totLevels) * k) << 3;
}
/**
diff --git a/src/main/java/org/apache/datasketches/theta/ConcurrentDirectQuickSelectSketch.java b/src/main/java/org/apache/datasketches/theta/ConcurrentDirectQuickSelectSketch.java
index 946603194..dbdedebd5 100644
--- a/src/main/java/org/apache/datasketches/theta/ConcurrentDirectQuickSelectSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/ConcurrentDirectQuickSelectSketch.java
@@ -199,7 +199,7 @@ public void awaitBgPropagationTermination() {
@Override
public final void initBgPropagationService() {
- executorService_ = ConcurrentPropagationService.getExecutorService(Thread.currentThread().getId());
+ executorService_ = ConcurrentPropagationService.getExecutorService(Thread.currentThread().threadId());
}
@Override
@@ -258,7 +258,7 @@ public boolean validateEpoch(final long epoch) {
private void advanceEpoch() {
awaitBgPropagationTermination();
startEagerPropagation();
- ConcurrentPropagationService.resetExecutorService(Thread.currentThread().getId());
+ ConcurrentPropagationService.resetExecutorService(Thread.currentThread().threadId());
//no inspection NonAtomicOperationOnVolatileField
// this increment of a volatile field is done within the scope of the propagation
// synchronization and hence is done by a single thread.
diff --git a/src/main/java/org/apache/datasketches/theta/ConcurrentHeapQuickSelectSketch.java b/src/main/java/org/apache/datasketches/theta/ConcurrentHeapQuickSelectSketch.java
index 1ce3b4ecc..e4cc3a157 100644
--- a/src/main/java/org/apache/datasketches/theta/ConcurrentHeapQuickSelectSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/ConcurrentHeapQuickSelectSketch.java
@@ -194,7 +194,7 @@ public void awaitBgPropagationTermination() {
@Override
public void initBgPropagationService() {
- executorService_ = ConcurrentPropagationService.getExecutorService(Thread.currentThread().getId());
+ executorService_ = ConcurrentPropagationService.getExecutorService(Thread.currentThread().threadId());
}
@Override
@@ -253,7 +253,7 @@ public boolean validateEpoch(final long epoch) {
private void advanceEpoch() {
awaitBgPropagationTermination();
startEagerPropagation();
- ConcurrentPropagationService.resetExecutorService(Thread.currentThread().getId());
+ ConcurrentPropagationService.resetExecutorService(Thread.currentThread().threadId());
//no inspection NonAtomicOperationOnVolatileField
// this increment of a volatile field is done within the scope of the propagation
// synchronization and hence is done by a single thread
diff --git a/src/main/java/org/apache/datasketches/theta/DirectQuickSelectSketch.java b/src/main/java/org/apache/datasketches/theta/DirectQuickSelectSketch.java
index ad9051a08..af073a5ee 100644
--- a/src/main/java/org/apache/datasketches/theta/DirectQuickSelectSketch.java
+++ b/src/main/java/org/apache/datasketches/theta/DirectQuickSelectSketch.java
@@ -327,11 +327,11 @@ UpdateReturnState hashUpdate(final long hash) {
throw new SketchesArgumentException("Out of Memory, MemoryRequestServer is null, cannot expand.");
}
- final WritableMemory newDstMem = memReqSvr_.request(wmem_,reqBytes);
+ final WritableMemory newDstMem = memReqSvr_.request(wmem_, reqBytes);
moveAndResize(wmem_, preambleLongs, lgArrLongs, newDstMem, tgtLgArrLongs, thetaLong);
- memReqSvr_.requestClose(wmem_, newDstMem);
+ memReqSvr_.requestClose(wmem_);
wmem_ = newDstMem;
hashTableThreshold_ = getOffHeapHashTableThreshold(lgNomLongs, tgtLgArrLongs);
diff --git a/src/test/java/org/apache/datasketches/filters/bloomfilter/BloomFilterTest.java b/src/test/java/org/apache/datasketches/filters/bloomfilter/BloomFilterTest.java
index 7d72fae2f..2d71805ac 100644
--- a/src/test/java/org/apache/datasketches/filters/bloomfilter/BloomFilterTest.java
+++ b/src/test/java/org/apache/datasketches/filters/bloomfilter/BloomFilterTest.java
@@ -31,7 +31,7 @@
import org.apache.datasketches.memory.WritableMemory;
import org.testng.annotations.Test;
-import jdk.incubator.foreign.ResourceScope;
+import java.lang.foreign.Arena;
public class BloomFilterTest {
@@ -52,8 +52,9 @@ public void createNewFilterTest() throws Exception {
assertFalse(bf1.isDirect());
assertFalse(bf1.isReadOnly());
- WritableMemory wmem;
- try (ResourceScope scope = (wmem = WritableMemory.allocateDirect(sizeBytes)).scope()) {
+
+ try (Arena arena = Arena.ofConfined()) {
+ WritableMemory wmem = WritableMemory.allocateDirect(sizeBytes, arena);
final BloomFilter bf2 = new BloomFilter(numBits, numHashes, seed, wmem);
assertTrue(bf2.isEmpty());
assertTrue(bf2.hasMemory());
@@ -158,8 +159,9 @@ public void basicFilterOperationsTest() {
int numFound = 0;
for (long i = 0; i < 2 * n; ++i) {
- if (bf.query(i))
+ if (bf.query(i)) {
++numFound;
+ }
}
assertTrue(numFound >= n);
assertTrue(numFound < 1.1 * n);
@@ -339,8 +341,12 @@ public void nonEmptySerializationTest() {
int fromBytesCount = 0;
for (int i = 0; i < numBits; ++i) {
boolean val = fromBytes.query(0.5 + i);
- if (val) ++fromBytesCount;
- if (i < n) assertTrue(val);
+ if (val) {
+ ++fromBytesCount;
+ }
+ if (i < n) {
+ assertTrue(val);
+ }
}
assertEquals(fromBytesCount, n + count); // same numbers of items should match
@@ -354,8 +360,12 @@ public void nonEmptySerializationTest() {
int fromLongsCount = 0;
for (int i = 0; i < numBits; ++i) {
boolean val = fromLongs.query(0.5 + i);
- if (val) ++fromLongsCount;
- if (i < n) assertTrue(val);
+ if (val) {
+ ++fromLongsCount;
+ }
+ if (i < n) {
+ assertTrue(val);
+ }
}
assertEquals(fromLongsCount, n + count); // same numbers of items should match
diff --git a/src/test/java/org/apache/datasketches/hash/MurmurHash3AdaptorTest.java b/src/test/java/org/apache/datasketches/hash/MurmurHash3AdaptorTest.java
deleted file mode 100644
index 16a8e6652..000000000
--- a/src/test/java/org/apache/datasketches/hash/MurmurHash3AdaptorTest.java
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.datasketches.hash;
-
-import static org.apache.datasketches.hash.MurmurHash3Adaptor.asDouble;
-import static org.apache.datasketches.hash.MurmurHash3Adaptor.asInt;
-import static org.apache.datasketches.hash.MurmurHash3Adaptor.hashToBytes;
-import static org.apache.datasketches.hash.MurmurHash3Adaptor.hashToLongs;
-import static org.apache.datasketches.hash.MurmurHash3Adaptor.modulo;
-
-import org.apache.datasketches.common.SketchesArgumentException;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-/**
- * @author Lee Rhodes
- */
-public class MurmurHash3AdaptorTest {
-
- @Test
- public void checkToBytesLong() {
- byte[] result = hashToBytes(2L, 0L);
- for (int i = 8; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- }
-
- @Test
- public void checkToBytesLongArr() {
- long[] arr = { 1L, 2L };
- byte[] result = hashToBytes(arr, 0L);
- for (int i = 8; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- arr = null;
- result = hashToBytes(arr, 0L);
- Assert.assertEquals(result, null);
-
- arr = new long[0];
- result = hashToBytes(arr, 0L);
- Assert.assertEquals(result, null);
- }
-
- @Test
- public void checkToBytesIntArr() {
- int[] arr = { 1, 2 };
- byte[] result = hashToBytes(arr, 0L);
- for (int i = 8; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- arr = null;
- result = hashToBytes(arr, 0L);
- Assert.assertEquals(result, null);
-
- arr = new int[0];
- result = hashToBytes(arr, 0L);
- Assert.assertEquals(result, null);
- }
-
- @Test
- public void checkToBytesCharArr() {
- char[] arr = { 1, 2 };
- byte[] result = hashToBytes(arr, 0L);
- for (int i = 8; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- arr = null;
- result = hashToBytes(arr, 0L);
- Assert.assertEquals(result, null);
-
- arr = new char[0];
- result = hashToBytes(arr, 0L);
- Assert.assertEquals(result, null);
- }
-
- @Test
- public void checkToBytesByteArr() {
- byte[] arr = { 1, 2 };
- byte[] result = hashToBytes(arr, 0L);
- for (int i = 8; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- arr = null;
- result = hashToBytes(arr, 0L);
- Assert.assertEquals(result, null);
-
- arr = new byte[0];
- result = hashToBytes(arr, 0L);
- Assert.assertEquals(result, null);
-
- }
-
- @Test
- public void checkToBytesDouble() {
- byte[] result = hashToBytes(1.0, 0L);
- for (int i = 8; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- result = hashToBytes(0.0, 0L);
- for (int i = 8; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- result = hashToBytes( -0.0, 0L);
- for (int i = 8; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- }
-
- @Test
- public void checkToBytesString() {
- byte[] result = hashToBytes("1", 0L);
- for (int i = 8; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- result = hashToBytes("", 0L);
- Assert.assertEquals(result, null);
-
- String s = null;
- result = hashToBytes(s, 0L);
- Assert.assertEquals(result, null);
- }
-
- /************/
-
- @Test
- public void checkToLongsLong() {
- long[] result = hashToLongs(2L, 0L);
- for (int i = 2; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- }
-
- @Test
- public void checkToLongsLongArr() {
- long[] arr = { 1L, 2L };
- long[] result = hashToLongs(arr, 0L);
- for (int i = 2; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- arr = null;
- result = hashToLongs(arr, 0L);
- Assert.assertEquals(result, null);
-
- arr = new long[0];
- result = hashToLongs(arr, 0L);
- Assert.assertEquals(result, null);
- }
-
- @Test
- public void checkToLongsIntArr() {
- int[] arr = { 1, 2 };
- long[] result = hashToLongs(arr, 0L);
- for (int i = 2; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- arr = null;
- result = hashToLongs(arr, 0L);
- Assert.assertEquals(result, null);
-
- arr = new int[0];
- result = hashToLongs(arr, 0L);
- Assert.assertEquals(result, null);
- }
-
- @Test
- public void checkToLongsCharArr() {
- char[] arr = { 1, 2 };
- long[] result = hashToLongs(arr, 0L);
- for (int i = 2; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- arr = null;
- result = hashToLongs(arr, 0L);
- Assert.assertEquals(result, null);
-
- arr = new char[0];
- result = hashToLongs(arr, 0L);
- Assert.assertEquals(result, null);
- }
-
- @Test
- public void checkToLongsByteArr() {
- byte[] arr = { 1, 2 };
- long[] result = hashToLongs(arr, 0L);
- for (int i = 2; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- arr = null;
- result = hashToLongs(arr, 0L);
- Assert.assertEquals(result, null);
-
- arr = new byte[0];
- result = hashToLongs(arr, 0L);
- Assert.assertEquals(result, null);
-
- }
-
- @Test
- public void checkToLongsDouble() {
- long[] result = hashToLongs(1.0, 0L);
- for (int i = 2; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- result = hashToLongs(0.0, 0L);
- for (int i = 2; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- result = hashToLongs( -0.0, 0L);
- for (int i = 2; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- }
-
- @Test
- public void checkToLongsString() {
- long[] result = hashToLongs("1", 0L);
- for (int i = 2; i-- > 0;) {
- Assert.assertNotEquals(result[i], 0);
- }
- result = hashToLongs("", 0L);
- Assert.assertEquals(result, null);
- String s = null;
- result = hashToLongs(s, 0L);
- Assert.assertEquals(result, null);
- }
-
- /*************/
-
- @Test
- public void checkModulo() {
- int div = 7;
- for (int i = 20; i-- > 0;) {
- long[] out = hashToLongs(i, 9001);
- int mod = modulo(out[0], out[1], div);
- Assert.assertTrue((mod < div) && (mod >= 0));
- mod = modulo(out, div);
- Assert.assertTrue((mod < div) && (mod >= 0));
- }
- }
-
- @Test
- public void checkAsDouble() {
- for (int i = 0; i < 10000; i++ ) {
- double result = asDouble(hashToLongs(i, 0));
- Assert.assertTrue((result >= 0) && (result < 1.0));
- }
- }
-
- //Check asInt() functions
-
- @Test
- public void checkAsInt() {
- int lo = (3 << 28);
- int hi = (1 << 30) + 1;
- for (byte i = 0; i < 126; i++ ) {
- long[] longArr = {i, i+1}; //long[]
- int result = asInt(longArr, lo);
- Assert.assertTrue((result >= 0) && (result < lo));
- result = asInt(longArr, hi);
- Assert.assertTrue((result >= 0) && (result < hi));
-
- int[] intArr = {i, i+1}; //int[]
- result = asInt(intArr, lo);
- Assert.assertTrue((result >= 0) && (result < lo));
- result = asInt(intArr, hi);
- Assert.assertTrue((result >= 0) && (result < hi));
-
- byte[] byteArr = {i, (byte)(i+1)}; //byte[]
- result = asInt(byteArr, lo);
- Assert.assertTrue((result >= 0) && (result < lo));
- result = asInt(byteArr, hi);
- Assert.assertTrue((result >= 0) && (result < hi));
-
- long longV = i; //long
- result = asInt(longV, lo);
- Assert.assertTrue((result >= 0) && (result < lo));
- result = asInt(longV, hi);
- Assert.assertTrue((result >= 0) && (result < hi));
-
- double v = i; //double
- result = asInt(v, lo);
- Assert.assertTrue((result >= 0) && (result < lo));
- result = asInt(v, hi);
- Assert.assertTrue((result >= 0) && (result < hi));
-
- String s = Integer.toString(i); //String
- result = asInt(s, lo);
- Assert.assertTrue((result >= 0) && (result < lo));
- result = asInt(s, hi);
- Assert.assertTrue((result >= 0) && (result < hi));
- }
- }
-
- @Test (expectedExceptions = SketchesArgumentException.class)
- public void checkAsIntCornerCaseLongNull() {
- long[] arr = null;
- asInt(arr, 1000);
- }
-
- @Test (expectedExceptions = SketchesArgumentException.class)
- public void checkAsIntCornerCaseLongEmpty() {
- long[] arr = new long[0];
- asInt(arr, 1000);
- }
-
- @Test (expectedExceptions = SketchesArgumentException.class)
- public void checkAsIntCornerCaseIntNull() {
- int[] arr = null;
- asInt(arr, 1000);
- }
-
- @Test (expectedExceptions = SketchesArgumentException.class)
- public void checkAsIntCornerCaseIntEmpty() {
- int[] arr = new int[0];
- asInt(arr, 1000);
- }
-
- @Test (expectedExceptions = SketchesArgumentException.class)
- public void checkAsIntCornerCaseByteNull() {
- byte[] arr = null;
- asInt(arr, 1000);
- }
-
- @Test (expectedExceptions = SketchesArgumentException.class)
- public void checkAsIntCornerCaseByteEmpty() {
- byte[] arr = new byte[0];
- asInt(arr, 1000);
- }
-
- @Test (expectedExceptions = SketchesArgumentException.class)
- public void checkAsIntCornerCaseStringNull() {
- String s = null;
- asInt(s, 1000);
- }
-
- @Test (expectedExceptions = SketchesArgumentException.class)
- public void checkAsIntCornerCaseStringEmpty() {
- String s = "";
- asInt(s, 1000);
- }
-
- @Test (expectedExceptions = SketchesArgumentException.class)
- public void checkAsIntCornerCaseNTooSmall() {
- String s = "abc";
- asInt(s, 1);
- }
-
- @Test
- public void printlnTest() {
- println("PRINTING: "+this.getClass().getName());
- }
-
- /**
- * @param s value to print
- */
- static void println(String s) {
- //System.out.println(s); //disable here
- }
-
-}
diff --git a/src/test/java/org/apache/datasketches/hash/MurmurHash3v4Test.java b/src/test/java/org/apache/datasketches/hash/MurmurHash3FFM21Test.java
similarity index 83%
rename from src/test/java/org/apache/datasketches/hash/MurmurHash3v4Test.java
rename to src/test/java/org/apache/datasketches/hash/MurmurHash3FFM21Test.java
index 6cd4d624f..d9771d304 100644
--- a/src/test/java/org/apache/datasketches/hash/MurmurHash3v4Test.java
+++ b/src/test/java/org/apache/datasketches/hash/MurmurHash3FFM21Test.java
@@ -28,13 +28,12 @@
import org.testng.annotations.Test;
import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.internal.MurmurHash3v4;
import org.apache.datasketches.memory.WritableMemory;
/**
* @author Lee Rhodes
*/
-public class MurmurHash3v4Test {
+public class MurmurHash3FFM21Test {
private Random rand = new Random();
private static final int trials = 1 << 20;
@@ -154,25 +153,25 @@ private static final long[] hashV1(byte[] key, long seed) {
}
private static final long[] hashV2(long[] key, long seed) {
- return MurmurHash3v4.hash(key, seed);
+ return MurmurHash3FFM21.hash(key, seed);
}
private static final long[] hashV2(int[] key2, long seed) {
- return MurmurHash3v4.hash(key2, seed);
+ return MurmurHash3FFM21.hash(key2, seed);
}
private static final long[] hashV2(char[] key, long seed) {
- return MurmurHash3v4.hash(key, seed);
+ return MurmurHash3FFM21.hash(key, seed);
}
private static final long[] hashV2(byte[] key, long seed) {
- return MurmurHash3v4.hash(key, seed);
+ return MurmurHash3FFM21.hash(key, seed);
}
//V2 single primitives
private static final long[] hashV2(long key, long seed, long[] out) {
- return MurmurHash3v4.hash(key, seed, out);
+ return MurmurHash3FFM21.hash(key, seed, out);
}
// private static final long[] hashV2(double key, long seed, long[] out) {
@@ -183,8 +182,6 @@ private static final long[] hashV2(long key, long seed, long[] out) {
// return MurmurHash3v4.hash(key, seed, out);
// }
-
-
@Test
public void offsetChecks() {
long seed = 12345;
@@ -197,9 +194,9 @@ public void offsetChecks() {
WritableMemory wmem = WritableMemory.allocate(cap);
for (int i = 0; i < cap; i++) { wmem.putByte(i, (byte)(-128 + i)); }
- for (int offset = 3; offset < 16; offset++) {
+ for (int offset = 0; offset < 16; offset++) {
int arrLen = cap - offset;
- hash1 = MurmurHash3v4.hash(wmem, offset, arrLen, seed, hash1);
+ hash1 = MurmurHash3FFM21.hash(wmem, offset, arrLen, seed, hash1);
byte[] byteArr2 = new byte[arrLen];
wmem.getByteArray(offset, byteArr2, 0, arrLen);
hash2 = MurmurHash3.hash(byteArr2, seed);
@@ -222,8 +219,8 @@ public void byteArrChecks() {
for (int i = 0; i < j; i++) { wmem.putByte(i, (byte) (-128 + i)); }
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v4.hash(in, seed);
+ hash2 = MurmurHash3FFM21.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3FFM21.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -246,8 +243,8 @@ public void charArrChecks() {
for (int i = 0; i < j; i++) { wmem.putInt(i, i); }
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v4.hash(in, seed);
+ hash2 = MurmurHash3FFM21.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3FFM21.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -270,8 +267,8 @@ public void intArrChecks() {
for (int i = 0; i < j; i++) { wmem.putInt(i, i); }
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v4.hash(in, seed);
+ hash2 = MurmurHash3FFM21.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3FFM21.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -294,8 +291,8 @@ public void longArrChecks() {
for (int i = 0; i < j; i++) { wmem.putLong(i, i); }
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v4.hash(in, seed);
+ hash2 = MurmurHash3FFM21.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3FFM21.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -313,8 +310,8 @@ public void longCheck() {
WritableMemory wmem = WritableMemory.writableWrap(in);
long[] hash1 = MurmurHash3.hash(in, 0);
- hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v4.hash(in, seed);
+ hash2 = MurmurHash3FFM21.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3FFM21.hash(in, seed);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
@@ -325,57 +322,57 @@ public void checkEmptiesNulls() {
long seed = 123;
long[] hashOut = new long[2];
try {
- MurmurHash3v4.hash(Memory.wrap(new long[0]), 0, 0, seed, hashOut); //mem empty
+ MurmurHash3FFM21.hash(Memory.wrap(new long[0]), 0, 0, seed, hashOut); //mem empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
String s = "";
- MurmurHash3v4.hash(s, seed, hashOut); //string empty
+ MurmurHash3FFM21.hash(s, seed, hashOut); //string empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
String s = null;
- MurmurHash3v4.hash(s, seed, hashOut); //string null
+ MurmurHash3FFM21.hash(s, seed, hashOut); //string null
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
byte[] barr = new byte[0];
- MurmurHash3v4.hash(barr, seed); //byte[] empty
+ MurmurHash3FFM21.hash(barr, seed); //byte[] empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
byte[] barr = null;
- MurmurHash3v4.hash(barr, seed); //byte[] null
+ MurmurHash3FFM21.hash(barr, seed); //byte[] null
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
char[] carr = new char[0];
- MurmurHash3v4.hash(carr, seed); //char[] empty
+ MurmurHash3FFM21.hash(carr, seed); //char[] empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
char[] carr = null;
- MurmurHash3v4.hash(carr, seed); //char[] null
+ MurmurHash3FFM21.hash(carr, seed); //char[] null
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
int[] iarr = new int[0];
- MurmurHash3v4.hash(iarr, seed); //int[] empty
+ MurmurHash3FFM21.hash(iarr, seed); //int[] empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
int[] iarr = null;
- MurmurHash3v4.hash(iarr, seed); //int[] null
+ MurmurHash3FFM21.hash(iarr, seed); //int[] null
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
long[] larr = new long[0];
- MurmurHash3v4.hash(larr, seed); //long[] empty
+ MurmurHash3FFM21.hash(larr, seed); //long[] empty
fail();
} catch (final IllegalArgumentException e) { } //OK
try {
long[] larr = null;
- MurmurHash3v4.hash(larr, seed); //long[] null
+ MurmurHash3FFM21.hash(larr, seed); //long[] null
fail();
} catch (final IllegalArgumentException e) { } //OK
}
@@ -385,9 +382,9 @@ public void checkStringLong() {
long seed = 123;
long[] hashOut = new long[2];
String s = "123";
- assertTrue(MurmurHash3v4.hash(s, seed, hashOut)[0] != 0);
+ assertTrue(MurmurHash3FFM21.hash(s, seed, hashOut)[0] != 0);
long v = 123;
- assertTrue(MurmurHash3v4.hash(v, seed, hashOut)[0] != 0);
+ assertTrue(MurmurHash3FFM21.hash(v, seed, hashOut)[0] != 0);
}
@Test
@@ -415,8 +412,8 @@ private static long[] checkDouble(double dbl) {
WritableMemory wmem = WritableMemory.writableWrap(dataArr);
long[] hash1 = MurmurHash3.hash(dataArr, 0);
- hash2 = MurmurHash3v4.hash(wmem, offset, bytes, seed, hash2);
- long[] hash3 = MurmurHash3v4.hash(dbl, seed, hash2);
+ hash2 = MurmurHash3FFM21.hash(wmem, offset, bytes, seed, hash2);
+ long[] hash3 = MurmurHash3FFM21.hash(dbl, seed, hash2);
assertEquals(hash1, hash2);
assertEquals(hash1, hash3);
diff --git a/src/test/java/org/apache/datasketches/hash/MurmurHash3FFM21bTest.java b/src/test/java/org/apache/datasketches/hash/MurmurHash3FFM21bTest.java
new file mode 100644
index 000000000..1e23772b5
--- /dev/null
+++ b/src/test/java/org/apache/datasketches/hash/MurmurHash3FFM21bTest.java
@@ -0,0 +1,419 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.hash;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.datasketches.hash.MurmurHash3FFM21.hash;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.MemorySegment;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.Resource;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Tests the MurmurHash3 against specific, known hash results given known
+ * inputs obtained from the public domain C++ version 150.
+ *
+ * @author Lee Rhodes
+ */
+public class MurmurHash3FFM21bTest {
+ private static final MemoryRequestServer memReqSvr = Resource.defaultMemReqSvr;
+
+ @Test
+ public void checkByteArrRemainderGT8() { //byte[], remainder > 8
+ String keyStr = "The quick brown fox jumps over the lazy dog";
+ byte[] key = keyStr.getBytes(UTF_8);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xe34bbc7bbc071b6cL;
+ long h2 = 0x7a433ca9c49a9347L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkByteArrRemainderGT8withSegment() { //byte[], remainder > 8
+ String keyStr = "The quick brown fox jumps over the lazy dog";
+ byte[] key = keyStr.getBytes(UTF_8);
+ long[] out = new long[2];
+ MemorySegment seg = MemorySegment.ofArray(key);
+ long[] result = hash(seg, 0, seg.byteSize(), 0, out);
+ //Should be:
+ long h1 = 0xe34bbc7bbc071b6cL;
+ long h2 = 0x7a433ca9c49a9347L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkByteArrChange1bit() { //byte[], change one bit
+ String keyStr = "The quick brown fox jumps over the lazy eog";
+ byte[] key = keyStr.getBytes(UTF_8);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0x362108102c62d1c9L;
+ long h2 = 0x3285cd100292b305L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkByteArrRemainderLt8() { //byte[], test a remainder < 8
+ String keyStr = "The quick brown fox jumps over the lazy dogdogdog";
+ byte[] key = keyStr.getBytes(UTF_8);
+ long[] result = hash(key, 0);
+ //Should be;
+ long h1 = 0x9c8205300e612fc4L;
+ long h2 = 0xcbc0af6136aa3df9L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkByteArrReaminderEQ8() { //byte[], test a remainder = 8
+ String keyStr = "The quick brown fox jumps over the lazy1";
+ byte[] key = keyStr.getBytes(UTF_8);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xe3301a827e5cdfe3L;
+ long h2 = 0xbdbf05f8da0f0392L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ /**
+ * This test should have the exact same output as Test4
+ */
+ @Test
+ public void checkLongArrRemainderEQ8() { //long[], test a remainder = 8
+ String keyStr = "The quick brown fox jumps over the lazy1";
+ long[] key = stringToLongs(keyStr);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xe3301a827e5cdfe3L;
+ long h2 = 0xbdbf05f8da0f0392L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ /**
+ * This test should have the exact same output as Test4
+ */
+ @Test
+ public void checkIntArrRemainderEQ8() { //int[], test a remainder = 8
+ String keyStr = "The quick brown fox jumps over the lazy1"; //40B
+ int[] key = stringToInts(keyStr);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xe3301a827e5cdfe3L;
+ long h2 = 0xbdbf05f8da0f0392L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkIntArrRemainderEQ0() { //int[], test a remainder = 0
+ String keyStr = "The quick brown fox jumps over t"; //32B
+ int[] key = stringToInts(keyStr);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xdf6af91bb29bdacfL;
+ long h2 = 0x91a341c58df1f3a6L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ /**
+ * Tests an odd remainder of int[].
+ */
+ @Test
+ public void checkIntArrOddRemainder() { //int[], odd remainder
+ String keyStr = "The quick brown fox jumps over the lazy dog"; //43B
+ int[] key = stringToInts(keyStr);
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0x1eb232b0087543f5L;
+ long h2 = 0xfc4c1383c3ace40fL;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ /**
+ * Tests an odd remainder of int[].
+ */
+ @Test
+ public void checkCharArrOddRemainder() { //char[], odd remainder
+ String keyStr = "The quick brown fox jumps over the lazy dog.."; //45B
+ char[] key = keyStr.toCharArray();
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0xca77b498ea9ed953L;
+ long h2 = 0x8b8f8ec3a8f4657eL;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ /**
+ * Tests an odd remainder of int[].
+ */
+ @Test
+ public void checkCharArrRemainderEQ0() { //char[], remainder of 0
+ String keyStr = "The quick brown fox jumps over the lazy "; //40B
+ char[] key = keyStr.toCharArray();
+ long[] result = hash(key, 0);
+ //Should be:
+ long h1 = 0x51b15e9d0887f9f1L;
+ long h2 = 0x8106d226786511ebL;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ @Test
+ public void checkByteArrAllOnesZeros() { //byte[], test a ones byte and a zeros byte
+ byte[] key = {
+ 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e,
+ 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x73, 0x20, 0x6f, 0x76, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67,
+ (byte) 0xff, 0x64, 0x6f, 0x67, 0x00
+ };
+ long[] result = MurmurHash3FFM21.hash(key, 0);
+ //Should be:
+ long h1 = 0xe88abda785929c9eL;
+ long h2 = 0x96b98587cacc83d6L;
+ Assert.assertEquals(result[0], h1);
+ Assert.assertEquals(result[1], h2);
+ }
+
+ /**
+ * This test demonstrates that the hash of byte[], char[], int[], or long[] will produce the
+ * same hash result if, and only if, all the arrays have the same exact length in bytes, and if
+ * the contents of the values in the arrays have the same byte endianness and overall order.
+ */
+ @Test
+ public void checkCrossTypeHashConsistency() {
+ long[] out;
+ println("Bytes");
+ byte[] bArr = {1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15,16, 17,18,19,20,21,22,23,24};
+ long[] out1 = hash(bArr, 0L);
+ println(longToHexBytes(out1[0]));
+ println(longToHexBytes(out1[1]));
+
+ println("Chars");
+ char[] cArr = {0X0201, 0X0403, 0X0605, 0X0807, 0X0a09, 0X0c0b, 0X0e0d, 0X100f,
+ 0X1211, 0X1413, 0X1615, 0X1817};
+ out = hash(cArr, 0L);
+ Assert.assertEquals(out, out1);
+ println(longToHexBytes(out[0]));
+ println(longToHexBytes(out[1]));
+
+ println("Ints");
+ int[] iArr = {0X04030201, 0X08070605, 0X0c0b0a09, 0X100f0e0d, 0X14131211, 0X18171615};
+ out = hash(iArr, 0L);
+ Assert.assertEquals(out, out1);
+ println(longToHexBytes(out[0]));
+ println(longToHexBytes(out[1]));
+
+ println("Longs");
+ long[] lArr = {0X0807060504030201L, 0X100f0e0d0c0b0a09L, 0X1817161514131211L};
+ out = hash(lArr, 0L);
+ Assert.assertEquals(out, out1);
+ println(longToHexBytes(out[0]));
+ println(longToHexBytes(out[1]));
+ }
+
+ @Test
+ public void checkEmptyOrNullExceptions() {
+ try {
+ long[] arr = null;
+ hash(arr, 1L);
+ fail();
+ }
+ catch (final IllegalArgumentException e) { }
+ try {
+ int[] arr = null; hash(arr, 1L); fail();
+ } catch (final IllegalArgumentException e) { }
+ try {
+ char[] arr = null; hash(arr, 1L); fail();
+ } catch (final IllegalArgumentException e) { }
+ try {
+ byte[] arr = null; hash(arr, 1L); fail();
+ } catch (final IllegalArgumentException e) { }
+
+ long[] out = new long[2];
+ try {
+ String in = null; hash(in, 1L, out); fail();
+ } catch (final IllegalArgumentException e) { }
+ try {
+ Memory mem = Memory.wrap(new byte[0]);
+ hash(mem, 0L, 4L, 1L, out);
+ } catch (final IllegalArgumentException e) { }
+ try (Arena arena = Arena.ofConfined()) {
+ Memory mem = WritableMemory.allocateDirect(8, 1, ByteOrder.nativeOrder(), memReqSvr, arena);
+ out = hash(mem, 0L, 4L, 1L, out);
+ }
+ assertTrue((out[0] != 0) && (out[1] != 0));
+ }
+
+ @Test
+ public void checkHashTails() {
+ long[] out = new long[2];
+ WritableMemory mem = WritableMemory.allocate(32);
+ mem.fill((byte)85);
+
+ for (int i = 16; i <= 32; i++) {
+ out = hash(mem, 0, i, 1L, out);
+ }
+ }
+
+ @Test
+ public void checkSinglePrimitives() {
+ long[] out = new long[2];
+ out = hash(1L, 1L, out);
+ out = hash(0.0, 1L, out);
+ out = hash("123", 1L, out);
+ }
+
+ //Helper methods
+
+ private static long[] stringToLongs(String in) {
+ byte[] bArr = in.getBytes(UTF_8);
+ int inLen = bArr.length;
+ int outLen = (inLen / 8) + (((inLen % 8) != 0) ? 1 : 0);
+ long[] out = new long[outLen];
+
+ for (int i = 0; i < (outLen - 1); i++ ) {
+ for (int j = 0; j < 8; j++ ) {
+ out[i] |= ((bArr[(i * 8) + j] & 0xFFL) << (j * 8));
+ }
+ }
+ int inTail = 8 * (outLen - 1);
+ int rem = inLen - inTail;
+ for (int j = 0; j < rem; j++ ) {
+ out[outLen - 1] |= ((bArr[inTail + j] & 0xFFL) << (j * 8));
+ }
+ return out;
+ }
+
+ private static int[] stringToInts(String in) {
+ byte[] bArr = in.getBytes(UTF_8);
+ int inLen = bArr.length;
+ int outLen = (inLen / 4) + (((inLen % 4) != 0) ? 1 : 0);
+ int[] out = new int[outLen];
+
+ for (int i = 0; i < (outLen - 1); i++ ) {
+ for (int j = 0; j < 4; j++ ) {
+ out[i] |= ((bArr[(i * 4) + j] & 0xFFL) << (j * 8));
+ }
+ }
+ int inTail = 4 * (outLen - 1);
+ int rem = inLen - inTail;
+ for (int j = 0; j < rem; j++ ) {
+ out[outLen - 1] |= ((bArr[inTail + j] & 0xFFL) << (j * 8));
+ }
+ return out;
+ }
+
+ /**
+ * Returns a string of spaced hex bytes in Big-Endian order.
+ * @param v the given long
+ * @return string of spaced hex bytes in Big-Endian order.
+ */
+ private static String longToHexBytes(final long v) {
+ final long mask = 0XFFL;
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 8; i-- > 0; ) {
+ final String s = Long.toHexString((v >>> (i * 8)) & mask);
+ sb.append(zeroPad(s, 2)).append(" ");
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Prepend the given string with zeros. If the given string is equal or greater than the given
+ * field length, it will be returned without modification.
+ * @param s the given string
+ * @param fieldLength desired total field length including the given string
+ * @return the given string prepended with zeros.
+ */
+ private static final String zeroPad(final String s, final int fieldLength) {
+ return characterPad(s, fieldLength, '0', false);
+ }
+
+ /**
+ * Prepend or postpend the given string with the given character to fill the given field length.
+ * If the given string is equal or greater than the given field length, it will be returned
+ * without modification.
+ * @param s the given string
+ * @param fieldLength the desired field length
+ * @param padChar the desired pad character
+ * @param postpend if true append the padCharacters to the end of the string.
+ * @return prepended or postpended given string with the given character to fill the given field
+ * length.
+ */
+ private static final String characterPad(final String s, final int fieldLength, final char padChar,
+ final boolean postpend) {
+ final char[] chArr = s.toCharArray();
+ final int sLen = chArr.length;
+ if (sLen < fieldLength) {
+ final char[] out = new char[fieldLength];
+ final int blanks = fieldLength - sLen;
+
+ if (postpend) {
+ for (int i = 0; i < sLen; i++) {
+ out[i] = chArr[i];
+ }
+ for (int i = sLen; i < fieldLength; i++) {
+ out[i] = padChar;
+ }
+ } else { //prepend
+ for (int i = 0; i < blanks; i++) {
+ out[i] = padChar;
+ }
+ for (int i = blanks; i < fieldLength; i++) {
+ out[i] = chArr[i - blanks];
+ }
+ }
+
+ return String.valueOf(out);
+ }
+ return s;
+ }
+
+ @Test
+ public void printlnTest() {
+ println("PRINTING: "+this.getClass().getName());
+ }
+
+ /**
+ * @param s value to print
+ */
+ static void println(String s) {
+ //System.out.println(s); //disable here
+ }
+
+}
diff --git a/src/test/java/org/apache/datasketches/hll/DirectAuxHashMapTest.java b/src/test/java/org/apache/datasketches/hll/DirectAuxHashMapTest.java
index 75504bc83..ecebe4539 100644
--- a/src/test/java/org/apache/datasketches/hll/DirectAuxHashMapTest.java
+++ b/src/test/java/org/apache/datasketches/hll/DirectAuxHashMapTest.java
@@ -26,11 +26,10 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-import java.nio.ByteOrder;
+import java.lang.foreign.Arena;
import java.util.HashMap;
import org.apache.datasketches.common.SketchesStateException;
-import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
import org.testng.annotations.Test;
@@ -47,7 +46,7 @@ public void checkGrow() {
int n = 8; //put lgConfigK == 4 into HLL mode
long bytes = HllSketch.getMaxUpdatableSerializationBytes(lgConfigK, tgtHllType);
HllSketch hllSketch;
- WritableMemory wmem = WritableMemory.allocateDirect(bytes, 1, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer());
+ WritableMemory wmem = WritableMemory.allocateDirect(bytes, Arena.ofConfined());
hllSketch = new HllSketch(lgConfigK, tgtHllType, wmem);
for (int i = 0; i < n; i++) {
@@ -56,7 +55,7 @@ public void checkGrow() {
hllSketch.couponUpdate(HllUtil.pair(7, 15)); //mock extreme values
hllSketch.couponUpdate(HllUtil.pair(8, 15));
hllSketch.couponUpdate(HllUtil.pair(9, 15));
- //println(hllSketch.toString(true, true, true, true));
+ println(hllSketch.toString(true, true, true, true));
DirectHllArray dha = (DirectHllArray) hllSketch.hllSketchImpl;
assertEquals(dha.getAuxHashMap().getLgAuxArrInts(), 2);
assertTrue(hllSketch.isMemory());
@@ -74,14 +73,14 @@ public void checkGrow() {
byteArray = hllSketch.toUpdatableByteArray();
WritableMemory wmem2 = WritableMemory.writableWrap(byteArray);
hllSketch2 = HllSketch.writableWrap(wmem2);
- //println(hllSketch2.toString(true, true, true, true));
+ println(hllSketch2.toString(true, true, true, true));
DirectHllArray dha2 = (DirectHllArray) hllSketch2.hllSketchImpl;
assertEquals(dha2.getAuxHashMap().getLgAuxArrInts(), 2);
assertEquals(dha2.getAuxHashMap().getAuxCount(), 3);
//Check grow to on-heap
hllSketch.couponUpdate(HllUtil.pair(10, 15)); //puts it over the edge, must grow
- //println(hllSketch.toString(true, true, true, true));
+ println(hllSketch.toString(true, true, true, true));
dha = (DirectHllArray) hllSketch.hllSketchImpl;
assertEquals(dha.getAuxHashMap().getLgAuxArrInts(), 3);
assertEquals(dha.getAuxHashMap().getAuxCount(), 4);
diff --git a/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java b/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java
index 1b00e0301..6da2f05fe 100644
--- a/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java
+++ b/src/test/java/org/apache/datasketches/hll/DirectCouponListTest.java
@@ -25,12 +25,11 @@
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
-import org.testng.annotations.Test;
-
-import jdk.incubator.foreign.ResourceScope;
+import java.lang.foreign.Arena;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.Test;
/**
* @author Lee Rhodes
@@ -71,7 +70,8 @@ private static void promotions(int lgConfigK, int n, TgtHllType tgtHllType, bool
//println("DIRECT");
byte[] barr1;
WritableMemory wmem;
- try (ResourceScope scope = (wmem = WritableMemory.allocateDirect(bytes)).scope()) {
+ try (Arena arena = Arena.ofConfined()) {
+ wmem = WritableMemory.allocateDirect(bytes, arena);
hllSketch = new HllSketch(lgConfigK, tgtHllType, wmem);
assertTrue(hllSketch.isEmpty());
diff --git a/src/test/java/org/apache/datasketches/kll/KllItemsSketchTest.java b/src/test/java/org/apache/datasketches/kll/KllItemsSketchTest.java
index 9fc74d97b..2e6cc1ea1 100644
--- a/src/test/java/org/apache/datasketches/kll/KllItemsSketchTest.java
+++ b/src/test/java/org/apache/datasketches/kll/KllItemsSketchTest.java
@@ -599,15 +599,18 @@ public void checkReadOnlyExceptions() {
@Test
public void checkIsSameResource() {
int cap = 128;
- WritableMemory wmem = WritableMemory.allocate(cap);
+ WritableMemory wmem = WritableMemory.allocate(cap); //heap
WritableMemory reg1 = wmem.writableRegion(0, 64);
WritableMemory reg2 = wmem.writableRegion(64, 64);
assertFalse(reg1 == reg2);
- assertFalse(reg1.isSameResource(reg2));
+ assertFalse(reg1.isSameResource(reg2)); //same original resource, but different offsets
WritableMemory reg3 = wmem.writableRegion(0, 64);
assertFalse(reg1 == reg3);
- assertTrue(reg1.isSameResource(reg3));
+ assertTrue(reg1.isSameResource(reg3)); //same original resource, same offsets, different views.
+ reg1.putInt(0, -1);
+ assertEquals(-1, reg3.getInt(0)); //proof
+ reg1.putInt(0, 0);
byte[] byteArr1 = KllItemsSketch.newHeapInstance(20, Comparator.naturalOrder(), serDe).toByteArray();
reg1.putByteArray(0, byteArr1, 0, byteArr1.length);
@@ -615,11 +618,11 @@ public void checkIsSameResource() {
byte[] byteArr2 = KllItemsSketch.newHeapInstance(20, Comparator.naturalOrder(), serDe).toByteArray();
reg2.putByteArray(0, byteArr2, 0, byteArr2.length);
- assertFalse(sk1.isSameResource(reg2));
+ assertFalse(sk1.isSameResource(reg2)); //same original resource, but different offsets
byte[] byteArr3 = KllItemsSketch.newHeapInstance(20, Comparator.naturalOrder(), serDe).toByteArray();
reg3.putByteArray(0, byteArr3, 0, byteArr3.length);
- assertTrue(sk1.isSameResource(reg3));
+ assertTrue(sk1.isSameResource(reg3)); //same original resource, same offsets, different views.
}
// New added tests specially for KllItemsSketch
diff --git a/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java b/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java
index e51be4b20..2b67f9772 100644
--- a/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/DebugUnionTest.java
@@ -27,7 +27,8 @@
import org.testng.annotations.Test;
-import jdk.incubator.foreign.ResourceScope;
+import java.lang.foreign.Arena;
+import java.nio.ByteOrder;
import org.apache.datasketches.memory.WritableMemory;
import org.apache.datasketches.quantilescommon.QuantilesDoublesSketchIterator;
@@ -63,8 +64,8 @@ public void test() {
DoublesSketch.setRandom(1); //make deterministic for test
DoublesUnion dUnion;
DoublesSketch dSketch;
- WritableMemory wmem;
- try (ResourceScope scope = (wmem = WritableMemory.allocateDirect(10_000_000)).scope()) {
+ try (Arena arena = Arena.ofConfined()) {
+ WritableMemory wmem = WritableMemory.allocateDirect(10_000_000, arena);
dUnion = DoublesUnion.builder().setMaxK(8).build(wmem);
for (int s = 0; s < numSketches; s++) { dUnion.union(sketchArr[s]); }
dSketch = dUnion.getResult(); //result is on heap
diff --git a/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java b/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java
index 5195f4187..1c8819981 100644
--- a/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/DirectQuantilesMemoryRequestTest.java
@@ -24,6 +24,7 @@
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
+import java.lang.foreign.Arena;
import java.nio.ByteOrder;
import org.apache.datasketches.memory.DefaultMemoryRequestServer;
@@ -47,7 +48,7 @@ public void checkLimitedMemoryScenarios() { //Requesting application
//########## Owning Implementation
// This part would actually be part of the Memory owning implementation so it is faked here
- WritableMemory wmem = WritableMemory.allocateDirect(initBytes, 1, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer());
+ WritableMemory wmem = WritableMemory.allocateDirect(initBytes, Arena.ofConfined());
WritableMemory wmem2 = wmem;
println("Initial mem size: " + wmem.getCapacity());
@@ -80,7 +81,7 @@ public void checkGrowBaseBuf() {
final int u = 32; // don't need the BB to fill here
final int initBytes = (4 + (u / 2)) << 3; // not enough to hold everything
- WritableMemory wmem = WritableMemory.allocateDirect(initBytes, 1, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer());
+ WritableMemory wmem = WritableMemory.allocateDirect(initBytes, Arena.ofConfined());
WritableMemory wmem2 = wmem;
println("Initial mem size: " + wmem.getCapacity());
final UpdateDoublesSketch usk1 = DoublesSketch.builder().setK(k).build(wmem);
@@ -99,7 +100,7 @@ public void checkGrowCombBuf() {
final int u = (2 * k) - 1; //just to fill the BB
final int initBytes = ((2 * k) + 4) << 3; //just room for BB
- WritableMemory wmem = WritableMemory.allocateDirect(initBytes, 1, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer());
+ WritableMemory wmem = WritableMemory.allocateDirect(initBytes, Arena.ofConfined());
WritableMemory wmem2 = wmem;
println("Initial mem size: " + wmem.getCapacity());
final UpdateDoublesSketch usk1 = DoublesSketch.builder().setK(k).build(wmem);
@@ -115,15 +116,28 @@ public void checkGrowCombBuf() {
assertFalse(wmem2.isAlive());
}
+ @Test
+ public void checkUpdatableStorageBytes() {
+ final int k = 16;
+ final int initBytes = DoublesSketch.getUpdatableStorageBytes(k, 1);
+ println("Predicted Updatable Storage Bytes: " + initBytes);
+ final UpdateDoublesSketch usk1 = DoublesSketch.builder().setK(k).build();
+ usk1.update(1.0);
+ byte[] uarr = usk1.toByteArray();
+ println("Actual Storage Bytes " + uarr.length);
+ assertEquals(initBytes, uarr.length); //64
+ }
+
+
@Test
public void checkGrowFromWrappedEmptySketch() {
final int k = 16;
final int n = 0;
- final int initBytes = DoublesSketch.getUpdatableStorageBytes(k, n); //8 bytes
+ final int initBytes = DoublesSketch.getUpdatableStorageBytes(k, n); //empty: 8 bytes
final UpdateDoublesSketch usk1 = DoublesSketch.builder().setK(k).build();
- final Memory origSketchMem = Memory.wrap(usk1.toByteArray());
+ final Memory origSketchMem = Memory.wrap(usk1.toByteArray()); //on heap
- WritableMemory wmem = WritableMemory.allocateDirect(initBytes, 1, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer());
+ WritableMemory wmem = WritableMemory.allocateDirect(initBytes, Arena.ofConfined()); //off heap
WritableMemory wmem2 = wmem;
origSketchMem.copyTo(0, wmem, 0, initBytes);
UpdateDoublesSketch usk2 = DirectUpdateDoublesSketch.wrapInstance(wmem);
@@ -133,11 +147,11 @@ public void checkGrowFromWrappedEmptySketch() {
assertTrue(usk2.isEmpty());
//update the sketch forcing it to grow on-heap
- for (int i = 1; i <= 5; i++) { usk2.update(i); }
- assertEquals(usk2.getN(), 5);
+ usk2.update(1.0);
+ assertEquals(usk2.getN(), 1);
WritableMemory mem2 = usk2.getMemory();
assertFalse(wmem.isSameResource(mem2));
- assertFalse(mem2.isDirect()); //should now be on-heap
+ assertFalse(mem2.isDirect()); //should now be on-heap //TODO
final int expectedSize = COMBINED_BUFFER + ((2 * k) << 3);
assertEquals(mem2.getCapacity(), expectedSize);
diff --git a/src/test/java/org/apache/datasketches/quantiles/DoublesSketchTest.java b/src/test/java/org/apache/datasketches/quantiles/DoublesSketchTest.java
index 8cdc7bf71..762cfc057 100644
--- a/src/test/java/org/apache/datasketches/quantiles/DoublesSketchTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/DoublesSketchTest.java
@@ -34,7 +34,7 @@
import org.testng.Assert;
import org.testng.annotations.Test;
-import jdk.incubator.foreign.ResourceScope;
+import java.lang.foreign.Arena;
public class DoublesSketchTest {
@@ -141,7 +141,7 @@ public void checkEmptyExceptions() {
@Test
public void directSketchShouldMoveOntoHeapEventually() {
- WritableMemory wmem = WritableMemory.allocateDirect(1000, 1, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer());
+ WritableMemory wmem = WritableMemory.allocateDirect(1000, Arena.ofConfined());
WritableMemory wmem2 = wmem;
UpdateDoublesSketch sketch = DoublesSketch.builder().build(wmem);
Assert.assertTrue(sketch.isSameResource(wmem));
@@ -155,7 +155,7 @@ public void directSketchShouldMoveOntoHeapEventually() {
@Test
public void directSketchShouldMoveOntoHeapEventually2() {
int i = 0;
- WritableMemory wmem = WritableMemory.allocateDirect(50, 1, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer());
+ WritableMemory wmem = WritableMemory.allocateDirect(50, Arena.ofConfined());
WritableMemory wmem2 = wmem;
UpdateDoublesSketch sketch = DoublesSketch.builder().build(wmem);
Assert.assertTrue(sketch.isSameResource(wmem));
@@ -172,10 +172,8 @@ public void directSketchShouldMoveOntoHeapEventually2() {
@Test
public void checkEmptyDirect() {
- WritableMemory wmem ;
- try (ResourceScope scope = (wmem = WritableMemory.allocateDirect(1000, 1,
- ByteOrder.nativeOrder(), new DefaultMemoryRequestServer())).scope()) {
-
+ try (Arena arena = Arena.ofConfined()) {
+ WritableMemory wmem = WritableMemory.allocateDirect(1000, Arena.ofConfined());
UpdateDoublesSketch sketch = DoublesSketch.builder().build(wmem);
sketch.toByteArray(); //exercises a specific path
} catch (final Exception e) {
diff --git a/src/test/java/org/apache/datasketches/quantiles/PreambleUtilTest.java b/src/test/java/org/apache/datasketches/quantiles/PreambleUtilTest.java
index adf916ef3..765d4d037 100644
--- a/src/test/java/org/apache/datasketches/quantiles/PreambleUtilTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/PreambleUtilTest.java
@@ -37,24 +37,19 @@
import static org.apache.datasketches.quantiles.PreambleUtil.insertSerVer;
import static org.testng.Assert.assertEquals;
-import java.nio.ByteOrder;
+import java.lang.foreign.Arena;
-import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
import org.testng.annotations.Test;
-import jdk.incubator.foreign.ResourceScope;
-
public class PreambleUtilTest {
@Test
public void checkInsertsAndExtracts() {
final int bytes = 32;
- WritableMemory offHeapMem;
- try (ResourceScope scope = (offHeapMem = WritableMemory.allocateDirect(bytes, 1,
- ByteOrder.nativeOrder(), new DefaultMemoryRequestServer())).scope()) {
-
+ try (Arena arena = Arena.ofConfined()) {
+ WritableMemory offHeapMem = WritableMemory.allocateDirect(bytes, arena);
final WritableMemory onHeapMem = WritableMemory.writableWrap(new byte[bytes]);
onHeapMem.clear();
diff --git a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
index e0f79087b..cc5be6a85 100644
--- a/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
+++ b/src/test/java/org/apache/datasketches/theta/CompactSketchTest.java
@@ -32,7 +32,7 @@
import org.apache.datasketches.memory.WritableMemory;
import org.testng.annotations.Test;
-import jdk.incubator.foreign.ResourceScope;
+import java.lang.foreign.Arena;
/**
* @author Lee Rhodes
@@ -79,8 +79,8 @@ public void checkHeapifyWrap(int k, int u, boolean ordered) {
//Prepare Memory for direct
int bytes = usk.getCompactBytes(); //for Compact
- WritableMemory directMem;
- try (ResourceScope scope = (directMem = WritableMemory.allocateDirect(bytes)).scope()) {
+ try (Arena arena = Arena.ofConfined()) {
+ WritableMemory directMem = WritableMemory.allocateDirect(bytes, arena);
/**Via CompactSketch.compact**/
refSk = usk.compact(ordered, directMem);
diff --git a/src/test/java/org/apache/datasketches/theta/DirectQuickSelectSketchTest.java b/src/test/java/org/apache/datasketches/theta/DirectQuickSelectSketchTest.java
index f36597b7c..5f608113a 100644
--- a/src/test/java/org/apache/datasketches/theta/DirectQuickSelectSketchTest.java
+++ b/src/test/java/org/apache/datasketches/theta/DirectQuickSelectSketchTest.java
@@ -38,6 +38,7 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
+import java.lang.foreign.Arena;
import java.nio.ByteOrder;
import java.util.Arrays;
@@ -52,8 +53,6 @@
import org.apache.datasketches.thetacommon.ThetaUtil;
import org.testng.annotations.Test;
-import jdk.incubator.foreign.ResourceScope;
-
/**
* @author Lee Rhodes
*/
@@ -62,8 +61,8 @@ public class DirectQuickSelectSketchTest {
@Test//(expectedExceptions = SketchesArgumentException.class)
public void checkBadSerVer() {
int k = 512;
- WritableMemory wmem;
- try (ResourceScope scope = (wmem = makeNativeMemory(k)).scope()) {
+ try (Arena arena = Arena.ofConfined()) {
+ WritableMemory wmem = makeNativeMemory(k, arena);
UpdateSketch usk = UpdateSketch.builder().setNominalEntries(k).build(wmem);
DirectQuickSelectSketch sk1 = (DirectQuickSelectSketch)usk; //for internal checks
@@ -88,8 +87,8 @@ public void checkBadSerVer() {
@Test
public void checkConstructorKtooSmall() {
int k = 8;
- WritableMemory wmem;
- try (ResourceScope scope = (wmem = makeNativeMemory(k)).scope()) {
+ try (Arena arena = Arena.ofConfined()) {
+ WritableMemory wmem = makeNativeMemory(k, arena);
UpdateSketch.builder().setNominalEntries(k).build(wmem);
} catch (final Exception e) {
if (e instanceof SketchesArgumentException) {}
@@ -100,8 +99,8 @@ public void checkConstructorKtooSmall() {
@Test
public void checkConstructorMemTooSmall() {
int k = 16;
- WritableMemory wmem;
- try (ResourceScope scope = (wmem = makeNativeMemory(k/2)).scope()) {
+ try (Arena arena = Arena.ofConfined()) {
+ WritableMemory wmem = makeNativeMemory(k/2, arena);
UpdateSketch.builder().setNominalEntries(k).build(wmem);
} catch (final Exception e) {
if (e instanceof SketchesArgumentException) {}
@@ -126,10 +125,8 @@ public void checkHeapifyIllegalFamilyID_heapify() {
public void checkHeapifyMemoryEstimating() {
int k = 512;
int u = 2*k; //thus estimating
-
- WritableMemory wmem;
- try (ResourceScope scope = (wmem = makeNativeMemory(k)).scope()) {
-
+ try (Arena arena = Arena.ofConfined()) {
+ WritableMemory wmem = makeNativeMemory(k, arena);
UpdateSketch sk1 = UpdateSketch.builder().setNominalEntries(k).build(wmem);
for (int i=0; i
Date: Thu, 20 Feb 2025 15:59:19 -0800
Subject: [PATCH 71/88] Update .asf.yaml:
---
.asf.yaml | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/.asf.yaml b/.asf.yaml
index 50695edc9..5628899f8 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -4,15 +4,24 @@ github:
ghp_branch: gh-pages
ghp_path: /docs
- master:
- required_status_checks:
- # strict means "Require branches to be up to date before merging."
- strict: true
-
- required_pull_request_reviews:
- dismiss_stale_reviews: true
- required_approving_review_count: 1
+ protected_branches:
+ main:
+ required_status_checks:
+ # strict means "Require branches to be up to date before merging."
+ strict: true
+ required_pull_request_reviews:
+ dismiss_stale_reviews: true
+ equired_approving_review_count: 1
+
+ # squash or rebase must be allowed in the repo for this setting to be set to true.
+ required_linear_history: false
+
+ required_signatures: false
+
+ # requires all conversations to be resolved before merging is possible
+ required_conversation_resolution: false
+
dependabot_alerts: true
dependabot_updates: false
From bfb9f96823256a865d3268e5b542f051e49a4b91 Mon Sep 17 00:00:00 2001
From: Lee Rhodes
Date: Thu, 20 Feb 2025 16:13:19 -0800
Subject: [PATCH 72/88] change dismiss state reviews to false.
---
.asf.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.asf.yaml b/.asf.yaml
index 5628899f8..f7627bc08 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -11,7 +11,7 @@ github:
strict: true
required_pull_request_reviews:
- dismiss_stale_reviews: true
+ dismiss_stale_reviews: false
equired_approving_review_count: 1
# squash or rebase must be allowed in the repo for this setting to be set to true.
From 42a8a2686f8e86087862a813b7600cf81310095f Mon Sep 17 00:00:00 2001
From: jmalkin <786705+jmalkin@users.noreply.github.com>
Date: Fri, 21 Feb 2025 10:33:21 -0800
Subject: [PATCH 73/88] Fix a few typos in BloomFilter javadocs
---
.../filters/bloomfilter/BloomFilter.java | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilter.java b/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilter.java
index 171fc2cfb..7c166a29d 100644
--- a/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilter.java
+++ b/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilter.java
@@ -381,7 +381,7 @@ private void updateInternal(final long h0, final long h1) {
/**
* Updates the filter with the provided long and
- * returns the result from quering that value prior to the update.
+ * returns the result from querying that value prior to the update.
* @param item an item with which to update the filter
* @return The query result prior to applying the update
*/
@@ -393,7 +393,7 @@ public boolean queryAndUpdate(final long item) {
/**
* Updates the filter with the provided double and
- * returns the result from quering that value prior to the update.
+ * returns the result from querying that value prior to the update.
* The double is canonicalized (NaN and +/- infinity) in the call.
* @param item an item with which to update the filter
* @return The query result prior to applying the update
@@ -408,7 +408,7 @@ public boolean queryAndUpdate(final double item) {
/**
* Updates the filter with the provided String and
- * returns the result from quering that value prior to the update.
+ * returns the result from querying that value prior to the update.
* The string is converted to a byte array using UTF8 encoding.
*
* Note: this will not produce the same output hash values as the {@link #queryAndUpdate(char[])}
@@ -428,7 +428,7 @@ public boolean queryAndUpdate(final String item) {
/**
* Updates the filter with the provided byte[] and
- * returns the result from quering that array prior to the update.
+ * returns the result from querying that array prior to the update.
* @param data an array with which to update the filter
* @return The query result prior to applying the update, or false if data is null
*/
@@ -440,7 +440,7 @@ public boolean queryAndUpdate(final byte[] data) {
/**
* Updates the filter with the provided char[] and
- * returns the result from quering that array prior to the update.
+ * returns the result from querying that array prior to the update.
* @param data an array with which to update the filter
* @return The query result prior to applying the update, or false if data is null
*/
@@ -453,7 +453,7 @@ public boolean queryAndUpdate(final char[] data) {
/**
* Updates the filter with the provided short[] and
- * returns the result from quering that array prior to the update.
+ * returns the result from querying that array prior to the update.
* @param data an array with which to update the filter
* @return The query result prior to applying the update, or false if data is null
*/
@@ -466,7 +466,7 @@ public boolean queryAndUpdate(final short[] data) {
/**
* Updates the filter with the provided int[] and
- * returns the result from quering that array prior to the update.
+ * returns the result from querying that array prior to the update.
* @param data an array with which to update the filter
* @return The query result prior to applying the update, or false if data is null
*/
@@ -479,7 +479,7 @@ public boolean queryAndUpdate(final int[] data) {
/**
* Updates the filter with the provided long[] and
- * returns the result from quering that array prior to the update.
+ * returns the result from querying that array prior to the update.
* @param data an array with which to update the filter
* @return The query result prior to applying the update, or false if data is null
*/
@@ -492,7 +492,7 @@ public boolean queryAndUpdate(final long[] data) {
/**
* Updates the filter with the provided Memory and
- * returns the result from quering that Memory prior to the update.
+ * returns the result from querying that Memory prior to the update.
* @param mem an array with which to update the filter
* @return The query result prior to applying the update, or false if mem is null
*/
@@ -762,7 +762,7 @@ public static long getSerializedSize(final long numBits) {
* 3 ||---------------------------------NumBitsSet------------------------------------|
*
*
- * The raw BitArray bits, if non-empty start at byte 24.
+ * The raw BitArray bits, if non-empty, start at byte 32.
*/
/**
From feef1fafb0e42a5726b63090cf5fb687f63e0be8 Mon Sep 17 00:00:00 2001
From: Lee Rhodes Only "Direct" Serialization Version 3 (i.e, OpenSource) sketches that have + * been explicitly stored as direct sketches can be wrapped. + * Wrapping earlier serial version sketches will result in a heapify operation. + * These early versions were never designed to "wrap".
+ * + *Wrapping any subclass of this class that is empty or contains only a single item will + * result in heapified forms of empty and single item sketch respectively. + * This is actually faster and consumes less overall memory.
+ * + *This method checks if the DEFAULT_UPDATE_SEED was used to create the source Memory image. + * Note that SerialVersion 1 sketches cannot be checked as they don't have a seedHash field, + * so the resulting heapified CompactSketch will be given the hash of DEFAULT_UPDATE_SEED.
+ * + * @param bytes a byte array image of a Sketch that was created using the DEFAULT_UPDATE_SEED. + * See Memory + * + * @return a CompactSketch backed by the given Memory except as above. + */ public static CompactSketch wrap(final byte[] bytes) { return wrap(bytes, ThetaUtil.DEFAULT_UPDATE_SEED, false); } - + + /** + * Wrap takes the sketch image in the given Memory and refers to it directly. + * There is no data copying onto the java heap. + * The wrap operation enables fast read-only merging and access to all the public read-only API. + * + *Only "Direct" Serialization Version 3 (i.e, OpenSource) sketches that have + * been explicitly stored as direct sketches can be wrapped. + * Wrapping earlier serial version sketches will result in a heapify operation. + * These early versions were never designed to "wrap".
+ * + *Wrapping any subclass of this class that is empty or contains only a single item will + * result in heapified forms of empty and single item sketch respectively. + * This is actually faster and consumes less overall memory.
+ * + *This method checks if the given expectedSeed was used to create the source Memory image. + * Note that SerialVersion 1 sketches cannot be checked as they don't have a seedHash field, + * so the resulting heapified CompactSketch will be given the hash of the expectedSeed.
+ * + * @param bytes a byte array image of a Sketch that was created using the given expectedSeed. + * See Memory + * @param expectedSeed the seed used to validate the given Memory image. + * See Update Hash Seed. + * @return a CompactSketch backed by the given Memory except as above. + */ public static CompactSketch wrap(final byte[] bytes, final long expectedSeed) { return wrap(bytes, expectedSeed, true); } - + private static CompactSketch wrap(final byte[] bytes, final long seed, final boolean enforceSeed) { final int serVer = bytes[PreambleUtil.SER_VER_BYTE]; final int familyId = bytes[PreambleUtil.FAMILY_BYTE]; diff --git a/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java b/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java index 6c83add87..64c0fafd4 100644 --- a/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java +++ b/src/main/java/org/apache/datasketches/theta/DirectCompactCompressedSketch.java @@ -82,7 +82,7 @@ public int getCurrentBytes() { private static final int START_PACKED_DATA_EXACT_MODE = 8; private static final int START_PACKED_DATA_ESTIMATION_MODE = 16; - + @Override public int getRetainedEntries(final boolean valid) { //compact is always valid // number of entries is stored using variable length encoding @@ -132,7 +132,7 @@ long[] getCache() { final int numEntries = getRetainedEntries(); final long[] cache = new long[numEntries]; int i = 0; - HashIterator it = iterator(); + final HashIterator it = iterator(); while (it.next()) { cache[i++] = it.get(); } diff --git a/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java b/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java index b1be73c74..772480fea 100644 --- a/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java +++ b/src/main/java/org/apache/datasketches/theta/IntersectionImpl.java @@ -504,13 +504,13 @@ private void moveDataToTgt(final long[] arr, final int count) { } private void moveDataToTgt(final Sketch sketch) { - int count = sketch.getRetainedEntries(); + final int count = sketch.getRetainedEntries(); int tmpCnt = 0; if (wmem_ != null) { //Off Heap puts directly into mem final int preBytes = CONST_PREAMBLE_LONGS << 3; final int lgArrLongs = lgArrLongs_; final long thetaLong = thetaLong_; - HashIterator it = sketch.iterator(); + final HashIterator it = sketch.iterator(); while (it.next()) { final long hash = it.get(); if (continueCondition(thetaLong, hash)) { continue; } @@ -518,7 +518,7 @@ private void moveDataToTgt(final Sketch sketch) { tmpCnt++; } } else { //On Heap. Assumes HT exists and is large enough - HashIterator it = sketch.iterator(); + final HashIterator it = sketch.iterator(); while (it.next()) { final long hash = it.get(); if (continueCondition(thetaLong_, hash)) { continue; } diff --git a/src/main/java/org/apache/datasketches/theta/Sketch.java b/src/main/java/org/apache/datasketches/theta/Sketch.java index 6583e2dbf..cb202a189 100644 --- a/src/main/java/org/apache/datasketches/theta/Sketch.java +++ b/src/main/java/org/apache/datasketches/theta/Sketch.java @@ -472,7 +472,7 @@ public String toString(final boolean sketchSummary, final boolean dataDetail, fi final int w = width > 0 ? width : 8; // default is 8 wide if (curCount > 0) { sb.append("### SKETCH DATA DETAIL"); - HashIterator it = iterator(); + final HashIterator it = iterator(); int j = 0; while (it.next()) { final long h = it.get(); diff --git a/src/main/java/org/apache/datasketches/theta/WrappedCompactSketch.java b/src/main/java/org/apache/datasketches/theta/WrappedCompactSketch.java index b1073159b..519857d21 100644 --- a/src/main/java/org/apache/datasketches/theta/WrappedCompactSketch.java +++ b/src/main/java/org/apache/datasketches/theta/WrappedCompactSketch.java @@ -136,7 +136,7 @@ public byte[] toByteArray() { long[] getCache() { final long[] cache = new long[getRetainedEntries()]; int i = 0; - HashIterator it = iterator(); + final HashIterator it = iterator(); while (it.next()) { cache[i++] = it.get(); } diff --git a/src/test/java/org/apache/datasketches/hll/SizeAndModeTransitions.java b/src/test/java/org/apache/datasketches/hll/SizeAndModeTransitions.java index ad7a4e509..c9ffa1e28 100644 --- a/src/test/java/org/apache/datasketches/hll/SizeAndModeTransitions.java +++ b/src/test/java/org/apache/datasketches/hll/SizeAndModeTransitions.java @@ -45,7 +45,6 @@ public void checkHLL8Heap() { } else { sk = new HllSketch(lgK, tgtHllType); } - String type = tgtHllType.toString(); String store = direct ? "Memory" : "Heap"; for (int i = 1; i <= N; i++) { sk.update(i); From f776ff0522b881498436030acdde883e5fe08eed Mon Sep 17 00:00:00 2001 From: Lee Rhodes