| /* |
| * 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; |
| |
| public class SDTEncoder { |
| |
| // the last read time and value if upperDoor >= lowerDoor meaning out of compDeviation range, will |
| // store lastReadPair |
| private long lastReadTimestamp; |
| |
| private long lastReadLong; |
| private double lastReadDouble; |
| private int lastReadInt; |
| private float lastReadFloat; |
| |
| // the last stored time and vlaue we compare current point against lastStoredPair |
| private long lastStoredTimestamp; |
| |
| private long lastStoredLong; |
| private double lastStoredDouble; |
| private int lastStoredInt; |
| private float lastStoredFloat; |
| |
| // the maximum curUpperSlope between the lastStoredPoint to the current point upperDoor can only |
| // open up |
| private double upperDoor; |
| |
| // the minimum curLowerSlope between the lastStoredPoint to the current point lowerDoor can only |
| // open downard |
| private double lowerDoor; |
| |
| // the maximum absolute difference the user set if the data's value is within compDeviation, it |
| // will be compressed and discarded after compression, it will only store out of range <time, |
| // data> to form the trend |
| private double compDeviation; |
| |
| // the minimum time distance between two stored data points if current point time to the last |
| // stored point time distance <= compMinTime, current point will NOT be stored regardless of |
| // compression deviation |
| private long compMinTime; |
| |
| // the maximum time distance between two stored data points if current point time to the last |
| // stored point time distance >= compMaxTime, current point will be stored regardless of |
| // compression deviation |
| private long compMaxTime; |
| |
| // isFirstValue is true when the encoder takes the first point or reset() when cur point's |
| // distance to the last stored point's distance exceeds compMaxTime |
| private boolean isFirstValue; |
| |
| public SDTEncoder() { |
| upperDoor = Integer.MIN_VALUE; |
| lowerDoor = Integer.MAX_VALUE; |
| compDeviation = -1; |
| compMinTime = 0; |
| compMaxTime = Long.MAX_VALUE; |
| isFirstValue = true; |
| } |
| |
| public boolean encodeFloat(long time, float value) { |
| // store the first time and value pair |
| if (isFirstValue(time, value)) { |
| return true; |
| } |
| |
| // if current point to the last stored point's time distance is within compMinTime, |
| // will not check two doors nor store any point within the compMinTime time range |
| if (time - lastStoredTimestamp <= compMinTime) { |
| return false; |
| } |
| |
| // if current point to the last stored point's time distance is larger than compMaxTime, |
| // will reset two doors, and store current point |
| if (time - lastStoredTimestamp >= compMaxTime) { |
| reset(time, value); |
| return true; |
| } |
| |
| double curUpperSlope = (value - lastStoredFloat - compDeviation) / (time - lastStoredTimestamp); |
| if (curUpperSlope > upperDoor) { |
| upperDoor = curUpperSlope; |
| } |
| |
| double curLowerSlope = (value - lastStoredFloat + compDeviation) / (time - lastStoredTimestamp); |
| if (curLowerSlope < lowerDoor) { |
| lowerDoor = curLowerSlope; |
| } |
| |
| // current point to the lastStoredPair's value exceeds compDev, will store lastReadPair and |
| // update two doors |
| if (upperDoor >= lowerDoor) { |
| lastStoredTimestamp = lastReadTimestamp; |
| lastStoredFloat = lastReadFloat; |
| upperDoor = (value - lastStoredFloat - compDeviation) / (time - lastStoredTimestamp); |
| lowerDoor = (value - lastStoredFloat + compDeviation) / (time - lastStoredTimestamp); |
| lastReadFloat = value; |
| lastReadTimestamp = time; |
| return true; |
| } |
| |
| lastReadFloat = value; |
| lastReadTimestamp = time; |
| return false; |
| } |
| |
| public boolean encodeLong(long time, long value) { |
| // store the first time and value pair |
| if (isFirstValue(time, value)) { |
| return true; |
| } |
| |
| // if current point to the last stored point's time distance is within compMinTime, |
| // will not check two doors nor store any point within the compMinTime time range |
| if (time - lastStoredTimestamp <= compMinTime) { |
| return false; |
| } |
| |
| // if current point to the last stored point's time distance is larger than compMaxTime, |
| // will reset two doors, and store current point |
| if (time - lastStoredTimestamp >= compMaxTime) { |
| reset(time, value); |
| return true; |
| } |
| |
| double curUpperSlope = (value - lastStoredLong - compDeviation) / (time - lastStoredTimestamp); |
| if (curUpperSlope > upperDoor) { |
| upperDoor = curUpperSlope; |
| } |
| |
| double curLowerSlope = (value - lastStoredLong + compDeviation) / (time - lastStoredTimestamp); |
| if (curLowerSlope < lowerDoor) { |
| lowerDoor = curLowerSlope; |
| } |
| |
| // current point to the lastStoredPair's value exceeds compDev, will store lastReadPair and |
| // update two doors |
| if (upperDoor >= lowerDoor) { |
| lastStoredLong = lastReadLong; |
| lastStoredTimestamp = lastReadTimestamp; |
| upperDoor = (value - lastStoredLong - compDeviation) / (time - lastStoredTimestamp); |
| lowerDoor = (value - lastStoredLong + compDeviation) / (time - lastStoredTimestamp); |
| lastReadLong = value; |
| lastReadTimestamp = time; |
| return true; |
| } |
| |
| lastReadLong = value; |
| lastReadTimestamp = time; |
| return false; |
| } |
| |
| public boolean encodeInt(long time, int value) { |
| // store the first time and value pair |
| if (isFirstValue(time, value)) { |
| return true; |
| } |
| |
| // if current point to the last stored point's time distance is within compMinTime, |
| // will not check two doors nor store any point within the compMinTime time range |
| if (time - lastStoredTimestamp <= compMinTime) { |
| return false; |
| } |
| |
| // if current point to the last stored point's time distance is larger than compMaxTime, |
| // will reset two doors, and store current point |
| if (time - lastStoredTimestamp >= compMaxTime) { |
| reset(time, value); |
| return true; |
| } |
| |
| double curUpperSlope = (value - lastStoredInt - compDeviation) / (time - lastStoredTimestamp); |
| if (curUpperSlope > upperDoor) { |
| upperDoor = curUpperSlope; |
| } |
| |
| double curLowerSlope = (value - lastStoredInt + compDeviation) / (time - lastStoredTimestamp); |
| if (curLowerSlope < lowerDoor) { |
| lowerDoor = curLowerSlope; |
| } |
| |
| // current point to the lastStoredPair's value exceeds compDev, will store lastReadPair and |
| // update two doors |
| if (upperDoor >= lowerDoor) { |
| lastStoredTimestamp = lastReadTimestamp; |
| lastStoredInt = lastReadInt; |
| upperDoor = (value - lastStoredInt - compDeviation) / (time - lastStoredTimestamp); |
| lowerDoor = (value - lastStoredInt + compDeviation) / (time - lastStoredTimestamp); |
| lastReadInt = value; |
| lastReadTimestamp = time; |
| return true; |
| } |
| |
| lastReadInt = value; |
| lastReadTimestamp = time; |
| return false; |
| } |
| |
| public boolean encodeDouble(long time, double value) { |
| // store the first time and value pair |
| if (isFirstValue(time, value)) { |
| return true; |
| } |
| |
| // if current point to the last stored point's time distance is within compMinTime, |
| // will not check two doors nor store any point within the compMinTime time range |
| if (time - lastStoredTimestamp <= compMinTime) { |
| return false; |
| } |
| |
| // if current point to the last stored point's time distance is larger than compMaxTime, |
| // will reset two doors, and store current point; |
| if (time - lastStoredTimestamp >= compMaxTime) { |
| reset(time, value); |
| return true; |
| } |
| |
| double curUpperSlope = |
| (value - lastStoredDouble - compDeviation) / (time - lastStoredTimestamp); |
| if (curUpperSlope > upperDoor) { |
| upperDoor = curUpperSlope; |
| } |
| |
| double curLowerSlope = |
| (value - lastStoredDouble + compDeviation) / (time - lastStoredTimestamp); |
| if (curLowerSlope < lowerDoor) { |
| lowerDoor = curLowerSlope; |
| } |
| |
| // current point to the lastStoredPair's value exceeds compDev, will store lastReadPair and |
| // update two doors |
| if (upperDoor >= lowerDoor) { |
| lastStoredTimestamp = lastReadTimestamp; |
| lastStoredDouble = lastReadDouble; |
| upperDoor = (value - lastStoredDouble - compDeviation) / (time - lastStoredTimestamp); |
| lowerDoor = (value - lastStoredDouble + compDeviation) / (time - lastStoredTimestamp); |
| lastReadDouble = value; |
| lastReadTimestamp = time; |
| return true; |
| } |
| |
| lastReadDouble = value; |
| lastReadTimestamp = time; |
| return false; |
| } |
| |
| public int encode(long[] timestamps, double[] values, int batchSize) { |
| int index = 0; |
| for (int i = 0; i < batchSize; i++) { |
| if (encodeDouble(timestamps[i], values[i])) { |
| timestamps[index] = lastStoredTimestamp; |
| values[index] = lastStoredDouble; |
| index++; |
| } |
| } |
| return index; |
| } |
| |
| public int encode(long[] timestamps, int[] values, int batchSize) { |
| int index = 0; |
| for (int i = 0; i < batchSize; i++) { |
| if (encodeInt(timestamps[i], values[i])) { |
| timestamps[index] = lastStoredTimestamp; |
| values[index] = lastStoredInt; |
| index++; |
| } |
| } |
| return index; |
| } |
| |
| public int encode(long[] timestamps, long[] values, int batchSize) { |
| int index = 0; |
| for (int i = 0; i < batchSize; i++) { |
| if (encodeLong(timestamps[i], values[i])) { |
| timestamps[index] = lastStoredTimestamp; |
| values[index] = lastStoredLong; |
| index++; |
| } |
| } |
| return index; |
| } |
| |
| public int encode(long[] timestamps, float[] values, int batchSize) { |
| int index = 0; |
| for (int i = 0; i < batchSize; i++) { |
| if (encodeFloat(timestamps[i], values[i])) { |
| timestamps[index] = lastStoredTimestamp; |
| values[index] = lastStoredFloat; |
| index++; |
| } |
| } |
| return index; |
| } |
| |
| private boolean isFirstValue(long time, float value) { |
| if (isFirstValue) { |
| isFirstValue = false; |
| lastReadTimestamp = time; |
| lastReadFloat = value; |
| lastStoredTimestamp = time; |
| lastStoredFloat = value; |
| return true; |
| } |
| return false; |
| } |
| |
| private boolean isFirstValue(long time, long value) { |
| if (isFirstValue) { |
| isFirstValue = false; |
| lastReadTimestamp = time; |
| lastReadLong = value; |
| lastStoredTimestamp = time; |
| lastStoredLong = value; |
| return true; |
| } |
| return false; |
| } |
| |
| private boolean isFirstValue(long time, int value) { |
| if (isFirstValue) { |
| isFirstValue = false; |
| lastReadTimestamp = time; |
| lastReadInt = value; |
| lastStoredTimestamp = time; |
| lastStoredInt = value; |
| return true; |
| } |
| return false; |
| } |
| |
| private boolean isFirstValue(long time, double value) { |
| if (isFirstValue) { |
| isFirstValue = false; |
| lastReadTimestamp = time; |
| lastReadDouble = value; |
| lastStoredTimestamp = time; |
| lastStoredDouble = value; |
| return true; |
| } |
| return false; |
| } |
| |
| private void reset() { |
| upperDoor = Integer.MIN_VALUE; |
| lowerDoor = Integer.MAX_VALUE; |
| } |
| |
| /** |
| * if current point to the last stored point's time distance >= compMaxTime, will store current |
| * point and reset upperDoor and lowerDoor |
| * |
| * @param time current time |
| * @param value current value |
| */ |
| private void reset(long time, long value) { |
| reset(); |
| lastStoredTimestamp = time; |
| lastStoredLong = value; |
| } |
| |
| private void reset(long time, double value) { |
| reset(); |
| lastStoredTimestamp = time; |
| lastStoredDouble = value; |
| } |
| |
| private void reset(long time, int value) { |
| reset(); |
| lastStoredTimestamp = time; |
| lastStoredInt = value; |
| } |
| |
| private void reset(long time, float value) { |
| reset(); |
| lastStoredTimestamp = time; |
| lastStoredFloat = value; |
| } |
| |
| public void setCompDeviation(double compDeviation) { |
| this.compDeviation = compDeviation; |
| } |
| |
| public double getCompDeviation() { |
| return compDeviation; |
| } |
| |
| public void setCompMinTime(long compMinTime) { |
| this.compMinTime = compMinTime; |
| } |
| |
| public long getCompMinTime() { |
| return compMinTime; |
| } |
| |
| public void setCompMaxTime(long compMaxTime) { |
| this.compMaxTime = compMaxTime; |
| } |
| |
| public long getCompMaxTime() { |
| return compMaxTime; |
| } |
| |
| public long getTime() { |
| return lastStoredTimestamp; |
| } |
| |
| public int getIntValue() { |
| return lastStoredInt; |
| } |
| |
| public double getDoubleValue() { |
| return lastStoredDouble; |
| } |
| |
| public long getLongValue() { |
| return lastStoredLong; |
| } |
| |
| public float getFloatValue() { |
| return lastStoredFloat; |
| } |
| } |