blob: f0e67a24fbce8ce3e3e1d564acc7b010f58df8f1 [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.MIN_LG_NOM_LONGS;
import static org.apache.datasketches.theta.CompactOperations.checkIllegalCurCountAndEmpty;
import static org.apache.datasketches.theta.CompactOperations.correctThetaOnCompact;
import static org.apache.datasketches.theta.PreambleUtil.EMPTY_FLAG_MASK;
import static org.apache.datasketches.theta.PreambleUtil.SER_VER;
import static org.apache.datasketches.theta.PreambleUtil.insertCurCount;
import static org.apache.datasketches.theta.PreambleUtil.insertFamilyID;
import static org.apache.datasketches.theta.PreambleUtil.insertFlags;
import static org.apache.datasketches.theta.PreambleUtil.insertLgArrLongs;
import static org.apache.datasketches.theta.PreambleUtil.insertLgNomLongs;
import static org.apache.datasketches.theta.PreambleUtil.insertLgResizeFactor;
import static org.apache.datasketches.theta.PreambleUtil.insertP;
import static org.apache.datasketches.theta.PreambleUtil.insertPreLongs;
import static org.apache.datasketches.theta.PreambleUtil.insertSeedHash;
import static org.apache.datasketches.theta.PreambleUtil.insertSerVer;
import static org.apache.datasketches.theta.PreambleUtil.insertThetaLong;
import org.apache.datasketches.ResizeFactor;
import org.apache.datasketches.Util;
import org.apache.datasketches.memory.WritableMemory;
/**
* The parent class for Heap Updatable Theta Sketches.
*
* @author Lee Rhodes
*/
abstract class HeapUpdateSketch extends UpdateSketch {
final int lgNomLongs_;
private final long seed_;
private final float p_;
private final ResizeFactor rf_;
HeapUpdateSketch(final int lgNomLongs, final long seed, final float p, final ResizeFactor rf) {
lgNomLongs_ = Math.max(lgNomLongs, MIN_LG_NOM_LONGS);
seed_ = seed;
p_ = p;
rf_ = rf;
}
//Sketch
@Override
public int getCurrentBytes() {
final int preLongs = getCurrentPreambleLongs();
final int dataLongs = getCurrentDataLongs();
return (preLongs + dataLongs) << 3;
}
@Override
public boolean isDirect() {
return false;
}
@Override
public boolean hasMemory() {
return false;
}
//UpdateSketch
@Override
public int getLgNomLongs() {
return lgNomLongs_;
}
@Override
float getP() {
return p_;
}
@Override
public ResizeFactor getResizeFactor() {
return rf_;
}
@Override
long getSeed() {
return seed_;
}
//restricted methods
@Override
short getSeedHash() {
return Util.computeSeedHash(getSeed());
}
//Used by HeapAlphaSketch and HeapQuickSelectSketch
byte[] toByteArray(final int preLongs, final byte familyID) {
if (isDirty()) { rebuild(); }
checkIllegalCurCountAndEmpty(isEmpty(), getRetainedEntries(true));
final int preBytes = (preLongs << 3) & 0X3F;
final int dataBytes = getCurrentDataLongs() << 3;
final byte[] byteArrOut = new byte[preBytes + dataBytes];
final WritableMemory memOut = WritableMemory.writableWrap(byteArrOut);
//preamble first 8 bytes. Note: only compact can be reduced to 8 bytes.
final int lgRf = getResizeFactor().lg() & 0x3;
insertPreLongs(memOut, preLongs);
insertLgResizeFactor(memOut, lgRf);
insertSerVer(memOut, SER_VER);
insertFamilyID(memOut, familyID);
insertLgNomLongs(memOut, getLgNomLongs());
insertLgArrLongs(memOut, getLgArrLongs());
insertSeedHash(memOut, getSeedHash());
insertCurCount(memOut, this.getRetainedEntries(true));
insertP(memOut, getP());
final long thetaLong =
correctThetaOnCompact(isEmpty(), getRetainedEntries(true), getThetaLong());
insertThetaLong(memOut, thetaLong);
//Flags: BigEnd=0, ReadOnly=0, Empty=X, compact=0, ordered=0
final byte flags = isEmpty() ? (byte) EMPTY_FLAG_MASK : 0;
insertFlags(memOut, flags);
//Data
final int arrLongs = 1 << getLgArrLongs();
final long[] cache = getCache();
memOut.putLongArray(preBytes, cache, 0, arrLongs); //load byteArrOut
return byteArrOut;
}
}