blob: bd5183cc0363639094fb6b3bbdc24ca4145b2dd6 [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.cpc;
import static org.apache.datasketches.Util.computeSeedHash;
import static org.apache.datasketches.cpc.PreambleUtil.checkCapacity;
import static org.apache.datasketches.cpc.PreambleUtil.checkLoPreamble;
import static org.apache.datasketches.cpc.PreambleUtil.getDefinedPreInts;
import static org.apache.datasketches.cpc.PreambleUtil.getFiCol;
import static org.apache.datasketches.cpc.PreambleUtil.getFormatOrdinal;
import static org.apache.datasketches.cpc.PreambleUtil.getHipAccum;
import static org.apache.datasketches.cpc.PreambleUtil.getKxP;
import static org.apache.datasketches.cpc.PreambleUtil.getLgK;
import static org.apache.datasketches.cpc.PreambleUtil.getNumCoupons;
import static org.apache.datasketches.cpc.PreambleUtil.getNumSv;
import static org.apache.datasketches.cpc.PreambleUtil.getPreInts;
import static org.apache.datasketches.cpc.PreambleUtil.getSeedHash;
import static org.apache.datasketches.cpc.PreambleUtil.getSvLengthInts;
import static org.apache.datasketches.cpc.PreambleUtil.getSvStream;
import static org.apache.datasketches.cpc.PreambleUtil.getWLengthInts;
import static org.apache.datasketches.cpc.PreambleUtil.getWStream;
import static org.apache.datasketches.cpc.PreambleUtil.isCompressed;
import static org.apache.datasketches.cpc.PreambleUtil.putEmptyHip;
import static org.apache.datasketches.cpc.PreambleUtil.putEmptyMerged;
import static org.apache.datasketches.cpc.PreambleUtil.putPinnedSlidingHip;
import static org.apache.datasketches.cpc.PreambleUtil.putPinnedSlidingHipNoSv;
import static org.apache.datasketches.cpc.PreambleUtil.putPinnedSlidingMerged;
import static org.apache.datasketches.cpc.PreambleUtil.putPinnedSlidingMergedNoSv;
import static org.apache.datasketches.cpc.PreambleUtil.putSparseHybridHip;
import static org.apache.datasketches.cpc.PreambleUtil.putSparseHybridMerged;
import static org.apache.datasketches.cpc.RuntimeAsserts.rtAssert;
import org.apache.datasketches.memory.Memory;
import org.apache.datasketches.memory.WritableMemory;
/**
* @author Lee Rhodes
* @author Kevin Lang
*/
final class CompressedState {
private static final String LS = System.getProperty("line.separator");
private boolean csvIsValid = false;
private boolean windowIsValid = false;
final int lgK;
final short seedHash;
int fiCol = 0;
boolean mergeFlag = false; //compliment of HIP Flag
long numCoupons = 0;
double kxp;
double hipEstAccum = 0.0;
int numCsv = 0;
int[] csvStream = null; //may be longer than required
int csvLengthInts = 0;
int[] cwStream = null; //may be longer than required
int cwLengthInts = 0;
//int cpcRequiredBytes = 0;
private CompressedState(final int lgK, final short seedHash) {
this.lgK = lgK;
this.seedHash = seedHash;
kxp = 1 << lgK;
}
static CompressedState compress(final CpcSketch source) {
final short seedHash = computeSeedHash(source.seed);
final CompressedState target = new CompressedState(source.lgK, seedHash);
target.fiCol = source.fiCol;
target.mergeFlag = source.mergeFlag;
target.numCoupons = source.numCoupons;
target.kxp = source.kxp;
target.hipEstAccum = source.hipEstAccum;
target.csvIsValid = source.pairTable != null;
target.windowIsValid = (source.slidingWindow != null);
CpcCompression.compress(source, target);
return target;
}
Flavor getFlavor() {
return CpcUtil.determineFlavor(lgK, numCoupons);
}
Format getFormat() {
final int ordinal = ((cwLengthInts > 0) ? 4 : 0)
| ((numCsv > 0) ? 2 : 0)
| ( mergeFlag ? 0 : 1 ); //complement of HIP
return Format.ordinalToFormat(ordinal);
}
int getWindowOffset() {
return CpcUtil.determineCorrectOffset(lgK, numCoupons);
}
long getRequiredSerializedBytes() {
final Format format = getFormat();
final int preInts = getDefinedPreInts(format);
return 4L * (preInts + csvLengthInts + cwLengthInts);
}
static CompressedState importFromMemory(final Memory mem) {
checkLoPreamble(mem);
rtAssert(isCompressed(mem));
final int lgK = getLgK(mem);
final short seedHash = getSeedHash(mem);
final CompressedState state = new CompressedState(lgK, seedHash);
final int fmtOrd = getFormatOrdinal(mem);
final Format format = Format.ordinalToFormat(fmtOrd);
state.mergeFlag = !((fmtOrd & 1) > 0); //merge flag is complement of HIP
state.csvIsValid = (fmtOrd & 2) > 0;
state.windowIsValid = (fmtOrd & 4) > 0;
switch (format) {
case EMPTY_MERGED :
case EMPTY_HIP : {
checkCapacity(mem.getCapacity(), 8L);
break;
}
case SPARSE_HYBRID_MERGED : {
//state.fiCol = getFiCol(mem);
state.numCoupons = getNumCoupons(mem);
state.numCsv = (int) state.numCoupons; //only true for sparse_hybrid
state.csvLengthInts = getSvLengthInts(mem);
//state.cwLength = getCwLength(mem);
//state.kxp = getKxP(mem);
//state.hipEstAccum = getHipAccum(mem);
checkCapacity(mem.getCapacity(), state.getRequiredSerializedBytes());
//state.cwStream = getCwStream(mem);
state.csvStream = getSvStream(mem);
break;
}
case SPARSE_HYBRID_HIP : {
//state.fiCol = getFiCol(mem);
state.numCoupons = getNumCoupons(mem);
state.numCsv = (int) state.numCoupons; //only true for sparse_hybrid
state.csvLengthInts = getSvLengthInts(mem);
//state.cwLength = getCwLength(mem);
state.kxp = getKxP(mem);
state.hipEstAccum = getHipAccum(mem);
checkCapacity(mem.getCapacity(), state.getRequiredSerializedBytes());
//state.cwStream = getCwStream(mem);
state.csvStream = getSvStream(mem);
break;
}
case PINNED_SLIDING_MERGED_NOSV : {
state.fiCol = getFiCol(mem);
state.numCoupons = getNumCoupons(mem);
//state.numCsv = getNumCsv(mem);
//state.csvLength = getCsvLength(mem);
state.cwLengthInts = getWLengthInts(mem);
//state.kxp = getKxP(mem);
//state.hipEstAccum = getHipAccum(mem);
checkCapacity(mem.getCapacity(), state.getRequiredSerializedBytes());
state.cwStream = getWStream(mem);
//state.csvStream = getCsvStream(mem);
break;
}
case PINNED_SLIDING_HIP_NOSV : {
state.fiCol = getFiCol(mem);
state.numCoupons = getNumCoupons(mem);
//state.numCsv = getNumCsv(mem);
//state.csvLength = getCsvLength(mem);
state.cwLengthInts = getWLengthInts(mem);
state.kxp = getKxP(mem);
state.hipEstAccum = getHipAccum(mem);
checkCapacity(mem.getCapacity(), state.getRequiredSerializedBytes());
state.cwStream = getWStream(mem);
//state.csvStream = getCsvStream(mem);
break;
}
case PINNED_SLIDING_MERGED : {
state.fiCol = getFiCol(mem);
state.numCoupons = getNumCoupons(mem);
state.numCsv = getNumSv(mem);
state.csvLengthInts = getSvLengthInts(mem);
state.cwLengthInts = getWLengthInts(mem);
//state.kxp = getKxP(mem);
//state.hipEstAccum = getHipAccum(mem);
checkCapacity(mem.getCapacity(), state.getRequiredSerializedBytes());
state.cwStream = getWStream(mem);
state.csvStream = getSvStream(mem);
break;
}
case PINNED_SLIDING_HIP : {
state.fiCol = getFiCol(mem);
state.numCoupons = getNumCoupons(mem);
state.numCsv = getNumSv(mem);
state.csvLengthInts = getSvLengthInts(mem);
state.cwLengthInts = getWLengthInts(mem);
state.kxp = getKxP(mem);
state.hipEstAccum = getHipAccum(mem);
checkCapacity(mem.getCapacity(), state.getRequiredSerializedBytes());
state.cwStream = getWStream(mem);
state.csvStream = getSvStream(mem);
break;
}
}
checkCapacity(mem.getCapacity(),
4L * (getPreInts(mem) + state.csvLengthInts + state.cwLengthInts));
return state;
}
void exportToMemory(final WritableMemory wmem) {
final Format format = getFormat();
switch (format) {
case EMPTY_MERGED : {
putEmptyMerged(wmem, lgK, seedHash);
break;
}
case EMPTY_HIP : {
putEmptyHip(wmem, lgK, seedHash);
break;
}
case SPARSE_HYBRID_MERGED : {
putSparseHybridMerged(wmem,
lgK,
(int) numCoupons, //unsigned
csvLengthInts,
seedHash,
csvStream);
break;
}
case SPARSE_HYBRID_HIP : {
putSparseHybridHip(wmem,
lgK,
(int) numCoupons, //unsigned
csvLengthInts,
kxp,
hipEstAccum,
seedHash,
csvStream);
break;
}
case PINNED_SLIDING_MERGED_NOSV : {
putPinnedSlidingMergedNoSv(wmem,
lgK,
fiCol,
(int) numCoupons, //unsigned
cwLengthInts,
seedHash,
cwStream);
break;
}
case PINNED_SLIDING_HIP_NOSV : {
putPinnedSlidingHipNoSv(wmem,
lgK,
fiCol,
(int) numCoupons, //unsigned
cwLengthInts,
kxp,
hipEstAccum,
seedHash,
cwStream);
break;
}
case PINNED_SLIDING_MERGED : {
putPinnedSlidingMerged(wmem,
lgK,
fiCol,
(int) numCoupons, //unsigned
numCsv,
csvLengthInts,
cwLengthInts,
seedHash,
csvStream,
cwStream);
break;
}
case PINNED_SLIDING_HIP : {
putPinnedSlidingHip(wmem,
lgK,
fiCol,
(int) numCoupons, //unsigned
numCsv,
kxp,
hipEstAccum,
csvLengthInts,
cwLengthInts,
seedHash,
csvStream,
cwStream);
break;
}
}
}
@Override
public String toString() {
return toString(this, false);
}
public static String toString(final CompressedState state, final boolean detail) {
final StringBuilder sb = new StringBuilder();
sb.append("CompressedState").append(LS);
sb.append(" Flavor : ").append(state.getFlavor()).append(LS);
sb.append(" Format : ").append(state.getFormat()).append(LS);
sb.append(" lgK : ").append(state.lgK).append(LS);
sb.append(" seedHash : ").append(state.seedHash).append(LS);
sb.append(" fiCol : ").append(state.fiCol).append(LS);
sb.append(" mergeFlag : ").append(state.mergeFlag).append(LS);
sb.append(" csvStream : ").append(state.csvIsValid).append(LS);
sb.append(" cwStream : ").append(state.windowIsValid).append(LS);
sb.append(" numCoupons : ").append(state.numCoupons).append(LS);
sb.append(" kxp : ").append(state.kxp).append(LS);
sb.append(" hipAccum : ").append(state.hipEstAccum).append(LS);
sb.append(" numCsv : ").append(state.numCsv).append(LS);
sb.append(" csvLengthInts : ").append(state.csvLengthInts).append(LS);
sb.append(" csLength : ").append(state.cwLengthInts).append(LS);
if (detail) {
if (state.csvStream != null) {
sb.append(" CsvStream : ").append(LS);
for (int i = 0; i < state.csvLengthInts; i++) {
sb.append(String.format("%8d %12d" + LS, i, state.csvStream[i]));
}
}
if (state.cwStream != null) {
sb.append(" CwStream : ").append(LS);
for (int i = 0; i < state.cwLengthInts; i++) {
sb.append(String.format("%8d %12d" + LS, i, state.cwStream[i]));
}
}
}
return sb.toString();
}
}