blob: 0b21f7b431bcc6772d5a3b8e7151bf1b6436fa62 [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_NOMINAL_ENTRIES;
import static org.apache.datasketches.Util.DEFAULT_UPDATE_SEED;
import static org.apache.datasketches.Util.LS;
import static org.apache.datasketches.Util.MAX_LG_NOM_LONGS;
import static org.apache.datasketches.Util.MIN_LG_NOM_LONGS;
import static org.apache.datasketches.Util.TAB;
import static org.apache.datasketches.Util.ceilingPowerOf2;
import org.apache.datasketches.Family;
import org.apache.datasketches.ResizeFactor;
import org.apache.datasketches.SketchesArgumentException;
import org.apache.datasketches.memory.DefaultMemoryRequestServer;
import org.apache.datasketches.memory.MemoryRequestServer;
import org.apache.datasketches.memory.WritableMemory;
/**
* For building a new SetOperation.
*
* @author Lee Rhodes
*/
public class SetOperationBuilder {
private int bLgNomLongs;
private long bSeed;
private ResizeFactor bRF;
private float bP;
private MemoryRequestServer bMemReqSvr;
/**
* Constructor for building a new SetOperation. The default configuration is
* <ul>
* <li>Max Nominal Entries (max K): {@value org.apache.datasketches.Util#DEFAULT_NOMINAL_ENTRIES}</li>
* <li>Seed: {@value org.apache.datasketches.Util#DEFAULT_UPDATE_SEED}</li>
* <li>{@link ResizeFactor#X8}</li>
* <li>Input Sampling Probability: 1.0</li>
* <li>Memory: null</li>
* </ul>
*/
public SetOperationBuilder() {
bLgNomLongs = Integer.numberOfTrailingZeros(DEFAULT_NOMINAL_ENTRIES);
bSeed = DEFAULT_UPDATE_SEED;
bP = (float) 1.0;
bRF = ResizeFactor.X8;
bMemReqSvr = new DefaultMemoryRequestServer();
}
/**
* Sets the Maximum Nominal Entries (max K) for this set operation. The effective value of K of the result of a
* Set Operation can be less than max K, but never greater.
* The minimum value is 16 and the maximum value is 67,108,864, which is 2^26.
* @param nomEntries <a href="{@docRoot}/resources/dictionary.html#nomEntries">Nominal Entres</a>
* This will become the ceiling power of 2 if it is not a power of 2.
* @return this SetOperationBuilder
*/
public SetOperationBuilder setNominalEntries(final int nomEntries) {
bLgNomLongs = Integer.numberOfTrailingZeros(ceilingPowerOf2(nomEntries));
if ((bLgNomLongs > MAX_LG_NOM_LONGS) || (bLgNomLongs < MIN_LG_NOM_LONGS)) {
throw new SketchesArgumentException("Nominal Entries must be >= 16 and <= 67108864: "
+ nomEntries);
}
return this;
}
/**
* Returns Log-base 2 Nominal Entries
* @return Log-base 2 Nominal Entries
*/
public int getLgNominalEntries() {
return bLgNomLongs;
}
/**
* Sets the long seed value that is require by the hashing function.
* @param seed <a href="{@docRoot}/resources/dictionary.html#seed">See seed</a>
* @return this SetOperationBuilder
*/
public SetOperationBuilder setSeed(final long seed) {
bSeed = seed;
return this;
}
/**
* Returns the seed
* @return the seed
*/
public long getSeed() {
return bSeed;
}
/**
* Sets the upfront uniform sampling probability, <i>p</i>. Although this functionality is
* implemented for Unions only, it rarely makes sense to use it. The proper use of upfront
* sampling is when building the sketches.
* @param p <a href="{@docRoot}/resources/dictionary.html#p">See Sampling Probability, <i>p</i></a>
* @return this SetOperationBuilder
*/
public SetOperationBuilder setP(final float p) {
if ((p <= 0.0) || (p > 1.0)) {
throw new SketchesArgumentException("p must be > 0 and <= 1.0: " + p);
}
bP = p;
return this;
}
/**
* Returns the pre-sampling probability <i>p</i>
* @return the pre-sampling probability <i>p</i>
*/
public float getP() {
return bP;
}
/**
* Sets the cache Resize Factor
* @param rf <a href="{@docRoot}/resources/dictionary.html#resizeFactor">See Resize Factor</a>
* @return this SetOperationBuilder
*/
public SetOperationBuilder setResizeFactor(final ResizeFactor rf) {
bRF = rf;
return this;
}
/**
* Returns the Resize Factor
* @return the Resize Factor
*/
public ResizeFactor getResizeFactor() {
return bRF;
}
/**
* Set the MemoryRequestServer
* @param memReqSvr the given MemoryRequestServer
* @return this SetOperationBuilder
*/
public SetOperationBuilder setMemoryRequestServer(final MemoryRequestServer memReqSvr) {
bMemReqSvr = memReqSvr;
return this;
}
/**
* Returns the MemoryRequestServer
* @return the MemoryRequestServer
*/
public MemoryRequestServer getMemoryRequestServer() {
return bMemReqSvr;
}
/**
* Returns a SetOperation with the current configuration of this Builder and the given Family.
* @param family the chosen SetOperation family
* @return a SetOperation
*/
public SetOperation build(final Family family) {
return build(family, null);
}
/**
* Returns a SetOperation with the current configuration of this Builder, the given Family
* and the given destination memory. Note that the destination memory cannot be used with AnotB.
* @param family the chosen SetOperation family
* @param dstMem The destination Memory.
* @return a SetOperation
*/
public SetOperation build(final Family family, final WritableMemory dstMem) {
SetOperation setOp = null;
switch (family) {
case UNION: {
if (dstMem == null) {
setOp = UnionImpl.initNewHeapInstance(bLgNomLongs, bSeed, bP, bRF);
}
else {
setOp = UnionImpl.initNewDirectInstance(bLgNomLongs, bSeed, bP, bRF, bMemReqSvr, dstMem);
}
break;
}
case INTERSECTION: {
if (dstMem == null) {
setOp = IntersectionImpl.initNewHeapInstance(bSeed);
}
else {
setOp = IntersectionImpl.initNewDirectInstance(bSeed, dstMem);
}
break;
}
case A_NOT_B: {
if (dstMem == null) {
setOp = new AnotBimpl(bSeed);
}
else {
throw new SketchesArgumentException(
"AnotB can not be persisted.");
}
break;
}
default:
throw new SketchesArgumentException(
"Given Family cannot be built as a SetOperation: " + family.toString());
}
return setOp;
}
/**
* Convenience method, returns a configured SetOperation Union with
* <a href="{@docRoot}/resources/dictionary.html#defaultNomEntries">Default Nominal Entries</a>
* @return a Union object
*/
public Union buildUnion() {
return (Union) build(Family.UNION);
}
/**
* Convenience method, returns a configured SetOperation Union with
* <a href="{@docRoot}/resources/dictionary.html#defaultNomEntries">Default Nominal Entries</a>
* and the given destination memory.
* @param dstMem The destination Memory.
* @return a Union object
*/
public Union buildUnion(final WritableMemory dstMem) {
return (Union) build(Family.UNION, dstMem);
}
/**
* Convenience method, returns a configured SetOperation Intersection with
* <a href="{@docRoot}/resources/dictionary.html#defaultNomEntries">Default Nominal Entries</a>
* @return an Intersection object
*/
public Intersection buildIntersection() {
return (Intersection) build(Family.INTERSECTION);
}
/**
* Convenience method, returns a configured SetOperation Intersection with
* <a href="{@docRoot}/resources/dictionary.html#defaultNomEntries">Default Nominal Entries</a>
* and the given destination memory.
* @param dstMem The destination Memory.
* @return an Intersection object
*/
public Intersection buildIntersection(final WritableMemory dstMem) {
return (Intersection) build(Family.INTERSECTION, dstMem);
}
/**
* Convenience method, returns a configured SetOperation ANotB with
* <a href="{@docRoot}/resources/dictionary.html#defaultUpdateSeed">Default Update Seed</a>
* @return an ANotB object
*/
public AnotB buildANotB() {
return (AnotB) build(Family.A_NOT_B);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SetOperationBuilder configuration:").append(LS);
sb.append("LgK:").append(TAB).append(bLgNomLongs).append(LS);
sb.append("K:").append(TAB).append(1 << bLgNomLongs).append(LS);
sb.append("Seed:").append(TAB).append(bSeed).append(LS);
sb.append("p:").append(TAB).append(bP).append(LS);
sb.append("ResizeFactor:").append(TAB).append(bRF).append(LS);
final String mrsStr = bMemReqSvr.getClass().getSimpleName();
sb.append("MemoryRequestServer:").append(TAB).append(mrsStr).append(LS);
return sb.toString();
}
}