blob: 45feb7637ac233d7408489655aa3412303248ad6 [file] [log] [blame]
/*
* 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.kll;
import static org.apache.datasketches.kll.KllSketch.SketchType.DOUBLES_SKETCH;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.apache.datasketches.common.SketchesArgumentException;
import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.WritableMemory;
import org.apache.datasketches.quantilescommon.DoublesSortedView;
import org.apache.datasketches.quantilescommon.DoublesSortedViewIterator;
import org.testng.annotations.Test;
public class KllMiscDirectDoublesTest {
static final String LS = System.getProperty("line.separator");
private static final DefaultMemoryRequestServer memReqSvr = new DefaultMemoryRequestServer();
@Test
public void checkBounds() {
final KllDoublesSketch kll = getDirectDoublesSketch(200, 0);
for (int i = 0; i < 1000; i++) {
kll.update(i);
}
final double eps = kll.getNormalizedRankError(false);
final double est = kll.getQuantile(0.5);
final double ub = kll.getQuantileUpperBound(0.5);
final double lb = kll.getQuantileLowerBound(0.5);
assertEquals(ub, kll.getQuantile(.5 + eps));
assertEquals(lb, kll.getQuantile(0.5 - eps));
println("Ext : " + est);
println("UB : " + ub);
println("LB : " + lb);
final double rest = kll.getRank(est);
final double restUB = kll.getRankUpperBound(rest);
final double restLB = kll.getRankLowerBound(rest);
assertTrue(restUB - rest < (2 * eps));
assertTrue(rest - restLB < (2 * eps));
}
@Test
public void checkMisc() {
final int k = 8;
final KllDoublesSketch sk = getDirectDoublesSketch(k, 0);
try { sk.getPartitionBoundaries(10); fail(); } catch (SketchesArgumentException e) {}
for (int i = 0; i < 20; i++) { sk.update(i); }
final double[] items = sk.getDoubleItemsArray();
assertEquals(items.length, 16);
final int[] levels = sk.getLevelsArray(sk.sketchStructure);
assertEquals(levels.length, 3);
assertEquals(sk.getNumLevels(), 2);
}
//@Test //enable static println(..) for visual checking
public void visualCheckToString() {
final int k = 20;
final KllDoublesSketch sk = getDirectDoublesSketch(k, 0);
for (int i = 0; i < 10; i++) { sk.update(i + 1); }
println(sk.toString(true, true));
final KllDoublesSketch sk2 = getDirectDoublesSketch(k, 0);
for (int i = 0; i < 400; i++) { sk2.update(i + 1); }
println("\n" + sk2.toString(true, true));
sk2.merge(sk);
final String s2 = sk2.toString(true, true);
println(LS + s2);
}
@Test
public void viewDirectCompactions() {
int k = 20;
int u = 108;
KllDoublesSketch sk = getDirectDoublesSketch(k, 0);
for (int i = 1; i <= u; i++) {
sk.update(i);
if (sk.levelsArr[0] == 0) {
println(sk.toString(true, true));
sk.update(++i);
println(sk.toString(true, true));
assertEquals(sk.getDoubleItemsArray()[sk.levelsArr[0]], i);
}
}
}
@Test
public void viewCompactionAndSortedView() {
int k = 20;
KllDoublesSketch sk = getDirectDoublesSketch(k, 0);
show(sk, 20);
DoublesSortedView sv = sk.getSortedView();
DoublesSortedViewIterator itr = sv.iterator();
printf("%12s%12s\n", "Value", "CumWeight");
while (itr.next()) {
double v = itr.getQuantile();
long wt = itr.getWeight();
printf("%12.1f%12d\n", v, wt);
}
}
private static void show(final KllDoublesSketch sk, int limit) {
int i = (int) sk.getN();
for ( ; i < limit; i++) { sk.update(i + 1); }
println(sk.toString(true, true));
}
@Test
public void checkSketchInitializeDoubleHeap() {
int k = 20; //don't change this
KllDoublesSketch sk;
//println("#### CASE: DOUBLE FULL HEAP");
sk = getDirectDoublesSketch(k, 0);
for (int i = 1; i <= k + 1; i++) { sk.update(i); }
//println(sk.toString(true, true));
assertEquals(sk.getK(), k);
assertEquals(sk.getN(), k + 1);
assertEquals(sk.getNumRetained(), 11);
assertFalse(sk.isEmpty());
assertTrue(sk.isEstimationMode());
assertEquals(sk.getMinK(), k);
assertEquals(sk.getDoubleItemsArray().length, 33);
assertEquals(sk.getLevelsArray(sk.sketchStructure).length, 3);
assertEquals(sk.getMaxItem(), 21.0);
assertEquals(sk.getMinItem(), 1.0);
assertEquals(sk.getNumLevels(), 2);
assertFalse(sk.isLevelZeroSorted());
//println("#### CASE: DOUBLE HEAP EMPTY");
sk = getDirectDoublesSketch(k, 0);
//println(sk.toString(true, true));
assertEquals(sk.getK(), k);
assertEquals(sk.getN(), 0);
assertEquals(sk.getNumRetained(), 0);
assertTrue(sk.isEmpty());
assertFalse(sk.isEstimationMode());
assertEquals(sk.getMinK(), k);
assertEquals(sk.getDoubleItemsArray().length, 20);
assertEquals(sk.getLevelsArray(sk.sketchStructure).length, 2);
try { sk.getMaxItem(); fail(); } catch (SketchesArgumentException e) { }
try { sk.getMinItem(); fail(); } catch (SketchesArgumentException e) { }
assertEquals(sk.getNumLevels(), 1);
assertFalse(sk.isLevelZeroSorted());
//println("#### CASE: DOUBLE HEAP SINGLE");
sk = getDirectDoublesSketch(k, 0);
sk.update(1);
//println(sk.toString(true, true));
assertEquals(sk.getK(), k);
assertEquals(sk.getN(), 1);
assertEquals(sk.getNumRetained(), 1);
assertFalse(sk.isEmpty());
assertFalse(sk.isEstimationMode());
assertEquals(sk.getMinK(), k);
assertEquals(sk.getDoubleItemsArray().length, 20);
assertEquals(sk.getLevelsArray(sk.sketchStructure).length, 2);
assertEquals(sk.getMaxItem(), 1.0);
assertEquals(sk.getMinItem(), 1.0);
assertEquals(sk.getNumLevels(), 1);
assertFalse(sk.isLevelZeroSorted());
}
@Test
public void checkSketchInitializeDoubleHeapifyCompactMem() {
int k = 20; //don't change this
KllDoublesSketch sk;
KllDoublesSketch sk2;
byte[] compBytes;
WritableMemory wmem;
//println("#### CASE: DOUBLE FULL HEAPIFIED FROM COMPACT");
sk2 = getDirectDoublesSketch(k, 0);
for (int i = 1; i <= k + 1; i++) { sk2.update(i); }
//println(sk.toString(true, true));
compBytes = sk2.toByteArray();
wmem = WritableMemory.writableWrap(compBytes);
//println(KllPreambleUtil.toString(wmem));
sk = KllDoublesSketch.heapify(wmem);
assertEquals(sk.getK(), k);
assertEquals(sk.getN(), k + 1);
assertEquals(sk.getNumRetained(), 11);
assertFalse(sk.isEmpty());
assertTrue(sk.isEstimationMode());
assertEquals(sk.getMinK(), k);
assertEquals(sk.getDoubleItemsArray().length, 33);
assertEquals(sk.getLevelsArray(sk.sketchStructure).length, 3);
assertEquals(sk.getMaxItem(), 21.0);
assertEquals(sk.getMinItem(), 1.0);
assertEquals(sk.getNumLevels(), 2);
assertFalse(sk.isLevelZeroSorted());
//println("#### CASE: DOUBLE EMPTY HEAPIFIED FROM COMPACT");
sk2 = getDirectDoublesSketch(k, 0);
//println(sk.toString(true, true));
compBytes = sk2.toByteArray();
wmem = WritableMemory.writableWrap(compBytes);
//println(KllPreambleUtil.toString(wmem));
sk = KllDoublesSketch.heapify(wmem);
assertEquals(sk.getK(), k);
assertEquals(sk.getN(), 0);
assertEquals(sk.getNumRetained(), 0);
assertTrue(sk.isEmpty());
assertFalse(sk.isEstimationMode());
assertEquals(sk.getMinK(), k);
assertEquals(sk.getDoubleItemsArray().length, 20);
assertEquals(sk.getLevelsArray(sk.sketchStructure).length, 2);
try { sk.getMaxItem(); fail(); } catch (SketchesArgumentException e) { }
try { sk.getMinItem(); fail(); } catch (SketchesArgumentException e) { }
assertEquals(sk.getNumLevels(), 1);
assertFalse(sk.isLevelZeroSorted());
//println("#### CASE: DOUBLE SINGLE HEAPIFIED FROM COMPACT");
sk2 = getDirectDoublesSketch(k, 0);
sk2.update(1);
//println(sk2.toString(true, true));
compBytes = sk2.toByteArray();
wmem = WritableMemory.writableWrap(compBytes);
//println(KllPreambleUtil.toString(wmem));
sk = KllDoublesSketch.heapify(wmem);
assertEquals(sk.getK(), k);
assertEquals(sk.getN(), 1);
assertEquals(sk.getNumRetained(), 1);
assertFalse(sk.isEmpty());
assertFalse(sk.isEstimationMode());
assertEquals(sk.getMinK(), k);
assertEquals(sk.getDoubleItemsArray().length, 20);
assertEquals(sk.getLevelsArray(sk.sketchStructure).length, 2);
assertEquals(sk.getMaxItem(), 1.0);
assertEquals(sk.getMinItem(), 1.0);
assertEquals(sk.getNumLevels(), 1);
assertFalse(sk.isLevelZeroSorted());
}
@Test
public void checkSketchInitializeDoubleHeapifyUpdatableMem() {
int k = 20; //don't change this
KllDoublesSketch sk;
KllDoublesSketch sk2;
byte[] compBytes;
WritableMemory wmem;
//println("#### CASE: DOUBLE FULL HEAPIFIED FROM UPDATABLE");
sk2 = getDirectDoublesSketch(k, 0);
for (int i = 1; i <= k + 1; i++) { sk2.update(i); }
//println(sk2.toString(true, true));
compBytes = KllHelper.toByteArray(sk2, true);
wmem = WritableMemory.writableWrap(compBytes);
sk = KllHeapDoublesSketch.heapifyImpl(wmem);
//println(sk.toString(true, true));
assertEquals(sk.getK(), k);
assertEquals(sk.getN(), k + 1);
assertEquals(sk.getNumRetained(), 11);
assertFalse(sk.isEmpty());
assertTrue(sk.isEstimationMode());
assertEquals(sk.getMinK(), k);
assertEquals(sk.getDoubleItemsArray().length, 33);
assertEquals(sk.getLevelsArray(sk.sketchStructure).length, 3);
assertEquals(sk.getMaxItem(), 21.0);
assertEquals(sk.getMinItem(), 1.0);
assertEquals(sk.getNumLevels(), 2);
assertFalse(sk.isLevelZeroSorted());
// println("#### CASE: DOUBLE EMPTY HEAPIFIED FROM UPDATABLE");
sk2 = getDirectDoublesSketch(k, 0);
//println(sk.toString(true, true));
compBytes = KllHelper.toByteArray(sk2, true);
wmem = WritableMemory.writableWrap(compBytes);
//println(KllPreambleUtil.toString(wmem));
sk = KllHeapDoublesSketch.heapifyImpl(wmem);
assertEquals(sk.getK(), k);
assertEquals(sk.getN(), 0);
assertEquals(sk.getNumRetained(), 0);
assertTrue(sk.isEmpty());
assertFalse(sk.isEstimationMode());
assertEquals(sk.getMinK(), k);
assertEquals(sk.getDoubleItemsArray().length, 20);
assertEquals(sk.getLevelsArray(sk.sketchStructure).length, 2);
try { sk.getMaxItem(); fail(); } catch (SketchesArgumentException e) { }
try { sk.getMinItem(); fail(); } catch (SketchesArgumentException e) { }
assertEquals(sk.getNumLevels(), 1);
assertFalse(sk.isLevelZeroSorted());
//println("#### CASE: DOUBLE SINGLE HEAPIFIED FROM UPDATABLE");
sk2 = getDirectDoublesSketch(k, 0);
sk2.update(1);
//println(sk.toString(true, true));
compBytes = KllHelper.toByteArray(sk2, true);
wmem = WritableMemory.writableWrap(compBytes);
//println(KllPreambleUtil.memoryToString(wmem, true));
sk = KllHeapDoublesSketch.heapifyImpl(wmem);
assertEquals(sk.getK(), k);
assertEquals(sk.getN(), 1);
assertEquals(sk.getNumRetained(), 1);
assertFalse(sk.isEmpty());
assertFalse(sk.isEstimationMode());
assertEquals(sk.getMinK(), k);
assertEquals(sk.getDoubleItemsArray().length, 20);
assertEquals(sk.getLevelsArray(sk.sketchStructure).length, 2);
assertEquals(sk.getMaxItem(), 1.0);
assertEquals(sk.getMinItem(), 1.0);
assertEquals(sk.getNumLevels(), 1);
assertFalse(sk.isLevelZeroSorted());
}
@Test
public void checkMemoryToStringDoubleUpdatable() {
int k = 20; //don't change this
KllDoublesSketch sk;
KllDoublesSketch sk2;
byte[] upBytes;
byte[] upBytes2;
WritableMemory wmem;
String s;
println("#### CASE: DOUBLE FULL UPDATABLE");
sk = getDirectDoublesSketch(k, 0);
for (int i = 1; i <= k + 1; i++) { sk.update(i); }
upBytes = KllHelper.toByteArray(sk, true);
wmem = WritableMemory.writableWrap(upBytes);
s = KllPreambleUtil.toString(wmem, DOUBLES_SKETCH, true);
println("step 1: sketch to byte[]/memory & analyze memory");
println(s);
sk2 = KllDoublesSketch.writableWrap(wmem, memReqSvr);
upBytes2 = KllHelper.toByteArray(sk2, true);
wmem = WritableMemory.writableWrap(upBytes2);
s = KllPreambleUtil.toString(wmem, DOUBLES_SKETCH, true);
println("step 2: memory to heap sketch, to byte[]/memory & analyze memory. Should match above");
println(s);
assertEquals(upBytes, upBytes2);
println("#### CASE: DOUBLE EMPTY UPDATABLE");
sk = getDirectDoublesSketch(k, 0);
upBytes = KllHelper.toByteArray(sk, true);
wmem = WritableMemory.writableWrap(upBytes);
s = KllPreambleUtil.toString(wmem, DOUBLES_SKETCH, true);
println("step 1: sketch to byte[]/memory & analyze memory");
println(s);
sk2 = KllDoublesSketch.writableWrap(wmem, memReqSvr);
upBytes2 = KllHelper.toByteArray(sk2, true);
wmem = WritableMemory.writableWrap(upBytes2);
s = KllPreambleUtil.toString(wmem, DOUBLES_SKETCH, true);
println("step 2: memory to heap sketch, to byte[]/memory & analyze memory. Should match above");
println(s);
assertEquals(upBytes, upBytes2);
println("#### CASE: DOUBLE SINGLE UPDATABL");
sk = getDirectDoublesSketch(k, 0);
sk.update(1);
upBytes = KllHelper.toByteArray(sk, true);
wmem = WritableMemory.writableWrap(upBytes);
s = KllPreambleUtil.toString(wmem, DOUBLES_SKETCH, true);
println("step 1: sketch to byte[]/memory & analyze memory");
println(s);
sk2 = KllDoublesSketch.writableWrap(wmem, memReqSvr);
upBytes2 = KllHelper.toByteArray(sk2, true);
wmem = WritableMemory.writableWrap(upBytes2);
s = KllPreambleUtil.toString(wmem, DOUBLES_SKETCH, true);
println("step 2: memory to heap sketch, to byte[]/memory & analyze memory. Should match above");
println(s);
assertEquals(upBytes, upBytes2);
}
@Test
public void checkSimpleMerge() {
int k = 20;
int n1 = 21;
int n2 = 21;
KllDoublesSketch sk1 = getDirectDoublesSketch(k, 0);
KllDoublesSketch sk2 = getDirectDoublesSketch(k, 0);
for (int i = 1; i <= n1; i++) {
sk1.update(i);
}
for (int i = 1; i <= n2; i++) {
sk2.update(i + 100);
}
println(sk1.toString(true, true));
println(sk2.toString(true, true));
sk1.merge(sk2);
println(sk1.toString(true, true));
assertEquals(sk1.getMaxItem(), 121.0);
assertEquals(sk1.getMinItem(), 1.0);
}
@Test
public void checkSizes() {
KllDoublesSketch sk = getDirectDoublesSketch(20, 0);
for (int i = 1; i <= 21; i++) { sk.update(i); }
//println(sk.toString(true, true));
byte[] byteArr1 = KllHelper.toByteArray(sk, true);
int size1 = sk.currentSerializedSizeBytes(true);
assertEquals(size1, byteArr1.length);
byte[] byteArr2 = sk.toByteArray();
int size2 = sk.currentSerializedSizeBytes(false);
assertEquals(size2, byteArr2.length);
}
@Test
public void checkNewInstance() {
int k = 200;
WritableMemory dstMem = WritableMemory.allocate(6000);
KllDoublesSketch sk = KllDoublesSketch.newDirectInstance(k, dstMem, memReqSvr);
for (int i = 1; i <= 10_000; i++) {sk.update(i); }
assertEquals(sk.getMinItem(), 1.0);
assertEquals(sk.getMaxItem(), 10000.0);
//println(sk.toString(true, true));
}
@Test
public void checkDifferentM() {
int k = 20;
int m = 4;
WritableMemory dstMem = WritableMemory.allocate(1000);
KllDoublesSketch sk = KllDirectDoublesSketch.newDirectUpdatableInstance(k, m, dstMem, memReqSvr);
for (int i = 1; i <= 200; i++) {sk.update(i); }
assertEquals(sk.getMinItem(), 1.0);
assertEquals(sk.getMaxItem(), 200.0);
}
private static KllDoublesSketch getDirectDoublesSketch(final int k, final int n) {
KllDoublesSketch sk = KllDoublesSketch.newHeapInstance(k);
for (int i = 1; i <= n; i++) { sk.update(i); }
byte[] byteArr = KllHelper.toByteArray(sk, true);
WritableMemory wmem = WritableMemory.writableWrap(byteArr);
KllDoublesSketch ddsk = KllDoublesSketch.writableWrap(wmem, memReqSvr);
return ddsk;
}
@Test
public void printlnTest() {
String s = "PRINTING: printf in " + this.getClass().getName();
println(s);
printf("%s\n", s);
}
private final static boolean enablePrinting = false;
/**
* @param format the format
* @param args the args
*/
private static final void printf(final String format, final Object ...args) {
if (enablePrinting) { System.out.printf(format, args); }
}
/**
* @param o the Object to println
*/
private static final void println(final Object o) {
if (enablePrinting) { System.out.println(o.toString()); }
}
}