blob: ee73f114e4266e56144524636062348c9e68e0c5 [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.theta;
import static org.apache.datasketches.Util.DEFAULT_UPDATE_SEED;
import static org.apache.datasketches.theta.PreambleUtil.EMPTY_FLAG_MASK;
import static org.apache.datasketches.theta.PreambleUtil.FAMILY_BYTE;
import static org.apache.datasketches.theta.PreambleUtil.FLAGS_BYTE;
import static org.apache.datasketches.theta.PreambleUtil.PREAMBLE_LONGS_BYTE;
import static org.apache.datasketches.theta.PreambleUtil.RETAINED_ENTRIES_INT;
import static org.apache.datasketches.theta.PreambleUtil.SER_VER_BYTE;
import static org.apache.datasketches.theta.PreambleUtil.THETA_LONG;
import org.apache.datasketches.Family;
import org.apache.datasketches.SketchesArgumentException;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
/**
* This class brings together the common sketch and set operation creation methods and
* the public static methods into one place.
*
* @author Lee Rhodes
*/
public final class Sketches {
private Sketches() {}
/**
* Ref: {@link UpdateSketchBuilder UpdateSketchBuilder}
* @return {@link UpdateSketchBuilder UpdateSketchBuilder}
*/
public static UpdateSketchBuilder updateSketchBuilder() {
return new UpdateSketchBuilder();
}
/**
* Ref: {@link Sketch#heapify(Memory) Sketch.heapify(Memory)}
* @param srcMem Ref: {@link Sketch#heapify(Memory) Sketch.heapify(Memory)} {@code srcMem}
* @return {@link Sketch Sketch}
*/
public static Sketch heapifySketch(final Memory srcMem) {
return Sketch.heapify(srcMem);
}
/**
* Ref: {@link Sketch#heapify(Memory, long) Sketch.heapify(Memory, long)}
* @param srcMem Ref: {@link Sketch#heapify(Memory, long) Sketch.heapify(Memory, long)} {@code srcMem}
* @param seed Ref: {@link Sketch#heapify(Memory, long) Sketch.heapify(Memory, long)} {@code seed}
* @return {@link Sketch Sketch}
*/
public static Sketch heapifySketch(final Memory srcMem, final long seed) {
return Sketch.heapify(srcMem, seed);
}
/**
* Ref: {@link UpdateSketch#heapify(Memory) UpdateSketch.heapify(Memory)}
* @param srcMem Ref: {@link UpdateSketch#heapify(Memory) UpdateSketch.heapify(Memory)} {@code srcMem}
* @return {@link UpdateSketch UpdateSketch}
*/
public static UpdateSketch heapifyUpdateSketch(final Memory srcMem) {
return UpdateSketch.heapify(srcMem);
}
/**
* Ref: {@link UpdateSketch#heapify(Memory, long) UpdateSketch.heapify(Memory, long)}
* @param srcMem Ref: {@link UpdateSketch#heapify(Memory, long) UpdateSketch.heapify(Memory, long)}
* {@code srcMem}
* @param seed Ref: {@link UpdateSketch#heapify(Memory, long) UpdateSketch.heapify(Memory, long)}
* {@code seed}
* @return {@link UpdateSketch UpdateSketch}
*/
public static UpdateSketch heapifyUpdateSketch(final Memory srcMem, final long seed) {
return UpdateSketch.heapify(srcMem, seed);
}
/**
* Ref: {@link Sketch#wrap(Memory) Sketch.wrap(Memory)}
* @param srcMem Ref: {@link Sketch#wrap(Memory) Sketch.wrap(Memory)} {@code srcMem}
* @return {@link Sketch Sketch}
*/
public static Sketch wrapSketch(final Memory srcMem) {
return Sketch.wrap(srcMem);
}
/**
* Ref: {@link Sketch#wrap(Memory, long) Sketch.wrap(Memory, long)}
* @param srcMem Ref: {@link Sketch#wrap(Memory, long) Sketch.wrap(Memory, long)} {@code srcMem}
* @param seed Ref: {@link Sketch#wrap(Memory, long) Sketch.wrap(Memory, long)} {@code seed}
* @return {@link Sketch Sketch}
*/
public static Sketch wrapSketch(final Memory srcMem, final long seed) {
return Sketch.wrap(srcMem, seed);
}
/**
* Ref: {@link UpdateSketch#wrap(Memory) UpdateSketch.wrap(Memory)}
* @param srcMem Ref: {@link UpdateSketch#wrap(Memory) UpdateSketch.wrap(Memory)} {@code srcMem}
* @return {@link UpdateSketch UpdateSketch}
*/
public static UpdateSketch wrapUpdateSketch(final WritableMemory srcMem) {
return wrapUpdateSketch(srcMem, DEFAULT_UPDATE_SEED);
}
/**
* Ref: {@link UpdateSketch#wrap(Memory, long) UpdateSketch.wrap(Memory, long)}
* @param srcMem Ref: {@link UpdateSketch#wrap(Memory, long) UpdateSketch.wrap(Memory, long)} {@code srcMem}
* @param seed Ref: {@link UpdateSketch#wrap(Memory, long) UpdateSketch.wrap(Memory, long)} {@code seed}
* @return {@link UpdateSketch UpdateSketch}
*/
public static UpdateSketch wrapUpdateSketch(final WritableMemory srcMem, final long seed) {
return UpdateSketch.wrap(srcMem, seed);
}
/**
* Ref: {@link SetOperationBuilder SetOperationBuilder}
* @return {@link SetOperationBuilder SetOperationBuilder}
*/
public static SetOperationBuilder setOperationBuilder() {
return new SetOperationBuilder();
}
/**
* Ref: {@link SetOperation#heapify(Memory) SetOperation.heapify(Memory)}
* @param srcMem Ref: {@link SetOperation#heapify(Memory) SetOperation.heapify(Memory)} {@code srcMem}
* @return {@link SetOperation SetOperation}
*/
public static SetOperation heapifySetOperation(final Memory srcMem) {
return SetOperation.heapify(srcMem);
}
/**
* Ref: {@link SetOperation#heapify(Memory, long) SetOperation.heapify(Memory, long)}
* @param srcMem Ref: {@link SetOperation#heapify(Memory, long) SetOperation.heapify(Memory, long)}
* {@code srcMem}
* @param seed Ref: {@link SetOperation#heapify(Memory, long) SetOperation.heapify(Memory, long)}
* {@code seed}
* @return {@link SetOperation SetOperation}
*/
public static SetOperation heapifySetOperation(final Memory srcMem, final long seed) {
return SetOperation.heapify(srcMem, seed);
}
/**
* Ref: {@link SetOperation#wrap(Memory) SetOperation.wrap(Memory)}
* @param srcMem Ref: {@link SetOperation#wrap(Memory) SetOperation.wrap(Memory)} {@code srcMem}
* @return {@link SetOperation SetOperation}
*/
public static SetOperation wrapSetOperation(final Memory srcMem) {
return wrapSetOperation(srcMem, DEFAULT_UPDATE_SEED);
}
/**
* Ref: {@link SetOperation#wrap(Memory) SetOperation.wrap(Memory)}
* @param srcMem Ref: {@link SetOperation#wrap(Memory) SetOperation.wrap(Memory)} {@code srcMem}
* @return {@link SetOperation SetOperation}
*/
public static SetOperation wrapSetOperation(final WritableMemory srcMem) {
return wrapSetOperation(srcMem, DEFAULT_UPDATE_SEED);
}
/**
* Convenience method, calls {@link SetOperation#wrap(Memory)} and casts the result to a Union
* @param srcMem Ref: {@link SetOperation#wrap(Memory)} {@code srcMem}
* @return a Union backed by the given Memory
*/
public static Union wrapUnion(final Memory srcMem) {
return (Union) SetOperation.wrap(srcMem);
}
/**
* Convenience method, calls {@link SetOperation#wrap(Memory)} and casts the result to a Union
* @param srcMem Ref: {@link SetOperation#wrap(Memory)} {@code srcMem}
* @return a Union backed by the given Memory
*/
public static Union wrapUnion(final WritableMemory srcMem) {
return (Union) SetOperation.wrap(srcMem);
}
/**
* Convenience method, calls {@link SetOperation#wrap(Memory)} and casts the result to a Intersection
* @param srcMem Ref: {@link SetOperation#wrap(Memory)} {@code srcMem}
* @return a Intersection backed by the given Memory
*/
public static Intersection wrapIntersection(final Memory srcMem) {
return (Intersection) SetOperation.wrap(srcMem);
}
/**
* Convenience method, calls {@link SetOperation#wrap(Memory)} and casts the result to a Intersection
* @param srcMem Ref: {@link SetOperation#wrap(Memory)} {@code srcMem}
* @return a Intersection backed by the given Memory
*/
public static Intersection wrapIntersection(final WritableMemory srcMem) {
return (Intersection) SetOperation.wrap(srcMem);
}
/**
* Ref: {@link SetOperation#wrap(Memory, long) SetOperation.wrap(Memory, long)}
* @param srcMem Ref: {@link SetOperation#wrap(Memory, long) SetOperation.wrap(Memory, long)}
* {@code srcMem}
* @param seed Ref: {@link SetOperation#wrap(Memory, long) SetOperation.wrap(Memory, long)}
* {@code seed}
* @return {@link SetOperation SetOperation}
*/
public static SetOperation wrapSetOperation(final Memory srcMem, final long seed) {
return SetOperation.wrap(srcMem, seed);
}
/**
* Ref: {@link SetOperation#wrap(Memory, long) SetOperation.wrap(Memory, long)}
* @param srcMem Ref: {@link SetOperation#wrap(Memory, long) SetOperation.wrap(Memory, long)}
* {@code srcMem}
* @param seed Ref: {@link SetOperation#wrap(Memory, long) SetOperation.wrap(Memory, long)}
* {@code seed}
* @return {@link SetOperation SetOperation}
*/
public static SetOperation wrapSetOperation(final WritableMemory srcMem, final long seed) {
return SetOperation.wrap(srcMem, seed);
}
//Get size methods, etc
/**
* Ref: {@link Sketch#getMaxCompactSketchBytes(int)}
* @param numberOfEntries Ref: {@link Sketch#getMaxCompactSketchBytes(int)}
* {@code numberOfEntries}
* @return Ref: {@link Sketch#getMaxCompactSketchBytes(int)}
*/
public static int getMaxCompactSketchBytes(final int numberOfEntries) {
return Sketch.getMaxCompactSketchBytes(numberOfEntries);
}
/**
* Ref: {@link Sketch#getMaxUpdateSketchBytes(int)}
* @param nomEntries Ref: {@link Sketch#getMaxUpdateSketchBytes(int)} {@code nomEntries}
* @return Ref: {@link Sketch#getMaxUpdateSketchBytes(int)}
*/
public static int getMaxUpdateSketchBytes(final int nomEntries) {
return Sketch.getMaxUpdateSketchBytes(nomEntries);
}
/**
* Ref: {@link Sketch#getSerializationVersion(Memory)}
* @param srcMem Ref: {@link Sketch#getSerializationVersion(Memory)} {@code srcMem}
* @return Ref: {@link Sketch#getSerializationVersion(Memory)}
*/
public static int getSerializationVersion(final Memory srcMem) {
return Sketch.getSerializationVersion(srcMem);
}
/**
* Ref: {@link SetOperation#getMaxUnionBytes(int)}
* @param nomEntries Ref: {@link SetOperation#getMaxUnionBytes(int)} {@code nomEntries}
* @return Ref: {@link SetOperation#getMaxUnionBytes(int)}
*/
public static int getMaxUnionBytes(final int nomEntries) {
return SetOperation.getMaxUnionBytes(nomEntries);
}
/**
* Ref: {@link SetOperation#getMaxIntersectionBytes(int)}
* @param nomEntries Ref: {@link SetOperation#getMaxIntersectionBytes(int)} {@code nomEntries}
* @return Ref: {@link SetOperation#getMaxIntersectionBytes(int)}
*/
public static int getMaxIntersectionBytes(final int nomEntries) {
return SetOperation.getMaxIntersectionBytes(nomEntries);
}
/**
* Ref: {@link SetOperation#getMaxAnotBResultBytes(int)}.
* Returns the maximum number of bytes for the returned CompactSketch, given the maximum
* value of nomEntries of the first sketch A of AnotB.
* @param maxNomEntries the given value
* @return the maximum number of bytes.
*/
public static int getMaxAnotBResultBytes(final int maxNomEntries) {
return SetOperation.getMaxAnotBResultBytes(maxNomEntries);
}
//Get estimates and bounds from Memory
/**
* Gets the unique count estimate from a valid memory image of a Sketch
* @param srcMem <a href="{@docRoot}/resources/dictionary.html#mem">See Memory</a>
* @return the sketch's best estimate of the cardinality of the input stream.
*/
public static double getEstimate(final Memory srcMem) {
checkIfValidThetaSketch(srcMem);
return Sketch.estimate(getThetaLong(srcMem), getRetainedEntries(srcMem));
}
/**
* Gets the approximate upper error bound from a valid memory image of a Sketch
* given the specified number of Standard Deviations.
* This will return getEstimate() if isEmpty() is true.
*
* @param numStdDev
* <a href="{@docRoot}/resources/dictionary.html#numStdDev">See Number of Standard Deviations</a>
* @param srcMem
* <a href="{@docRoot}/resources/dictionary.html#mem">See Memory</a>
* @return the upper bound.
*/
public static double getUpperBound(final int numStdDev, final Memory srcMem) {
return Sketch.upperBound(getRetainedEntries(srcMem), getThetaLong(srcMem), numStdDev, getEmpty(srcMem));
}
/**
* Gets the approximate lower error bound from a valid memory image of a Sketch
* given the specified number of Standard Deviations.
* This will return getEstimate() if isEmpty() is true.
*
* @param numStdDev
* <a href="{@docRoot}/resources/dictionary.html#numStdDev">See Number of Standard Deviations</a>
* @param srcMem <a href="{@docRoot}/resources/dictionary.html#mem">See Memory</a>
* @return the lower bound.
*/
public static double getLowerBound(final int numStdDev, final Memory srcMem) {
return Sketch.lowerBound(getRetainedEntries(srcMem), getThetaLong(srcMem), numStdDev, getEmpty(srcMem));
}
//Restricted static methods
static int getPreambleLongs(final Memory srcMem) {
return srcMem.getByte(PREAMBLE_LONGS_BYTE) & 0X3F; //for SerVer 1,2,3
}
static int getRetainedEntries(final Memory srcMem) {
final int serVer = srcMem.getByte(SER_VER_BYTE);
if (serVer == 1) {
final int entries = srcMem.getInt(RETAINED_ENTRIES_INT);
if ((getThetaLong(srcMem) == Long.MAX_VALUE) && (entries == 0)) {
return 0;
}
return entries;
}
//SerVer 2 or 3
final int preLongs = getPreambleLongs(srcMem);
final boolean empty = (srcMem.getByte(FLAGS_BYTE) & EMPTY_FLAG_MASK) != 0; //for SerVer 2 & 3
if (preLongs == 1) {
return empty ? 0 : 1;
}
//preLongs > 1
return srcMem.getInt(RETAINED_ENTRIES_INT); //for SerVer 1,2,3
}
static long getThetaLong(final Memory srcMem) {
final int preLongs = getPreambleLongs(srcMem);
return (preLongs < 3) ? Long.MAX_VALUE : srcMem.getLong(THETA_LONG); //for SerVer 1,2,3
}
static boolean getEmpty(final Memory srcMem) {
final int serVer = srcMem.getByte(SER_VER_BYTE);
if (serVer == 1) {
return ((getThetaLong(srcMem) == Long.MAX_VALUE) && (getRetainedEntries(srcMem) == 0));
}
return (srcMem.getByte(FLAGS_BYTE) & EMPTY_FLAG_MASK) != 0; //for SerVer 2 & 3
}
static void checkIfValidThetaSketch(final Memory srcMem) {
final int fam = srcMem.getByte(FAMILY_BYTE);
if (!Sketch.isValidSketchID(fam)) {
throw new SketchesArgumentException("Source Memory not a valid Sketch. Family: "
+ Family.idToFamily(fam).toString());
}
}
}