blob: 9a9ba4cac0c4b89613a3d69c54556ffadbc46548 [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.iotdb.tsfile.encoding.encoder;
import org.apache.iotdb.tsfile.encoding.bitpacking.LongPacker;
import org.apache.iotdb.tsfile.encoding.fire.LongFire;
import org.apache.iotdb.tsfile.exception.encoding.TsFileEncodingException;
import org.apache.iotdb.tsfile.utils.ReadWriteForEncodingUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Vector;
public class DoubleSprintzEncoder extends SprintzEncoder {
// bit packer
LongPacker packer;
// Long Fire Predictor
LongFire firePred;
// we save all value in a list and calculate its bitWidth
protected Vector<Double> values;
// convert to Long Buffer
long[] convertBuffer;
public DoubleSprintzEncoder() {
super();
values = new Vector<>();
firePred = new LongFire(3);
convertBuffer = new long[Block_size];
}
@Override
protected void reset() {
super.reset();
values.clear();
}
@Override
public int getOneItemMaxSize() {
return 1 + (1 + Block_size) * Double.BYTES;
}
@Override
public long getMaxByteSize() {
return 1 + (long) (values.size() + 1) * Double.BYTES;
}
protected long predict(Double value, Double preVlaue) throws TsFileEncodingException {
long pred;
if (predictMethod.equals("delta")) {
pred = delta(value, preVlaue);
} else if (predictMethod.equals("fire")) {
pred = fire(value, preVlaue);
} else {
throw new TsFileEncodingException(
"Config: Predict Method {} of SprintzEncoder is not supported.");
}
if (pred <= 0) {
pred = -2 * pred;
} else {
pred = 2 * pred - 1; // TODO:overflow
}
return pred;
}
@Override
protected void bitPack() throws IOException {
final double preValue = values.get(0);
values.remove(0);
Vector<Long> convertBufferList = new Vector<>();
for (long itemBuffer : convertBuffer) {
convertBufferList.add(itemBuffer);
}
this.bitWidth = ReadWriteForEncodingUtils.getLongMaxBitWidth(convertBufferList);
packer = new LongPacker(this.bitWidth);
byte[] bytes = new byte[bitWidth];
packer.pack8Values(convertBuffer, 0, bytes);
ReadWriteForEncodingUtils.writeIntLittleEndianPaddedOnBitWidth(bitWidth, byteCache, 1);
byteCache.write(ByteBuffer.allocate(8).putDouble(preValue).array());
byteCache.write(bytes, 0, bytes.length);
}
protected long delta(Double value, Double preValue) {
return Double.doubleToLongBits(value) - Double.doubleToLongBits(preValue);
}
protected long fire(Double value, Double preValue) {
long prev = Double.doubleToLongBits(preValue);
long val = Double.doubleToLongBits(value);
long pred = firePred.predict(prev);
long err = val - pred;
firePred.train(prev, val, err);
return err;
}
@Override
public void flush(ByteArrayOutputStream out) throws IOException {
if (byteCache.size() > 0) {
byteCache.writeTo(out);
}
if (!values.isEmpty()) {
int size = values.size();
size |= (1 << 7);
ReadWriteForEncodingUtils.writeIntLittleEndianPaddedOnBitWidth(size, out, 1);
DoublePrecisionEncoderV2 encoder = new DoublePrecisionEncoderV2();
for (double val : values) {
encoder.encode(val, out);
}
encoder.flush(out);
}
reset();
}
@Override
public void encode(double value, ByteArrayOutputStream out) {
if (!isFirstCached) {
values.add(value);
isFirstCached = true;
return;
} else {
values.add(value);
}
if (values.size() == Block_size + 1) {
try {
firePred.reset();
for (int i = 1; i <= Block_size; i++) {
convertBuffer[i - 1] = predict(values.get(i), values.get(i - 1));
}
bitPack();
isFirstCached = false;
values.clear();
groupNum++;
if (groupNum == groupMax) {
flush(out);
}
} catch (IOException e) {
logger.error("Error occured when encoding INT32 Type value with with Sprintz", e);
}
}
}
}