blob: e676a6652a154643fc1cef418b77e14a84f3625d [file]
/*
* 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 java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
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 java.lang.foreign.MemorySegment;
import org.apache.datasketches.common.ResizeFactor;
import org.apache.datasketches.common.Util;
import org.apache.datasketches.thetacommon.ThetaUtil;
/**
* The parent class for HeapUpdatableThetaSketches.
*
* @author Lee Rhodes
*/
abstract class HeapUpdateSketch extends UpdatableThetaSketch {
final int lgNomLongs_;
private final float p_;
private final ResizeFactor rf_;
HeapUpdateSketch(final int lgNomLongs, final long seed, final float p, final ResizeFactor rf) {
super(seed);
lgNomLongs_ = Math.max(lgNomLongs, ThetaUtil.MIN_LG_NOM_LONGS);
p_ = p;
rf_ = rf;
}
//ThetaSketch
@Override
public int getCurrentBytes() {
final int preLongs = getCurrentPreambleLongs();
final int dataLongs = getCurrentDataLongs();
return preLongs + dataLongs << 3;
}
//UpdatableThetaSketch
@Override
public final int getLgNomLongs() {
return lgNomLongs_;
}
@Override
float getP() {
return p_;
}
@Override
public ResizeFactor getResizeFactor() {
return rf_;
}
//restricted methods
@Override
short getSeedHash() {
return Util.computeSeedHash(getSeed());
}
//Used by HeapAlphaSketch and HeapQuickSelectThetaSketch / UpdatableThetaSketch
byte[] toByteArray(final int preLongs, final byte familyID) {
if (isDirty()) { rebuild(); }
checkIllegalCurCountAndEmpty(isEmpty(), getRetainedEntries(true));
final int preBytes = (preLongs << 3) & 0X3F; //24 bytes; mask to 6 bits
final int dataBytes = getCurrentDataLongs() << 3;
final byte[] byteArrOut = new byte[preBytes + dataBytes];
final MemorySegment segOut = MemorySegment.ofArray(byteArrOut);
//preamble first 8 bytes. Note: only compact can be reduced to 8 bytes.
final int lgRf = getResizeFactor().lg() & 0x3; //mask to 2 bits
insertPreLongs(segOut, preLongs); //byte 0 low 6 bits
insertLgResizeFactor(segOut, lgRf); //byte 0 high 2 bits
insertSerVer(segOut, SER_VER); //byte 1
insertFamilyID(segOut, familyID); //byte 2
insertLgNomLongs(segOut, getLgNomLongs()); //byte 3
insertLgArrLongs(segOut, getLgArrLongs()); //byte 4
insertSeedHash(segOut, getSeedHash()); //bytes 6 & 7
insertCurCount(segOut, this.getRetainedEntries(true));
insertP(segOut, getP());
final long thetaLong =
correctThetaOnCompact(isEmpty(), getRetainedEntries(true), getThetaLong());
insertThetaLong(segOut, thetaLong);
//Flags: BigEnd=0, ReadOnly=0, Empty=X, compact=0, ordered=0
final byte flags = isEmpty() ? (byte) EMPTY_FLAG_MASK : 0;
insertFlags(segOut, flags);
//Data
final int arrLongs = 1 << getLgArrLongs();
final long[] cache = getCache();
//segOut.putLongArray(preBytes, cache, 0, arrLongs); //load byteArrOut
MemorySegment.copy(cache, 0, segOut, JAVA_LONG_UNALIGNED, preBytes, arrLongs);
return byteArrOut;
}
}