| /* |
| * 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()); |
| } |
| } |
| } |