blob: 8ee358bfed010da678c49039ae2bb69d2a0ff0ad [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.kll;
import static org.apache.datasketches.kll.KllPreambleUtil.DATA_START_ADR;
import static org.apache.datasketches.kll.KllPreambleUtil.PREAMBLE_INTS_FULL;
import static org.apache.datasketches.kll.KllPreambleUtil.SERIAL_VERSION_UPDATABLE;
import static org.apache.datasketches.kll.KllPreambleUtil.UPDATABLE_BIT_MASK;
import static org.apache.datasketches.kll.KllPreambleUtil.getMemoryK;
import static org.apache.datasketches.kll.KllPreambleUtil.getMemoryLevelZeroSortedFlag;
import static org.apache.datasketches.kll.KllPreambleUtil.getMemoryM;
import static org.apache.datasketches.kll.KllPreambleUtil.getMemoryMinK;
import static org.apache.datasketches.kll.KllPreambleUtil.getMemoryN;
import static org.apache.datasketches.kll.KllPreambleUtil.getMemoryNumLevels;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemoryFamilyID;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemoryFlags;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemoryK;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemoryLevelZeroSortedFlag;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemoryM;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemoryMinK;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemoryN;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemoryNumLevels;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemoryPreInts;
import static org.apache.datasketches.kll.KllPreambleUtil.setMemorySerVer;
import static org.apache.datasketches.kll.KllSketch.Error.NOT_SINGLE_ITEM;
import static org.apache.datasketches.kll.KllSketch.Error.TGT_IS_READ_ONLY;
import static org.apache.datasketches.kll.KllSketch.Error.kllSketchThrow;
import static org.apache.datasketches.kll.KllSketch.SketchType.DOUBLES_SKETCH;
import org.apache.datasketches.common.Family;
import org.apache.datasketches.memory.MemoryRequestServer;
import org.apache.datasketches.memory.WritableMemory;
/**
* This class implements an off-heap doubles KllSketch via a WritableMemory instance of the sketch.
*
* <p>Please refer to the documentation in the package-info:<br>
* {@link org.apache.datasketches.kll}</p>
*
* @author Lee Rhodes, Kevin Lang
*/
class KllDirectDoublesSketch extends KllDoublesSketch {
/**
* The constructor with Memory that can be off-heap.
* @param wmem the current WritableMemory
* @param memReqSvr the given MemoryRequestServer to request a larger WritableMemory
* @param memVal the MemoryValadate object
*/
KllDirectDoublesSketch(final WritableMemory wmem, final MemoryRequestServer memReqSvr,
final KllMemoryValidate memVal) {
super(wmem, memReqSvr);
levelsArr = memVal.levelsArr;
}
/**
* Create a new instance of this sketch.
* @param k parameter that controls size of the sketch and accuracy of estimates
* @param m parameter that controls the minimum level width in items.
* @param dstMem the given destination WritableMemory object for use by the sketch
* @param memReqSvr the given MemoryRequestServer to request a larger WritableMemory
* @return a new instance of this sketch
*/
static KllDirectDoublesSketch newDirectInstance(final int k, final int m, final WritableMemory dstMem,
final MemoryRequestServer memReqSvr) {
setMemoryPreInts(dstMem, PREAMBLE_INTS_FULL);
setMemorySerVer(dstMem, SERIAL_VERSION_UPDATABLE);
setMemoryFamilyID(dstMem, Family.KLL.getID());
setMemoryFlags(dstMem, UPDATABLE_BIT_MASK);
setMemoryK(dstMem, k);
setMemoryM(dstMem, m);
setMemoryN(dstMem, 0);
setMemoryMinK(dstMem, k);
setMemoryNumLevels(dstMem, 1);
int offset = DATA_START_ADR;
dstMem.putIntArray(offset, new int[] {k, k}, 0, 2);
offset += 2 * Integer.BYTES;
dstMem.putDoubleArray(offset, new double[] {Double.NaN, Double.NaN}, 0, 2);
offset += 2 * Double.BYTES;
dstMem.putDoubleArray(offset, new double[k], 0, k);
final KllMemoryValidate memVal = new KllMemoryValidate(dstMem, DOUBLES_SKETCH);
return new KllDirectDoublesSketch(dstMem, memReqSvr, memVal);
}
@Override
public int getK() {
return getMemoryK(wmem);
}
@Override
public long getN() {
return getMemoryN(wmem);
}
@Override //returns entire array including empty space at bottom
double[] getDoubleItemsArray() {
final int capacityItems = levelsArr[getNumLevels()];
final double[] quantilesArr = new double[capacityItems];
final int levelsBytes = levelsArr.length * Integer.BYTES; //updatable format
final int offset = DATA_START_ADR + levelsBytes + 2 * Double.BYTES;
wmem.getDoubleArray(offset, quantilesArr, 0, capacityItems);
return quantilesArr;
}
@Override
double getDoubleSingleItem() {
if (!isSingleItem()) { kllSketchThrow(NOT_SINGLE_ITEM); return Double.NaN; }
final int k = getK();
final int offset = DATA_START_ADR + 2 * Integer.BYTES + (2 + k - 1) * Double.BYTES;
return wmem.getDouble(offset);
}
@Override
int getM() {
return getMemoryM(wmem);
}
@Override
double getMaxDoubleItem() {
final int offset = DATA_START_ADR + getLevelsArray().length * Integer.BYTES + Double.BYTES;
return wmem.getDouble(offset);
}
@Override
double getMinDoubleItem() {
final int offset = DATA_START_ADR + getLevelsArray().length * Integer.BYTES;
return wmem.getDouble(offset);
}
@Override
int getMinK() {
return getMemoryMinK(wmem);
}
@Override
void incN() {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
long n = getMemoryN(wmem);
setMemoryN(wmem, ++n);
}
@Override
void incNumLevels() {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
int numLevels = getMemoryNumLevels(wmem);
setMemoryNumLevels(wmem, ++numLevels);
}
@Override
boolean isLevelZeroSorted() {
return getMemoryLevelZeroSortedFlag(wmem);
}
@Override
void setDoubleItemsArray(final double[] doubleItems) {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
final int offset = DATA_START_ADR + getLevelsArray().length * Integer.BYTES + 2 * Double.BYTES;
wmem.putDoubleArray(offset, doubleItems, 0, doubleItems.length);
}
@Override
void setDoubleItemsArrayAt(final int index, final double item) {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
final int offset =
DATA_START_ADR + getLevelsArray().length * Integer.BYTES + (index + 2) * Double.BYTES;
wmem.putDouble(offset, item);
}
@Override
void setLevelZeroSorted(final boolean sorted) {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
setMemoryLevelZeroSortedFlag(wmem, sorted);
}
@Override
void setMaxDoubleItem(final double item) {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
final int offset = DATA_START_ADR + getLevelsArray().length * Integer.BYTES + Double.BYTES;
wmem.putDouble(offset, item);
}
@Override
void setMinDoubleItem(final double item) {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
final int offset = DATA_START_ADR + getLevelsArray().length * Integer.BYTES;
wmem.putDouble(offset, item);
}
@Override
void setMinK(final int minK) {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
setMemoryMinK(wmem, minK);
}
@Override
void setN(final long n) {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
setMemoryN(wmem, n);
}
@Override
void setNumLevels(final int numLevels) {
if (readOnly) { kllSketchThrow(TGT_IS_READ_ONLY); }
setMemoryNumLevels(wmem, numLevels);
}
}