You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by le...@apache.org on 2021/10/18 19:59:32 UTC
[datasketches-java] 03/03: This fixes Mikhail's Bug:
datasketches-java Issue #368.
This is an automated email from the ASF dual-hosted git repository.
leerho pushed a commit to branch FixMikhailsBug
in repository https://gitbox.apache.org/repos/asf/datasketches-java.git
commit c89e0711418666801f4dcc5c39924ad656d97e5f
Author: Lee Rhodes <le...@users.noreply.github.com>
AuthorDate: Mon Oct 18 15:59:04 2021 -0400
This fixes Mikhail's Bug: datasketches-java Issue #368.
In addition to the issue that Mikhail found, I found a number of other
discrepancies in the treatment of various corner cases in the Set
Operations. Those were also fixed.
---
.../org/apache/datasketches/theta/AnotBimpl.java | 13 +-
.../java/org/apache/datasketches/tuple/AnotB.java | 107 +++-
.../apache/datasketches/tuple/Intersection.java | 22 +-
.../datasketches/tuple/QuickSelectSketch.java | 3 +-
.../theta/CornerCaseThetaSetOperationsTest.java | 679 +++++++++++++++++++++
.../CornerCaseTupleSetOperationsTest.java | 659 ++++++++++++++++++++
6 files changed, 1449 insertions(+), 34 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/theta/AnotBimpl.java b/src/main/java/org/apache/datasketches/theta/AnotBimpl.java
index 35e3241..6f8828e 100644
--- a/src/main/java/org/apache/datasketches/theta/AnotBimpl.java
+++ b/src/main/java/org/apache/datasketches/theta/AnotBimpl.java
@@ -78,6 +78,7 @@ final class AnotBimpl extends AnotB {
//process A
hashArr_ = getHashArrA(skA);
+ hashArr_ = (hashArr_ == null) ? new long[0] : hashArr_;
empty_ = false;
thetaLong_ = skA.getThetaLong();
curCount_ = hashArr_.length;
@@ -93,6 +94,7 @@ final class AnotBimpl extends AnotB {
//process B
hashArr_ = getResultHashArr(thetaLong_, curCount_, hashArr_, skB);
+ hashArr_ = (hashArr_ == null) ? new long[0] : hashArr_;
curCount_ = hashArr_.length;
empty_ = curCount_ == 0 && thetaLong_ == Long.MAX_VALUE;
}
@@ -119,17 +121,22 @@ final class AnotBimpl extends AnotB {
}
//Both skA & skB are not null
+ final long minThetaLong = Math.min(skA.getThetaLong(), skB.getThetaLong());
+
if (skA.isEmpty()) { return skA.compact(dstOrdered, dstMem); }
+ //A is not Empty
checkSeedHashes(skA.getSeedHash(), seedHash_);
- if (skB.isEmpty()) { return skA.compact(dstOrdered, dstMem); }
+ if (skB.isEmpty() && skB.getRetainedEntries() == 0) {
+ return skA.compact(dstOrdered, dstMem);
+ }
checkSeedHashes(skB.getSeedHash(), seedHash_);
//Both skA & skB are not empty
//process A
final long[] hashArrA = getHashArrA(skA);
- final int countA = hashArrA.length;
- final long minThetaLong = Math.min(skA.getThetaLong(), skB.getThetaLong());
+ final int countA = (hashArrA == null) ? 0 : hashArrA.length;
+
//process B
final long[] hashArrOut = getResultHashArr(minThetaLong, countA, hashArrA, skB); //out is clone
diff --git a/src/main/java/org/apache/datasketches/tuple/AnotB.java b/src/main/java/org/apache/datasketches/tuple/AnotB.java
index 5dadfdf..2b5de6c 100644
--- a/src/main/java/org/apache/datasketches/tuple/AnotB.java
+++ b/src/main/java/org/apache/datasketches/tuple/AnotB.java
@@ -37,7 +37,7 @@ import org.apache.datasketches.SketchesStateException;
*
* <p>The stateful operation is as follows:</p>
* <pre><code>
- * AnotB anotb = SetOperationBuilder.buildAnotB();
+ * AnotB anotb = new AnotB();
*
* anotb.setA(Sketch skA); //The first argument.
* anotb.notB(Sketch skB); //The second (subtraction) argument.
@@ -49,7 +49,7 @@ import org.apache.datasketches.SketchesStateException;
*
* <p>The stateless operation is as follows:</p>
* <pre><code>
- * AnotB anotb = SetOperationBuilder.buildAnotB();
+ * AnotB anotb = new AnotB();
*
* CompactSketch csk = anotb.aNotB(Sketch skA, Sketch skB);
* </code></pre>
@@ -95,10 +95,10 @@ public final class AnotB<S extends Summary> {
* With a null as the first argument, we cannot know what the user's intent is.
* Since it is very likely that a <i>null</i> is a programming error, we throw a an exception.</p>
*
- * <p>An enpty input argument will set the internal state to empty.</p>
+ * <p>An empty input argument will set the internal state to empty.</p>
*
* <p>Rationale: An empty set is a mathematically legal concept. Although it makes any subsequent,
- * valid argument for B irrelvant, we must allow this and assume the user knows what they are
+ * valid argument for B irrelevant, we must allow this and assume the user knows what they are
* doing.</p>
*
* <p>Performing {@link #getResult(boolean)} just after this step will return a compact form of
@@ -106,6 +106,7 @@ public final class AnotB<S extends Summary> {
*
* @param skA The incoming sketch for the first argument, <i>A</i>.
*/
+ @SuppressWarnings("unchecked")
public void setA(final Sketch<S> skA) {
if (skA == null) {
reset();
@@ -116,14 +117,23 @@ public final class AnotB<S extends Summary> {
return;
}
//skA is not empty
- empty_ = false;
- thetaLong_ = skA.getThetaLong();
//process A
+ empty_ = false;
+ thetaLong_ = skA.getThetaLong();
final DataArrays<S> da = getDataArraysA(skA);
+
hashArr_ = da.hashArr;
- summaryArr_ = da.summaryArr;
+ hashArr_ = (hashArr_ == null) ? new long[0] : hashArr_;
curCount_ = hashArr_.length;
+
+ summaryArr_ = da.summaryArr;
+ if (summaryArr_ == null) {
+ final SummaryFactory<S> sumFact = ((QuickSelectSketch<S>)skA).getSummaryFactory();
+ final S summary = sumFact.newSummary();
+ final Class<S> summaryType = (Class<S>)summary.getClass();
+ summaryArr_ = (S[]) Array.newInstance(summaryType, 0);
+ }
}
/**
@@ -133,7 +143,7 @@ public final class AnotB<S extends Summary> {
*
* <p>An input argument of null or empty is ignored.</p>
*
- * <p>Rationale: A <i>null</i> for the second or following arguments is more tollerable because
+ * <p>Rationale: A <i>null</i> for the second or following arguments is more tolerable because
* <i>A NOT null</i> is still <i>A</i> even if we don't know exactly what the null represents. It
* clearly does not have any content that overlaps with <i>A</i>. Also, because this can be part of
* a multistep operation with multiple <i>notB</i> steps. Other following steps can still produce
@@ -143,18 +153,28 @@ public final class AnotB<S extends Summary> {
*
* @param skB The incoming Tuple sketch for the second (or following) argument <i>B</i>.
*/
+ @SuppressWarnings("unchecked")
public void notB(final Sketch<S> skB) {
- if (empty_ || skB == null || skB.isEmpty() || hashArr_ == null) { return; }
+ if (empty_ || skB == null || skB.isEmpty()) { return; }
//skB is not empty
final long thetaLongB = skB.getThetaLong();
thetaLong_ = Math.min(thetaLong_, thetaLongB);
//process B
final DataArrays<S> daB = getResultArraysTuple(thetaLong_, curCount_, hashArr_, summaryArr_, skB);
+
hashArr_ = daB.hashArr;
+ hashArr_ = (hashArr_ == null) ? new long[0] : hashArr_;
+ curCount_ = hashArr_.length;
+
summaryArr_ = daB.summaryArr;
+ if (summaryArr_ == null) {
+ final SummaryFactory<S> sumFact = ((QuickSelectSketch<S>)skB).getSummaryFactory();
+ final S summary = sumFact.newSummary();
+ final Class<S> summaryType = (Class<S>)summary.getClass();
+ summaryArr_ = (S[]) Array.newInstance(summaryType, 0);
+ }
- curCount_ = hashArr_.length;
empty_ = curCount_ == 0 && thetaLong_ == Long.MAX_VALUE;
}
@@ -167,7 +187,7 @@ public final class AnotB<S extends Summary> {
*
* <p>An input argument of null or empty is ignored.</p>
*
- * <p>Rationale: A <i>null</i> for the second or following arguments is more tollerable because
+ * <p>Rationale: A <i>null</i> for the second or following arguments is more tolerable because
* <i>A NOT null</i> is still <i>A</i> even if we don't know exactly what the null represents. It
* clearly does not have any content that overlaps with <i>A</i>. Also, because this can be part of
* a multistep operation with multiple <i>notB</i> steps. Other following steps can still produce
@@ -185,15 +205,18 @@ public final class AnotB<S extends Summary> {
//process B
final DataArrays<S> daB = getResultArraysTheta(thetaLong_, curCount_, hashArr_, summaryArr_, skB);
+
hashArr_ = daB.hashArr;
- summaryArr_ = daB.summaryArr;
+ hashArr_ = (hashArr_ == null) ? new long[0] : hashArr_;
+ curCount_ = hashArr_.length;
+ summaryArr_ = daB.summaryArr;
curCount_ = hashArr_.length;
empty_ = curCount_ == 0 && thetaLong_ == Long.MAX_VALUE;
}
/**
- * Gets the result of the mutistep, stateful operation AnotB that have been executed with calls
+ * Gets the result of the multistep, stateful operation AnotB that have been executed with calls
* to {@link #setA(Sketch)} and ({@link #notB(Sketch)} or
* {@link #notB(org.apache.datasketches.theta.Sketch)}).
*
@@ -235,25 +258,40 @@ public final class AnotB<S extends Summary> {
* @param <S> Type of Summary
* @return the result as an unordered {@link CompactSketch}
*/
+ @SuppressWarnings("unchecked")
public static <S extends Summary>
CompactSketch<S> aNotB(final Sketch<S> skA, final Sketch<S> skB) {
if (skA == null || skB == null) {
throw new SketchesArgumentException("Neither argument may be null");
}
- if (skA.getRetainedEntries() == 0) { return skA.compact(); }
- if (skB.getRetainedEntries() == 0) { return skA.compact(); }
- //Both skA & skB are not empty
+ //Both skA & skB are not null
+
+ final long minThetaLong = Math.min(skA.getThetaLong(), skB.getThetaLong());
+
+ if (skA.isEmpty()) { return skA.compact(); }
+ if (skB.isEmpty() && skB.getRetainedEntries() == 0) { return skA.compact(); }
+ //Both skA & skB are not empty, and skB has valid entries
//Process A
final DataArrays<S> da = getDataArraysA(skA);
- final long[] hashArrA = da.hashArr;
- final S[] summaryArrA = da.summaryArr;
+ long[] hashArrA = da.hashArr;
+ hashArrA = (hashArrA == null) ? new long[0] : hashArrA;
final int countA = hashArrA.length;
+ S[] summaryArrA = da.summaryArr;
+ if (summaryArrA == null) {
+ final SummaryFactory<S> sumFact = ((QuickSelectSketch<S>)skA).getSummaryFactory();
+ final S summary = sumFact.newSummary();
+ final Class<S> summaryType = (Class<S>)summary.getClass();
+ summaryArrA = (S[]) Array.newInstance(summaryType, 0);
+ }
+
+ if (countA == 0) {
+ return new CompactSketch<S>(new long[0], summaryArrA, minThetaLong, false);
+ }
+
//Process B
- final long minThetaLong = Math.min(skA.getThetaLong(), skB.getThetaLong());
final DataArrays<S> daB = getResultArraysTuple(minThetaLong, countA, hashArrA, summaryArrA, skB);
-
final long[] hashArr = daB.hashArr;
final S[] summaryArr = daB.summaryArr;
final int curCountOut = hashArr.length;
@@ -287,6 +325,7 @@ public final class AnotB<S extends Summary> {
* @param <S> Type of Summary
* @return the result as an unordered {@link CompactSketch}
*/
+ @SuppressWarnings("unchecked")
public static <S extends Summary>
CompactSketch<S> aNotB(final Sketch<S> skA, final org.apache.datasketches.theta.Sketch skB) {
if (skA == null || skB == null) {
@@ -294,19 +333,33 @@ public final class AnotB<S extends Summary> {
}
//Both skA & skB are not null
- if (skA.getRetainedEntries() == 0) { return skA.compact(); }
- if (skB.getRetainedEntries() == 0) { return skA.compact(); }
- //Both skA & skB have valid retained entries, and are not empty
+ final long minThetaLong = Math.min(skA.getThetaLong(), skB.getThetaLong());
+
+ if (skA.isEmpty()) { return skA.compact(); }
+ if (skB.isEmpty() && skB.getRetainedEntries() == 0) { return skA.compact(); }
+ //Both skA & skB are not empty, and skB has valid entries
+
//Process A
final DataArrays<S> da = getDataArraysA(skA);
- final long[] hashArrA = da.hashArr;
- final S[] summaryArrA = da.summaryArr;
+ long[] hashArrA = da.hashArr;
+ hashArrA = (hashArrA == null) ? new long[0] : hashArrA;
final int countA = hashArrA.length;
+ S[] summaryArrA = da.summaryArr;
+ if (summaryArrA == null) {
+ final SummaryFactory<S> sumFact = ((QuickSelectSketch<S>)skA).getSummaryFactory();
+ final S summary = sumFact.newSummary();
+ final Class<S> summaryType = (Class<S>)summary.getClass();
+ summaryArrA = (S[]) Array.newInstance(summaryType, 0);
+ }
+
+ if (countA == 0) {
+ return new CompactSketch<S>(new long[0], summaryArrA, minThetaLong, false);
+ }
+
//Process B
- final long minThetaLong = Math.min(skA.getThetaLong(), skB.getThetaLong());
- final DataArrays<S> daB = getResultArraysTheta(minThetaLong, countA, hashArrA, summaryArrA, skB);
+ final DataArrays<S> daB = getResultArraysTheta(minThetaLong, countA, hashArrA, summaryArrA, skB);
final long[] hashArr = daB.hashArr;
final S[] summaryArr = daB.summaryArr;
final int countOut = hashArr.length;
diff --git a/src/main/java/org/apache/datasketches/tuple/Intersection.java b/src/main/java/org/apache/datasketches/tuple/Intersection.java
index 9494580..8c047a9 100644
--- a/src/main/java/org/apache/datasketches/tuple/Intersection.java
+++ b/src/main/java/org/apache/datasketches/tuple/Intersection.java
@@ -107,14 +107,19 @@ public class Intersection<S extends Summary> {
if (tupleSketch == null) { throw new SketchesArgumentException("Sketch must not be null"); }
final boolean firstCall = firstCall_;
firstCall_ = false;
+ final boolean emptyIn = tupleSketch.isEmpty();
+ if (empty_ || emptyIn) { //empty rule
+ //Because of the definition of null above and the Empty Rule (which is OR), empty_ must be true.
+ //Whatever the current internal state, we make our local empty.
+ resetToEmpty();
+ return;
+ }
// input sketch could be first or next call
final long thetaLongIn = tupleSketch.getThetaLong();
final int countIn = tupleSketch.getRetainedEntries();
thetaLong_ = min(thetaLong_, thetaLongIn); //Theta rule
- // Empty rule extended in case incoming sketch does not have empty bit properly set
- final boolean emptyIn = countIn == 0 && thetaLongIn == Long.MAX_VALUE;
- empty_ |= emptyIn; //empty rule
+
if (countIn == 0) {
hashTables_.clear();
return;
@@ -274,12 +279,23 @@ public class Intersection<S extends Summary> {
* Resets the internal set to the initial state, which represents the Universal Set
*/
public void reset() {
+ hardReset();
+ }
+
+ private void hardReset() {
empty_ = false;
thetaLong_ = Long.MAX_VALUE;
hashTables_.clear();
firstCall_ = true;
}
+ private void resetToEmpty() {
+ empty_ = true;
+ thetaLong_ = Long.MAX_VALUE;
+ hashTables_.clear();
+ firstCall_ = false;
+ }
+
static int getLgTableSize(final int count) {
final int tableSize = max(ceilingPowerOf2((int) ceil(count / 0.75)), 1 << MIN_LG_NOM_LONGS);
return Integer.numberOfTrailingZeros(tableSize);
diff --git a/src/main/java/org/apache/datasketches/tuple/QuickSelectSketch.java b/src/main/java/org/apache/datasketches/tuple/QuickSelectSketch.java
index fd56b06..f80d6e9 100644
--- a/src/main/java/org/apache/datasketches/tuple/QuickSelectSketch.java
+++ b/src/main/java/org/apache/datasketches/tuple/QuickSelectSketch.java
@@ -292,7 +292,8 @@ class QuickSelectSketch<S extends Summary> extends Sketch<S> {
@SuppressWarnings("unchecked")
public CompactSketch<S> compact() {
if (getRetainedEntries() == 0) {
- return new CompactSketch<>(null, null, thetaLong_, empty_);
+ if (empty_) { return new CompactSketch<>(null, null, Long.MAX_VALUE, true); }
+ return new CompactSketch<>(null, null, thetaLong_, false);
}
final long[] hashArr = new long[getRetainedEntries()];
final S[] summaryArr = (S[])
diff --git a/src/test/java/org/apache/datasketches/theta/CornerCaseThetaSetOperationsTest.java b/src/test/java/org/apache/datasketches/theta/CornerCaseThetaSetOperationsTest.java
new file mode 100644
index 0000000..6a09c88
--- /dev/null
+++ b/src/test/java/org/apache/datasketches/theta/CornerCaseThetaSetOperationsTest.java
@@ -0,0 +1,679 @@
+/*
+ * 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.Util.DEFAULT_UPDATE_SEED;
+import static org.apache.datasketches.hash.MurmurHash3.hash;
+
+import org.testng.annotations.Test;
+
+public class CornerCaseThetaSetOperationsTest {
+
+ /* Hash Values
+ * 9223372036854775807 Theta = 1.0
+ *
+ * 6730918654704304314 hash(3L)[0] >>> 1 GT_MIDP
+ * 4611686018427387904 Theta for p = 0.5f = MIDP
+ * 2206043092153046979 hash(2L)[0] >>> 1 LT_MIDP_V
+ * 1498732507761423037 hash(5L)[0] >>> 1 LTLT_MIDP_V
+ *
+ * 1206007004353599230 hash(6L)[0] >>> 1 GT_LOWP_V
+ * 922337217429372928 Theta for p = 0.1f = LOWP
+ * 593872385995628096 hash(4L)[0] >>> 1 LT_LOWP_V
+ * 405753591161026837 hash(1L)[0] >>> 1 LTLT_LOWP_V
+
+ */
+ //private static final long
+
+ private static final long GT_MIDP_V = 3L;
+ private static final float MIDP = 0.5f;
+ private static final long LT_MIDP_V = 2L;
+ //private static final long LTLT_MIDP_V = 5L;
+
+ private static final long GT_LOWP_V = 6L;
+ private static final float LOWP = 0.1f;
+ private static final long LT_LOWP_V = 4L;
+ //private static final long VALUE_1 = 1L;
+
+
+ private static final double MIDP_THETA = MIDP;
+ private static final double LOWP_THETA = LOWP;
+
+
+ enum SkType {
+ NEW, //{ 1.0, 0, T} Bin: 101 Oct: 05
+ EXACT, //{ 1.0, >0, F} Bin: 111 Oct: 07, specify only value
+ ESTIMATION, //{<1.0, >0, F} Bin: 010 Oct: 02, specify only value
+ NEW_DEGEN, //{<1.0, 0, T} Bin: 001 Oct: 01, specify only p
+ RESULT_DEGEN //{<1.0, 0, F} Bin: 000 Oct: 0, specify p, value
+ }
+
+ //NOTE: 0 values in getSketch are not used.
+
+ @Test
+ public void newNew() {
+ UpdateSketch ska = getSketch(SkType.NEW, 0, 0);
+ UpdateSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+
+ }
+
+ @Test
+ public void newExact() {
+ UpdateSketch ska = getSketch(SkType.NEW, 0, 0);
+ UpdateSketch skb = getSketch(SkType.EXACT, 0, GT_MIDP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newNewDegen() {
+ UpdateSketch ska = getSketch(SkType.NEW, 0, 0);
+ UpdateSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newResultDegen() {
+ UpdateSketch ska = getSketch(SkType.NEW, 0, 0);
+ UpdateSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newNewEstimation() {
+ UpdateSketch ska = getSketch(SkType.NEW, 0, 0);
+ UpdateSketch skb = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ /*********************/
+
+ @Test
+ public void exactNew() {
+ UpdateSketch ska = getSketch(SkType.EXACT, 0, GT_MIDP_V);
+ UpdateSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 1, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 1, false);
+ }
+
+ @Test
+ public void exactExact() {
+ UpdateSketch ska = getSketch(SkType.EXACT, 0, GT_MIDP_V);
+ UpdateSketch skb = getSketch(SkType.EXACT, 0, GT_MIDP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 1, false);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void exactNewDegen() {
+ UpdateSketch ska = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+ UpdateSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 1, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 1, false);
+ }
+
+ @Test
+ public void exactResultDegen() {
+ UpdateSketch ska = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+ UpdateSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V); //entries = 0
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 1, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 1, false);
+ }
+
+ @Test
+ public void exactEstimation() {
+ UpdateSketch ska = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+ UpdateSketch skb = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 1, false);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 0, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 0, false);
+ }
+
+ /*********************/
+
+ @Test
+ public void estimationNew() {
+ UpdateSketch ska = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+ UpdateSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 1, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 1, false);
+ }
+
+ @Test
+ public void estimationExact() {
+ UpdateSketch ska = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+ UpdateSketch skb = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 1, false);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 0, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 0, false);
+ }
+
+ @Test
+ public void estimationNewDegen() {
+ UpdateSketch ska = getSketch(SkType.ESTIMATION, MIDP, LT_MIDP_V);
+ UpdateSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, MIDP_THETA, 1, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, MIDP_THETA, 1, false);
+ }
+
+ @Test
+ public void estimationResultDegen() {
+ UpdateSketch ska = getSketch(SkType.ESTIMATION, MIDP, LT_LOWP_V);
+ UpdateSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 1, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 1, false);
+ }
+
+ @Test
+ public void estimationEstimation() {
+ UpdateSketch ska = getSketch(SkType.ESTIMATION, MIDP, LT_LOWP_V);
+ UpdateSketch skb = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 1, false);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 0, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 0, false);
+ }
+
+ /*********************/
+
+ @Test
+ public void newDegenNew() {
+ UpdateSketch ska = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+ UpdateSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newDegenExact() {
+ UpdateSketch ska = getSketch(SkType.NEW_DEGEN, LOWP,0);
+ UpdateSketch skb = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newDegenNewDegen() {
+ UpdateSketch ska = getSketch(SkType.NEW_DEGEN, MIDP, 0);
+ UpdateSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newDegenResultDegen() {
+ UpdateSketch ska = getSketch(SkType.NEW_DEGEN, MIDP, 0);
+ UpdateSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newDegenEstimation() {
+ UpdateSketch ska = getSketch(SkType.NEW_DEGEN, MIDP, 0);
+ UpdateSketch skb = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, 1.0, 0, true);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, 1.0, 0, true);
+ }
+
+ /*********************/
+
+ @Test
+ public void resultDegenNew() {
+ UpdateSketch ska = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V); //entries = 0
+ UpdateSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 0, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 0, false);
+ }
+
+ @Test
+ public void resultDegenExact() {
+ UpdateSketch ska = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V); //entries = 0
+ UpdateSketch skb = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 0, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 0, false);
+ }
+
+ @Test
+ public void resultDegenNewDegen() {
+ UpdateSketch ska = getSketch(SkType.RESULT_DEGEN, MIDP, GT_MIDP_V); //entries = 0
+ UpdateSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, MIDP_THETA, 0, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, MIDP_THETA, 0, false);
+ }
+
+ @Test
+ public void resultDegenResultDegen() {
+ UpdateSketch ska = getSketch(SkType.RESULT_DEGEN, MIDP, GT_MIDP_V); //entries = 0
+ UpdateSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 0, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 0, false);
+ }
+
+ @Test
+ public void resultDegenEstimation() {
+ UpdateSketch ska = getSketch(SkType.RESULT_DEGEN, MIDP, GT_MIDP_V); //entries = 0
+ UpdateSketch skb = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless
+ Intersection inter = SetOperation.builder().buildIntersection();
+ CompactSketch csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ AnotB anotb = SetOperation.builder().buildANotB();
+ csk = anotb.aNotB(ska, skb);
+ checkResult("AnotB Stateless", csk, LOWP_THETA, 0, false);
+
+ //Stateful AnotB
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful", csk, LOWP_THETA, 0, false);
+ }
+
+ //=================================
+
+ private static void checkResult(String comment, CompactSketch sk, double theta, int entries, boolean empty) {
+ double skTheta = sk.getTheta();
+ int skEntries = sk.getRetainedEntries();
+ boolean skEmpty = sk.isEmpty();
+
+ boolean thetaOk = skTheta == theta;
+ boolean entriesOk = skEntries == entries;
+ boolean emptyOk = skEmpty == empty;
+ if (!thetaOk || !entriesOk || !emptyOk) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(comment + ": ");
+ if (!thetaOk) { sb.append("Got: " + skTheta + ", Expected: " + theta + "; "); }
+ if (!entriesOk) { sb.append("Got: " + skEntries + ", Expected: " + entries + "; "); }
+ if (!emptyOk) { sb.append("Got: " + skEmpty + ", Expected: " + empty + "."); }
+ throw new IllegalArgumentException(sb.toString());
+ }
+ }
+
+ private static UpdateSketch getSketch(SkType skType, float p, long value) {
+ UpdateSketchBuilder bldr = UpdateSketch.builder();
+ bldr.setLogNominalEntries(4);
+ UpdateSketch sk;
+ switch(skType) {
+ case NEW: { //{ 1.0, 0, T} Bin: 101 Oct: 05
+ sk = bldr.build();
+ break;
+ }
+ case EXACT: { //{ 1.0, >0, F} Bin: 111 Oct: 07
+ sk = bldr.build();
+ sk.update(value);
+ break;
+ }
+ case ESTIMATION: { //{<1.0, >0, F} Bin: 010 Oct: 02
+ bldr.setP(p);
+ sk = bldr.build();
+ sk.update(value);
+ break;
+ }
+ case NEW_DEGEN: { //{<1.0, 0, T} Bin: 001 Oct: 01
+ bldr.setP(p);
+ sk = bldr.build();
+ break;
+ }
+ case RESULT_DEGEN: { //{<1.0, 0, F} Bin: 000 Oct: 0
+ bldr.setP(p);
+ sk = bldr.build();
+ sk.update(value);
+ break;
+ }
+
+ default: { return null; } //should not happen
+ }
+ return sk;
+ }
+
+ private static void println(Object o) {
+ System.out.println(o.toString());
+ }
+
+ //@Test
+ public void printHash() {
+ long seed = DEFAULT_UPDATE_SEED;
+ long v = 6;
+ long hash = (hash(v, seed)[0]) >>> 1;
+ println(v + ", " + hash);
+ }
+
+ //@Test
+ public void printPAsLong() {
+ float p = 0.5f;
+ println("p = " + p + ", " + (long)(Long.MAX_VALUE * p));
+ }
+
+}
diff --git a/src/test/java/org/apache/datasketches/tuple/aninteger/CornerCaseTupleSetOperationsTest.java b/src/test/java/org/apache/datasketches/tuple/aninteger/CornerCaseTupleSetOperationsTest.java
new file mode 100644
index 0000000..4cfd2b6
--- /dev/null
+++ b/src/test/java/org/apache/datasketches/tuple/aninteger/CornerCaseTupleSetOperationsTest.java
@@ -0,0 +1,659 @@
+/*
+ * 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.tuple.aninteger;
+
+import org.apache.datasketches.tuple.AnotB;
+import org.apache.datasketches.tuple.CompactSketch;
+import org.apache.datasketches.tuple.Intersection;
+import org.testng.annotations.Test;
+
+public class CornerCaseTupleSetOperationsTest {
+
+ /* Hash Values
+ * 9223372036854775807 Theta = 1.0
+ *
+ * 6730918654704304314 hash(3L)[0] >>> 1 GT_MIDP
+ * 4611686018427387904 Theta for p = 0.5f = MIDP
+ * 2206043092153046979 hash(2L)[0] >>> 1 LT_MIDP_V
+ * 1498732507761423037 hash(5L)[0] >>> 1 LTLT_MIDP_V
+ *
+ * 1206007004353599230 hash(6L)[0] >>> 1 GT_LOWP_V
+ * 922337217429372928 Theta for p = 0.1f = LOWP
+ * 593872385995628096 hash(4L)[0] >>> 1 LT_LOWP_V
+ * 405753591161026837 hash(1L)[0] >>> 1 LTLT_LOWP_V
+
+ */
+ //private static final long
+
+ private static final long GT_MIDP_V = 3L;
+ private static final float MIDP = 0.5f;
+ private static final long LT_MIDP_V = 2L;
+ //private static final long LTLT_MIDP_V = 5L;
+
+ private static final long GT_LOWP_V = 6L;
+ private static final float LOWP = 0.1f;
+ private static final long LT_LOWP_V = 4L;
+ //private static final long VALUE_1 = 1L;
+
+
+ private static final double MIDP_THETA = MIDP;
+ private static final double LOWP_THETA = LOWP;
+
+ IntegerSummarySetOperations setOperations =
+ new IntegerSummarySetOperations(IntegerSummary.Mode.Min, IntegerSummary.Mode.Min);
+ Intersection<IntegerSummary> intersection = new Intersection<>(setOperations);
+
+ enum SkType {
+ NEW, //{ 1.0, 0, T} Bin: 101 Oct: 05
+ EXACT, //{ 1.0, >0, F} Bin: 111 Oct: 07, specify only value
+ ESTIMATION, //{<1.0, >0, F} Bin: 010 Oct: 02, specify only value
+ NEW_DEGEN, //{<1.0, 0, T} Bin: 001 Oct: 01, specify only p
+ RESULT_DEGEN //{<1.0, 0, F} Bin: 000 Oct: 0, specify p, value
+ }
+
+ //NOTE: 0 values in getSketch are not used.
+
+ @Test
+ public void newNew() {
+ IntegerSketch ska = getSketch(SkType.NEW, 0, 0);
+ IntegerSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newExact() {
+ IntegerSketch ska = getSketch(SkType.NEW, 0, 0);
+ IntegerSketch skb = getSketch(SkType.EXACT, 0, GT_MIDP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newNewDegen() {
+ IntegerSketch ska = getSketch(SkType.NEW, 0, 0);
+ IntegerSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newResultDegen() {
+ IntegerSketch ska = getSketch(SkType.NEW, 0, 0);
+ IntegerSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newNewEstimation() {
+ IntegerSketch ska = getSketch(SkType.NEW, 0, 0);
+ IntegerSketch skb = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ /*********************/
+
+ @Test
+ public void exactNew() {
+ IntegerSketch ska = getSketch(SkType.EXACT, 0, GT_MIDP_V);
+ IntegerSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 1, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 1, false);
+ }
+
+ @Test
+ public void exactExact() {
+ IntegerSketch ska = getSketch(SkType.EXACT, 0, GT_MIDP_V);
+ IntegerSketch skb = getSketch(SkType.EXACT, 0, GT_MIDP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 1, false);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void exactNewDegen() {
+ IntegerSketch ska = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+ IntegerSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 1, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 1, false);
+ }
+
+ @Test
+ public void exactResultDegen() { //AnotB: 1.0 != 0.10000000149011612;
+ IntegerSketch ska = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+ IntegerSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V); //entries = 0
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 1, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 1, false);
+ }
+
+ @Test
+ public void exactEstimation() {
+ IntegerSketch ska = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+ IntegerSketch skb = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 1, false);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+ }
+
+ /*********************/
+
+ @Test
+ public void estimationNew() {
+ IntegerSketch ska = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+ IntegerSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 1, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 1, false);
+ }
+
+ @Test
+ public void estimationExact() {
+ IntegerSketch ska = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+ IntegerSketch skb = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 1, false);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+ }
+
+ @Test
+ public void estimationNewDegen() {
+ IntegerSketch ska = getSketch(SkType.ESTIMATION, MIDP, LT_MIDP_V);
+ IntegerSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, MIDP_THETA, 1, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, MIDP_THETA, 1, false);
+ }
+
+ @Test
+ public void estimationResultDegen() {
+ IntegerSketch ska = getSketch(SkType.ESTIMATION, MIDP, LT_LOWP_V);
+ IntegerSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 1, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 1, false);
+ }
+
+ @Test
+ public void estimationEstimation() {
+ IntegerSketch ska = getSketch(SkType.ESTIMATION, MIDP, LT_LOWP_V);
+ IntegerSketch skb = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 1, false);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+ }
+
+ /*********************/
+
+ @Test
+ public void newDegenNew() {//AnotB: 0.10000000149011612 != 1.0;
+ IntegerSketch ska = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+ IntegerSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newDegenExact() { //AnotB: 0.10000000149011612 != 1.0;
+ IntegerSketch ska = getSketch(SkType.NEW_DEGEN, LOWP,0);
+ IntegerSketch skb = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newDegenNewDegen() { //AnotB: 0.10000000149011612 != 1.0;
+ IntegerSketch ska = getSketch(SkType.NEW_DEGEN, MIDP, 0);
+ IntegerSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newDegenResultDegen() { //AnotB: 0.10000000149011612 != 1.0;
+ IntegerSketch ska = getSketch(SkType.NEW_DEGEN, MIDP, 0);
+ IntegerSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP,GT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ @Test
+ public void newDegenEstimation() { //AnotB: 0.10000000149011612 != 1.0;
+ IntegerSketch ska = getSketch(SkType.NEW_DEGEN, MIDP, 0);
+ IntegerSketch skb =getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, 1.0, 0, true);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateful Tuple, Tuple", csk, 1.0, 0, true);
+ }
+
+ /*********************/
+
+ @Test
+ public void resultDegenNew() {
+ IntegerSketch ska = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V); //entries = 0
+ IntegerSketch skb = getSketch(SkType.NEW, 0, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+ }
+
+ @Test
+ public void resultDegenExact() {
+ IntegerSketch ska = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V); //entries = 0
+ IntegerSketch skb = getSketch(SkType.EXACT, 0, LT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+ }
+
+ @Test
+ public void resultDegenNewDegen() {
+ IntegerSketch ska = getSketch(SkType.RESULT_DEGEN, MIDP, GT_MIDP_V); //entries = 0
+ IntegerSketch skb = getSketch(SkType.NEW_DEGEN, LOWP, 0);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, 1.0, 0, true);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, MIDP_THETA, 0, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, MIDP_THETA, 0, false);
+ }
+
+ @Test
+ public void resultDegenResultDegen() { //AnotB NullPointerException
+ IntegerSketch ska = getSketch(SkType.RESULT_DEGEN, MIDP, GT_MIDP_V); //entries = 0
+ IntegerSketch skb = getSketch(SkType.RESULT_DEGEN, LOWP, GT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+ }
+
+ @Test
+ public void resultDegenEstimation() {
+ IntegerSketch ska = getSketch(SkType.RESULT_DEGEN, MIDP, GT_MIDP_V); //entries = 0
+ IntegerSketch skb = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
+
+ //Stateless Tuple, Tuple
+ Intersection<IntegerSummary> inter = new Intersection<>(setOperations);
+ CompactSketch<IntegerSummary> csk = inter.intersect(ska, skb);
+ checkResult("Intersect", csk, LOWP_THETA, 0, false);
+
+ csk = AnotB.aNotB(ska, skb);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+
+ //Stateful Tuple, Tuple
+ AnotB<IntegerSummary> anotb = new AnotB<>();
+ anotb.setA(ska);
+ anotb.notB(skb);
+ csk = anotb.getResult(true);
+ checkResult("AnotB Stateless Tuple, Tuple", csk, LOWP_THETA, 0, false);
+ }
+
+ //=================================
+
+ private static void checkResult(String comment, CompactSketch<IntegerSummary> sk, double theta, int entries, boolean empty) {
+ double skTheta = sk.getTheta();
+ int skEntries = sk.getRetainedEntries();
+ boolean skEmpty = sk.isEmpty();
+
+ boolean thetaOk = skTheta == theta;
+ boolean entriesOk = skEntries == entries;
+ boolean emptyOk = skEmpty == empty;
+ if (!thetaOk || !entriesOk || !emptyOk) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(comment + ": ");
+ if (!thetaOk) { sb.append("Got: " + skTheta + ", Expected: " + theta + "; "); }
+ if (!entriesOk) { sb.append("Got: " + skEntries + ", Expected: " + entries + "; "); }
+ if (!emptyOk) { sb.append("Got: " + skEmpty + ", Expected: " + empty + "."); }
+ throw new IllegalArgumentException(sb.toString());
+ }
+ }
+
+ private static IntegerSketch getSketch(SkType skType, float p, long value) {
+
+ IntegerSketch sk;
+ switch(skType) {
+ case NEW: { //{ 1.0, 0, T} Bin: 101 Oct: 05
+ sk = new IntegerSketch(4, 2, 1.0f, IntegerSummary.Mode.Min);
+ break;
+ }
+ case EXACT: { //{ 1.0, >0, F} Bin: 111 Oct: 07
+ sk = new IntegerSketch(4, 2, 1.0f, IntegerSummary.Mode.Min);
+ sk.update(value, 1);
+ break;
+ }
+ case ESTIMATION: { //{<1.0, >0, F} Bin: 010 Oct: 02
+ sk = new IntegerSketch(4, 2, p, IntegerSummary.Mode.Min);
+ sk.update(value, 1);
+ break;
+ }
+ case NEW_DEGEN: { //{<1.0, 0, T} Bin: 001 Oct: 01
+ sk = new IntegerSketch(4, 2, p, IntegerSummary.Mode.Min);
+ break;
+ }
+ case RESULT_DEGEN: { //{<1.0, 0, F} Bin: 000 Oct: 0
+ sk = new IntegerSketch(4, 2, p, IntegerSummary.Mode.Min);
+ sk.update(value, 1); // > theta
+ break;
+ }
+
+ default: { return null; } //should not happen
+ }
+ return sk;
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org