blob: 3100514e116c2162f8b1490a821ae77a974922f1 [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.IntPacker;
import org.apache.iotdb.tsfile.encoding.fire.IntFire;
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 FloatSprintzEncoder extends SprintzEncoder {
/** bit packer */
IntPacker packer;
/** Int Fire Predictor * */
IntFire firePred;
/** we save all value in a list and calculate its bitwidth. */
protected Vector<Float> values;
/** convert to integer Buffer * */
int[] convertBuffer;
public FloatSprintzEncoder() {
super();
values = new Vector<Float>();
firePred = new IntFire(2);
convertBuffer = new int[Block_size];
}
protected void reset() {
super.reset();
values.clear();
}
@Override
public int getOneItemMaxSize() {
return 1 + (1 + Block_size) * Integer.BYTES;
}
@Override
public long getMaxByteSize() {
return 1 + (long) (values.size() + 1) * Integer.BYTES;
}
protected int predict(Float value, Float preVlaue) throws TsFileEncodingException {
int 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 {
float preValue = values.get(0);
values.remove(0);
Vector<Integer> convertBufferList = new Vector<>();
for (int itemBuffer : convertBuffer) convertBufferList.add(itemBuffer);
this.bitWidth = ReadWriteForEncodingUtils.getIntMaxBitWidth(convertBufferList);
packer = new IntPacker(this.bitWidth);
byte[] bytes = new byte[bitWidth];
packer.pack8Values(convertBuffer, 0, bytes);
ReadWriteForEncodingUtils.writeIntLittleEndianPaddedOnBitWidth(bitWidth, byteCache, 1);
byteCache.write(ByteBuffer.allocate(Float.BYTES).putFloat(preValue).array());
byteCache.write(bytes, 0, bytes.length);
}
protected int delta(Float value, Float preValue) {
return Float.floatToIntBits(value) - Float.floatToIntBits(preValue);
}
protected int fire(Float value, Float preValue) {
int prev = Float.floatToIntBits(preValue);
int val = Float.floatToIntBits(value);
int pred = firePred.predict(prev);
int 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);
SinglePrecisionEncoderV2 encoder = new SinglePrecisionEncoderV2();
for (float val : values) {
encoder.encode(val, out);
}
encoder.flush(out);
}
reset();
}
@Override
public void encode(float 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 Float Type value with with Sprintz", e);
}
}
}
}