blob: 2d477cb9363219b1bb1f2a16b63f94a23dce3fb9 [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.exception.encoding.TsFileEncodingException;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
import org.apache.iotdb.tsfile.utils.ReadWriteForEncodingUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* Encoder for float or double value using rle or two-diff according to following grammar.
*
* <pre>{@code
* float encoder: <maxPointvalue> <encoded-data>
* maxPointvalue := number for accuracy of decimal places, store as unsigned var int
* encoded-data := same as encoder's pattern
* }</pre>
*/
public class FloatEncoder extends Encoder {
private Encoder encoder;
/** number for accuracy of decimal places. */
private int maxPointNumber;
/** maxPointValue = 10^(maxPointNumber). */
private double maxPointValue;
/** flag to check whether maxPointNumber is saved in the stream. */
private boolean isMaxPointNumberSaved;
public FloatEncoder(TSEncoding encodingType, TSDataType dataType, int maxPointNumber) {
super(encodingType);
this.maxPointNumber = maxPointNumber;
calculateMaxPonitNum();
isMaxPointNumberSaved = false;
if (encodingType == TSEncoding.RLE) {
if (dataType == TSDataType.FLOAT) {
encoder = new IntRleEncoder();
} else if (dataType == TSDataType.DOUBLE) {
encoder = new LongRleEncoder();
} else {
throw new TsFileEncodingException(
String.format("data type %s is not supported by FloatEncoder", dataType));
}
} else if (encodingType == TSEncoding.TS_2DIFF) {
if (dataType == TSDataType.FLOAT) {
encoder = new DeltaBinaryEncoder.IntDeltaEncoder();
} else if (dataType == TSDataType.DOUBLE) {
encoder = new DeltaBinaryEncoder.LongDeltaEncoder();
} else {
throw new TsFileEncodingException(
String.format("data type %s is not supported by FloatEncoder", dataType));
}
} else {
throw new TsFileEncodingException(
String.format("%s encoding is not supported by FloatEncoder", encodingType));
}
}
@Override
public void encode(float value, ByteArrayOutputStream out) {
saveMaxPointNumber(out);
int valueInt = convertFloatToInt(value);
encoder.encode(valueInt, out);
}
@Override
public void encode(double value, ByteArrayOutputStream out) {
saveMaxPointNumber(out);
long valueLong = convertDoubleToLong(value);
encoder.encode(valueLong, out);
}
private void calculateMaxPonitNum() {
if (maxPointNumber <= 0) {
maxPointNumber = 0;
maxPointValue = 1;
} else {
maxPointValue = Math.pow(10, maxPointNumber);
}
}
private int convertFloatToInt(float value) {
return (int) Math.round(value * maxPointValue);
}
private long convertDoubleToLong(double value) {
return Math.round(value * maxPointValue);
}
@Override
public void flush(ByteArrayOutputStream out) throws IOException {
encoder.flush(out);
reset();
}
private void reset() {
isMaxPointNumberSaved = false;
}
private void saveMaxPointNumber(ByteArrayOutputStream out) {
if (!isMaxPointNumberSaved) {
ReadWriteForEncodingUtils.writeUnsignedVarInt(maxPointNumber, out);
isMaxPointNumberSaved = true;
}
}
@Override
public int getOneItemMaxSize() {
return encoder.getOneItemMaxSize();
}
@Override
public long getMaxByteSize() {
return encoder.getMaxByteSize();
}
}