This is an automated email from the ASF dual-hosted git repository.

hui pushed a commit to branch research/encoding-reorder
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 65dc277b96e9fa64702e9431fdaa84a7b76a7f04
Author: xjz17 <[email protected]>
AuthorDate: Tue Oct 17 20:06:47 2023 +0800

    Create Reger.java
---
 .../org/apache/iotdb/tsfile/encoding/Reger.java    | 3402 ++++++++++++++++++++
 1 file changed, 3402 insertions(+)

diff --git 
a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/Reger.java 
b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/Reger.java
new file mode 100644
index 00000000000..9154c8f6670
--- /dev/null
+++ 
b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/Reger.java
@@ -0,0 +1,3402 @@
+package org.apache.iotdb.tsfile.encoding;
+
+import com.csvreader.CsvReader;
+import com.csvreader.CsvWriter;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.*;
+
+import static java.lang.Math.abs;
+import static java.lang.Math.pow;
+
+public class Reger {
+  public static int getBitWith(int num) {
+    if (num == 0) return 1;
+    else return 32 - Integer.numberOfLeadingZeros(num);
+  }
+  public static boolean containsValue(int[] array, int targetValue) {
+    for (int value : array) {
+      if (value == targetValue) {
+        return true;
+      }
+    }
+    return false;
+  }
+  public static int min3(int a, int b, int c) {
+    if (a < b && a < c) {
+      return 0;
+    } else if (b < c) {
+      return 1;
+    } else {
+      return 2;
+    }
+  }
+
+  public static byte[] int2Bytes(int integer) {
+    byte[] bytes = new byte[4];
+    bytes[0] = (byte) (integer >> 24);
+    bytes[1] = (byte) (integer >> 16);
+    bytes[2] = (byte) (integer >> 8);
+    bytes[3] = (byte) integer;
+    return bytes;
+  }
+  public static void int2Bytes(int integer,int encode_pos , byte[] cur_byte) {
+    cur_byte[encode_pos] = (byte) (integer >> 24);
+    cur_byte[encode_pos+1] = (byte) (integer >> 16);
+    cur_byte[encode_pos+2] = (byte) (integer >> 8);
+    cur_byte[encode_pos+3] = (byte) (integer);
+  }
+  public static void intByte2Bytes(int integer, int encode_pos , byte[] 
cur_byte) {
+    cur_byte[encode_pos] = (byte) (integer);
+  }
+
+  private static void long2intBytes(long integer, int encode_pos , byte[] 
cur_byte) {
+    cur_byte[encode_pos] = (byte) (integer >> 24);
+    cur_byte[encode_pos+1] = (byte) (integer >> 16);
+    cur_byte[encode_pos+2] = (byte) (integer >> 8);
+    cur_byte[encode_pos+3] = (byte) (integer);
+  }
+
+  public static int bytes2Integer(byte[] encoded, int start, int num) {
+    int value = 0;
+    if (num > 4) {
+      System.out.println("bytes2Integer error");
+      return 0;
+    }
+    for (int i = 0; i < num; i++) {
+      value <<= 8;
+      int b = encoded[i + start] & 0xFF;
+      value |= b;
+    }
+    return value;
+  }
+
+  private static long bytesLong2Integer(byte[] encoded, int decode_pos) {
+    long value = 0;
+    for (int i = 0; i < 4; i++) {
+      value <<= 8;
+      int b = encoded[i + decode_pos] & 0xFF;
+      value |= b;
+    }
+    return value;
+  }
+
+  public static void pack8Values(ArrayList<Integer> values, int offset, int 
width, int encode_pos,  byte[] encoded_result) {
+    int bufIdx = 0;
+    int valueIdx = offset;
+    // remaining bits for the current unfinished Integer
+    int leftBit = 0;
+
+    while (valueIdx < 8 + offset) {
+      // buffer is used for saving 32 bits as a part of result
+      int buffer = 0;
+      // remaining size of bits in the 'buffer'
+      int leftSize = 32;
+
+      // encode the left bits of current Integer to 'buffer'
+      if (leftBit > 0) {
+        buffer |= (values.get(valueIdx) << (32 - leftBit));
+        leftSize -= leftBit;
+        leftBit = 0;
+        valueIdx++;
+      }
+
+      while (leftSize >= width && valueIdx < 8 + offset) {
+        // encode one Integer to the 'buffer'
+        buffer |= (values.get(valueIdx)<< (leftSize - width));
+        leftSize -= width;
+        valueIdx++;
+      }
+      // If the remaining space of the buffer can not save the bits for one 
Integer,
+      if (leftSize > 0 && valueIdx < 8 + offset) {
+        // put the first 'leftSize' bits of the Integer into remaining space 
of the
+        // buffer
+        buffer |= (values.get(valueIdx) >>> (width - leftSize));
+        leftBit = width - leftSize;
+      }
+
+      // put the buffer into the final result
+      for (int j = 0; j < 4; j++) {
+        encoded_result[encode_pos] = (byte) ((buffer >>> ((3 - j) * 8)) & 
0xFF);
+        encode_pos ++;
+        bufIdx++;
+        if (bufIdx >= width) {
+          return ;
+        }
+      }
+    }
+//        return encode_pos;
+  }
+
+  public static void unpack8Values(byte[] encoded, int offset,int width,  
ArrayList<Integer> result_list) {
+    int byteIdx = offset;
+    long buffer = 0;
+    // total bits which have read from 'buf' to 'buffer'. i.e.,
+    // number of available bits to be decoded.
+    int totalBits = 0;
+    int valueIdx = 0;
+
+    while (valueIdx < 8) {
+      // If current available bits are not enough to decode one Integer,
+      // then add next byte from buf to 'buffer' until totalBits >= width
+      while (totalBits < width) {
+        buffer = (buffer << 8) | (encoded[byteIdx] & 0xFF);
+        byteIdx++;
+        totalBits += 8;
+      }
+
+      // If current available bits are enough to decode one Integer,
+      // then decode one Integer one by one until left bits in 'buffer' is
+      // not enough to decode one Integer.
+      while (totalBits >= width && valueIdx < 8) {
+        result_list.add ((int) (buffer >>> (totalBits - width)));
+        valueIdx++;
+        totalBits -= width;
+        buffer = buffer & ((1L << totalBits) - 1);
+      }
+    }
+  }
+
+  public static int bitPacking(ArrayList<Integer> numbers, int start, int 
bit_width,int encode_pos,  byte[] encoded_result) {
+    int block_num = (numbers.size()-start) / 8;
+    for(int i=0;i<block_num;i++){
+      pack8Values( numbers, start+i*8, bit_width,encode_pos, encoded_result);
+      encode_pos +=bit_width;
+    }
+
+    return encode_pos;
+
+  }
+
+  public static ArrayList<Integer> decodeBitPacking(
+          byte[] encoded, int decode_pos, int bit_width, int block_size) {
+    ArrayList<Integer> result_list = new ArrayList<>();
+    int block_num = (block_size - 1) / 8;
+
+    for (int i = 0; i < block_num; i++) { // bitpacking
+      unpack8Values( encoded, decode_pos, bit_width,  result_list);
+      decode_pos += bit_width;
+
+    }
+    return result_list;
+  }
+
+  public static byte[] bitWidth2Bytes(int integer) {
+    byte[] bytes = new byte[1];
+    bytes[0] = (byte) integer;
+    return bytes;
+  }
+
+  public static byte[] double2Bytes(double dou) {
+    long value = Double.doubleToRawLongBits(dou);
+    byte[] bytes = new byte[8];
+    for (int i = 0; i < 8; i++) {
+      bytes[i] = (byte) ((value >> 8 * i) & 0xff);
+    }
+    return bytes;
+  }
+
+  public static double bytes2Double(ArrayList<Byte> encoded, int start, int 
num) {
+    if (num > 8) {
+      System.out.println("bytes2Doubleerror");
+      return 0;
+    }
+    long value = 0;
+    for (int i = 0; i < 8; i++) {
+      value |= ((long) (encoded.get(i + start) & 0xff)) << (8 * i);
+    }
+    return Double.longBitsToDouble(value);
+  }
+
+  public static byte[] float2bytes(float f) {
+    int fbit = Float.floatToIntBits(f);
+    byte[] b = new byte[4];
+    for (int i = 0; i < 4; i++) {
+      b[i] = (byte) (fbit >> (24 - i * 8));
+    }
+    int len = b.length;
+    byte[] dest = new byte[len];
+    System.arraycopy(b, 0, dest, 0, len);
+    byte temp;
+    for (int i = 0; i < len / 2; ++i) {
+      temp = dest[i];
+      dest[i] = dest[len - i - 1];
+      dest[len - i - 1] = temp;
+    }
+    return dest;
+  }
+
+  public static float bytes2float(ArrayList<Byte> b, int index) {
+    int l;
+    l = b.get(index);
+    l &= 0xff;
+    l |= ((long) b.get(index + 1) << 8);
+    l &= 0xffff;
+    l |= ((long) b.get(index + 2) << 16);
+    l &= 0xffffff;
+    l |= ((long) b.get(index + 3) << 24);
+    return Float.intBitsToFloat(l);
+  }
+
+  public static int bytes2Integer(ArrayList<Byte> encoded, int start, int num) 
{
+    int value = 0;
+    if (num > 4) {
+      System.out.println("bytes2Integer error");
+      return 0;
+    }
+    for (int i = 0; i < num; i++) {
+      value <<= 8;
+      int b = encoded.get(i + start) & 0xFF;
+      value |= b;
+    }
+    return value;
+  }
+
+  public static int bytes2BitWidth(ArrayList<Byte> encoded, int start, int 
num) {
+    int value = 0;
+    if (num > 4) {
+      System.out.println("bytes2Integer error");
+      return 0;
+    }
+    for (int i = 0; i < num; i++) {
+      value <<= 8;
+      int b = encoded.get(i + start) & 0xFF;
+      value |= b;
+    }
+    return value;
+  }
+
+  public static byte[] bitPacking(ArrayList<Integer> numbers, int bit_width) {
+    int block_num = numbers.size() / 8;
+    byte[] result = new byte[bit_width * block_num];
+    for (int i = 0; i < block_num; i++) {
+      for (int j = 0; j < bit_width; j++) {
+        int tmp_int = 0;
+        for (int k = 0; k < 8; k++) {
+          tmp_int += (((numbers.get(i * 8 + k) >> j) % 2) << k);
+        }
+        result[i * bit_width + j] = (byte) tmp_int;
+      }
+    }
+    return result;
+  }
+
+  public static byte[] bitPacking(ArrayList<ArrayList<Integer>> numbers, int 
index, int bit_width) {
+    int block_num = numbers.size() / 8;
+    byte[] result = new byte[bit_width * block_num];
+    for (int i = 0; i < block_num; i++) {
+      for (int j = 0; j < bit_width; j++) {
+        int tmp_int = 0;
+        for (int k = 0; k < 8; k++) {
+          tmp_int += (((numbers.get(i * 8 + k + 1).get(index) >> j) % 2) << k);
+        }
+        result[i * bit_width + j] = (byte) tmp_int;
+      }
+    }
+    return result;
+  }
+
+  public static byte[] bitPacking(ArrayList<ArrayList<Integer>> numbers, int 
index, int start, int block_num, int bit_width) {
+    block_num = block_num / 8;
+    byte[] result = new byte[bit_width * block_num];
+
+    for (int i = 0; i < block_num; i++) {
+      for (int j = 0; j < bit_width; j++) {
+        int tmp_int = 0;
+        for (int k = 0; k < 8; k++) {
+          tmp_int += (((numbers.get(start + i * 8 + k).get(index) >> j) % 2) 
<< k);
+        }
+        result[i * bit_width + j] = (byte) tmp_int;
+      }
+    }
+    return result;
+  }
+
+  public static ArrayList<Integer> decodebitPacking(
+          ArrayList<Byte> encoded, int decode_pos, int bit_width, int 
min_delta, int block_size) {
+    ArrayList<Integer> result_list = new ArrayList<>();
+    for (int i = 0; i < (block_size - 1) / 8; i++) { // bitpacking  纵向8个,bit 
width是多少列
+      int[] val8 = new int[8];
+      for (int j = 0; j < 8; j++) {
+        val8[j] = 0;
+      }
+      for (int j = 0; j < bit_width; j++) {
+        byte tmp_byte = encoded.get(decode_pos + bit_width - 1 - j);
+        byte[] bit8 = new byte[8];
+        for (int k = 0; k < 8; k++) {
+          bit8[k] = (byte) (tmp_byte & 1);
+          tmp_byte = (byte) (tmp_byte >> 1);
+        }
+        for (int k = 0; k < 8; k++) {
+          val8[k] = val8[k] * 2 + bit8[k];
+        }
+      }
+      for (int j = 0; j < 8; j++) {
+        result_list.add(val8[j] + min_delta);
+      }
+      decode_pos += bit_width;
+    }
+    return result_list;
+  }
+
+  public static int part(ArrayList<ArrayList<Integer>> arr, int index, int 
low, int high) {
+    ArrayList<Integer> tmp = arr.get(low);
+    while (low < high) {
+      while (low < high
+              && (arr.get(high).get(index) > tmp.get(index)
+              || (Objects.equals(arr.get(high).get(index), tmp.get(index))
+              && arr.get(high).get(index ^ 1) >= tmp.get(index ^ 1)))) {
+        high--;
+      }
+      arr.set(low, arr.get(high));
+      while (low < high
+              && (arr.get(low).get(index) < tmp.get(index)
+              || (Objects.equals(arr.get(low).get(index), tmp.get(index))
+              && arr.get(low).get(index ^ 1) <= tmp.get(index ^ 1)))) {
+        low++;
+      }
+      arr.set(high, arr.get(low));
+    }
+    arr.set(low, tmp);
+    return low;
+  }
+
+  public static void quickSort(ArrayList<ArrayList<Integer>> arr, int index, 
int low, int high) {
+    Stack<Integer> stack = new Stack<>();
+    int mid = part(arr, index, low, high);
+    if (mid + 1 < high) {
+      stack.push(mid + 1);
+      stack.push(high);
+    }
+    if (mid - 1 > low) {
+      stack.push(low);
+      stack.push(mid - 1);
+    }
+    while (stack.empty() == false) {
+      high = stack.pop();
+      low = stack.pop();
+      mid = part(arr, index, low, high);
+      if (mid + 1 < high) {
+        stack.push(mid + 1);
+        stack.push(high);
+      }
+      if (mid - 1 > low) {
+        stack.push(low);
+        stack.push(mid - 1);
+      }
+    }
+  }
+
+  public static int getCommon(int m, int n) {
+    int z;
+    while (m % n != 0) {
+      z = m % n;
+      m = n;
+      n = z;
+    }
+    return n;
+  }
+
+  public static void splitTimeStamp3(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> result) {
+    int td_common = 0;
+    for (int i = 1; i < ts_block.size(); i++) {
+      int time_diffi = ts_block.get(i).get(0) - ts_block.get(i - 1).get(0);
+      if (td_common == 0) {
+        if (time_diffi != 0) {
+          td_common = time_diffi;
+          continue;
+        } else {
+          continue;
+        }
+      }
+      if (time_diffi != 0) {
+        td_common = getCommon(time_diffi, td_common);
+        if (td_common == 1) {
+          break;
+        }
+      }
+    }
+    if (td_common == 0) {
+      td_common = 1;
+    }
+
+    int t0 = ts_block.get(0).get(0);
+    for (int i = 0; i < ts_block.size(); i++) {
+      ArrayList<Integer> tmp = new ArrayList<>();
+      int interval_i = (ts_block.get(i).get(0) - t0) / td_common;
+      tmp.add(t0 + interval_i);
+      tmp.add(ts_block.get(i).get(1));
+      ts_block.set(i, tmp);
+    }
+    result.add(td_common);
+  }
+
+  // ------------------------------------------------basic 
function-------------------------------------------------------
+  public static ArrayList<ArrayList<Integer>> getEncodeBitsRegression(
+          ArrayList<ArrayList<Integer>> ts_block,
+          int block_size,
+          ArrayList<Integer> result,
+          ArrayList<Float> theta,
+          int segment_size) {
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+    theta.clear();
+
+    long sum_X_r = 0;
+    long sum_Y_r = 0;
+    long sum_squ_X_r = 0;
+    long sum_squ_XY_r = 0;
+    long sum_X_v = 0;
+    long sum_Y_v = 0;
+    long sum_squ_X_v = 0;
+    long sum_squ_XY_v = 0;
+
+    for (int i = 1; i < block_size; i++) {
+      sum_X_r += (ts_block.get(i - 1).get(0));
+      sum_X_v += ts_block.get(i - 1).get(1);
+      sum_Y_r += (ts_block.get(i).get(0));
+      sum_Y_v += ts_block.get(i).get(1);
+      sum_squ_X_r += ((long) (ts_block.get(i - 1).get(0)) * (ts_block.get(i - 
1).get(0)));
+      sum_squ_X_v += ((long) ts_block.get(i - 1).get(1) * ts_block.get(i - 
1).get(1));
+      sum_squ_XY_r += ((long) (ts_block.get(i - 1).get(0)) * 
(ts_block.get(i).get(0)));
+      sum_squ_XY_v += ((long) ts_block.get(i - 1).get(1) * 
ts_block.get(i).get(1));
+    }
+
+    int m_reg = block_size - 1;
+    float theta0_r = 0.0F;
+    float theta1_r = 1.0F;
+    if (m_reg * sum_squ_X_r != sum_X_r * sum_X_r) {
+      theta0_r =
+              (float) (sum_squ_X_r * sum_Y_r - sum_X_r * sum_squ_XY_r)
+                      / (float) (m_reg * sum_squ_X_r - sum_X_r * sum_X_r);
+      theta1_r =
+              (float) (m_reg * sum_squ_XY_r - sum_X_r * sum_Y_r)
+                      / (float) (m_reg * sum_squ_X_r - sum_X_r * sum_X_r);
+    }
+
+    float theta0_v = 0.0F;
+    float theta1_v = 1.0F;
+    if (m_reg * sum_squ_X_v != sum_X_v * sum_X_v) {
+      theta0_v =
+              (float) (sum_squ_X_v * sum_Y_v - sum_X_v * sum_squ_XY_v)
+                      / (float) (m_reg * sum_squ_X_v - sum_X_v * sum_X_v);
+      theta1_v =
+              (float) (m_reg * sum_squ_XY_v - sum_X_v * sum_Y_v)
+                      / (float) (m_reg * sum_squ_X_v - sum_X_v * sum_X_v);
+    }
+
+
+    ArrayList<Integer> tmp0 = new ArrayList<>();
+    tmp0.add(ts_block.get(0).get(0));
+    tmp0.add(ts_block.get(0).get(1));
+    ts_block_delta.add(tmp0);
+
+    // delta to Regression
+    for (int j = 1; j < block_size; j++) {
+      int epsilon_r =
+               (ts_block.get(j).get(0)
+                      - (int) (theta0_r + theta1_r * (float) ts_block.get(j - 
1).get(0)));
+      int epsilon_v =
+               (ts_block.get(j).get(1)  - (int) ( theta0_v +  theta1_v * 
(float) ts_block.get(j - 1).get(1)));
+
+
+      if (epsilon_r < timestamp_delta_min) {
+        timestamp_delta_min = epsilon_r;
+      }
+      if (epsilon_v < value_delta_min) {
+        value_delta_min = epsilon_v;
+      }
+      ArrayList<Integer> tmp = new ArrayList<>();
+      tmp.add(epsilon_r);
+      tmp.add(epsilon_v);
+      ts_block_delta.add(tmp);
+
+
+
+    }
+
+
+    int max_interval = Integer.MIN_VALUE;
+    int max_value = Integer.MIN_VALUE;
+    int length = 0;
+    for (int j = block_size - 1; j > 0; j--) {
+      int epsilon_r =ts_block_delta.get(j).get(0) - timestamp_delta_min;
+      int epsilon_v =ts_block_delta.get(j).get(1) - value_delta_min;
+
+      length += getBitWith(epsilon_r);
+      length += getBitWith(epsilon_v);
+      if (epsilon_r > max_interval) {
+        max_interval = epsilon_r;
+      }
+      if (epsilon_v > max_value) {
+        max_value = epsilon_v;
+      }
+      ArrayList<Integer> tmp = new ArrayList<>();
+      tmp.add(epsilon_r);
+      tmp.add(epsilon_v);
+      ts_block_delta.set(j, tmp);
+
+
+
+    }
+
+    int max_bit_width_interval = getBitWith(max_interval);
+    int max_bit_width_value = getBitWith(max_value);
+
+    // calculate error
+    result.clear();
+
+    result.add(length);
+    result.add(max_bit_width_interval);
+    result.add(max_bit_width_value);
+
+    result.add(timestamp_delta_min);
+    result.add(value_delta_min);
+
+    theta.add(theta0_r);
+    theta.add(theta1_r);
+    theta.add(theta0_v);
+    theta.add(theta1_v);
+
+    return ts_block_delta;
+  }
+  public static int[][] getEncodeBitsRegression(
+          int[][] ts_block,
+          int block_size,
+          int[] raw_length,
+          float[] theta,
+          int segment_size) {
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+    int[][] ts_block_delta = new int[ts_block.length][2];
+    theta= new float[4];
+
+    long sum_X_r = 0;
+    long sum_Y_r = 0;
+    long sum_squ_X_r = 0;
+    long sum_squ_XY_r = 0;
+    long sum_X_v = 0;
+    long sum_Y_v = 0;
+    long sum_squ_X_v = 0;
+    long sum_squ_XY_v = 0;
+
+    for (int i = 1; i < block_size; i++) {
+      sum_X_r += ts_block[i - 1][0];
+      sum_X_v += ts_block[i - 1][1];
+      sum_Y_r += ts_block[i][0];
+      sum_Y_v += ts_block[i][1];
+      sum_squ_X_r += ((long) (ts_block[i - 1][0]) * (ts_block[i - 1][0]));
+      sum_squ_X_v += ((long) ts_block[i - 1][1] * ts_block[i - 1][1]);
+      sum_squ_XY_r += ((long) (ts_block[i - 1][0]) * (ts_block[i][0]));
+      sum_squ_XY_v += ((long) ts_block[i - 1][1] * ts_block[i][1]);
+    }
+
+    int m_reg = block_size - 1;
+    float theta0_r = 0.0F;
+    float theta1_r = 1.0F;
+    if (m_reg * sum_squ_X_r != sum_X_r * sum_X_r) {
+      theta0_r =
+              (float) (sum_squ_X_r * sum_Y_r - sum_X_r * sum_squ_XY_r)
+                      / (float) (m_reg * sum_squ_X_r - sum_X_r * sum_X_r);
+      theta1_r =
+              (float) (m_reg * sum_squ_XY_r - sum_X_r * sum_Y_r)
+                      / (float) (m_reg * sum_squ_X_r - sum_X_r * sum_X_r);
+    }
+
+    float theta0_v = 0.0F;
+    float theta1_v = 1.0F;
+    if (m_reg * sum_squ_X_v != sum_X_v * sum_X_v) {
+      theta0_v =
+              (float) (sum_squ_X_v * sum_Y_v - sum_X_v * sum_squ_XY_v)
+                      / (float) (m_reg * sum_squ_X_v - sum_X_v * sum_X_v);
+      theta1_v =
+              (float) (m_reg * sum_squ_XY_v - sum_X_v * sum_Y_v)
+                      / (float) (m_reg * sum_squ_X_v - sum_X_v * sum_X_v);
+    }
+
+
+    ts_block_delta[0][0] = ts_block[0][0];
+    ts_block_delta[0][1] = ts_block[0][1];
+
+    // delta to Regression
+    for (int j = 1; j < block_size; j++) {
+      int epsilon_r =
+              (ts_block[j][0]
+                      - (int) (theta0_r + theta1_r * (float) ts_block[j - 
1][0]));
+      int epsilon_v =
+              (ts_block[j][1]  - (int) ( theta0_v +  theta1_v * (float) 
ts_block[j - 1][1]));
+
+
+      if (epsilon_r < timestamp_delta_min) {
+        timestamp_delta_min = epsilon_r;
+      }
+      if (epsilon_v < value_delta_min) {
+        value_delta_min = epsilon_v;
+      }
+      ts_block_delta[j][0] = epsilon_r;
+      ts_block_delta[j][1] = epsilon_v;
+
+    }
+
+
+    int max_interval = Integer.MIN_VALUE;
+    int max_value = Integer.MIN_VALUE;
+    int length = 0;
+    for (int j = block_size - 1; j > 0; j--) {
+      ts_block_delta[j][0] -= timestamp_delta_min;
+      int epsilon_r = ts_block_delta[j][0];
+      ts_block_delta[j][1] -= value_delta_min;
+      int epsilon_v = ts_block_delta[j][1];
+
+      length += getBitWith(ts_block_delta[j][0]);
+      length += getBitWith(ts_block_delta[j][1]);
+
+      if (epsilon_r > max_interval) {
+        max_interval = epsilon_r;
+      }
+      if (epsilon_v > max_value) {
+        max_value = epsilon_v;
+      }
+    }
+
+    int max_bit_width_interval = getBitWith(max_interval);
+    int max_bit_width_value = getBitWith(max_value);
+
+    // calculate error
+//    result.clear();
+    raw_length = new int[5];
+    raw_length[0] = length;
+    raw_length[1] = max_bit_width_interval;
+    raw_length[2] = max_bit_width_value;
+    raw_length[3] = timestamp_delta_min;
+    raw_length[4] = value_delta_min;
+
+
+    theta[0] = theta0_r;
+    theta[1] = theta1_r;
+    theta[2] = theta0_v;
+    theta[3] = theta1_v;
+
+    return ts_block_delta;
+  }
+
+  public static ArrayList<ArrayList<Integer>> getEncodeBitsRegressionNoTrain(
+          ArrayList<ArrayList<Integer>> ts_block,
+          int block_size,
+          ArrayList<Integer> result,
+          ArrayList<Float> theta,
+          int segment_size) {
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+
+    float theta0_r = theta.get(0);
+    float theta1_r = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+
+
+    ArrayList<Integer> tmp0 = new ArrayList<>();
+    tmp0.add(ts_block.get(0).get(0));
+    tmp0.add(ts_block.get(0).get(1));
+    ts_block_delta.add(tmp0);
+
+    ArrayList<ArrayList<Integer>> ts_block_delta_segment = new ArrayList<>();
+    ArrayList<Integer> tmp_segment = new ArrayList<>(2);
+    int max_interval_segment = Integer.MIN_VALUE;
+    int max_value_segment = Integer.MIN_VALUE;
+    tmp_segment.add(max_interval_segment);
+    tmp_segment.add(max_value_segment);
+
+
+    // delta to Regression
+    for (int j = 1; j < block_size; j++) {
+      int epsilon_r =
+               (ts_block.get(j).get(0)
+                      -  (int)(theta0_r + theta1_r * (float) ts_block.get(j - 
1).get(0)));
+      int epsilon_v =
+               (ts_block.get(j).get(1)
+                      - (int)(theta0_v +  theta1_v * (float) ts_block.get(j - 
1).get(1)));
+
+
+      if (epsilon_r < timestamp_delta_min) {
+        timestamp_delta_min = epsilon_r;
+      }
+      if (epsilon_v < value_delta_min) {
+        value_delta_min = epsilon_v;
+      }
+      ArrayList<Integer> tmp = new ArrayList<>();
+      tmp.add(epsilon_r);
+      tmp.add(epsilon_v);
+      ts_block_delta.add(tmp);
+      if (epsilon_r > max_interval_segment) {
+        max_interval_segment = epsilon_r;
+        tmp_segment.set(0, max_interval_segment);
+      }
+      if (epsilon_v > max_value_segment) {
+        max_value_segment = epsilon_v;
+        tmp_segment.set(1, max_value_segment);
+      }
+      if (j % segment_size == 0) {
+        ts_block_delta_segment.add(tmp_segment);
+        tmp_segment = new ArrayList<>();
+        max_interval_segment = Integer.MIN_VALUE;
+        max_value_segment = Integer.MIN_VALUE;
+        tmp_segment.add(max_interval_segment);
+        tmp_segment.add(max_value_segment);
+      }
+
+    }
+
+    int max_interval = Integer.MIN_VALUE;
+    int max_value = Integer.MIN_VALUE;
+    int length = 0;
+    for (int j = block_size - 1; j > 0; j--) {
+       int epsilon_r =ts_block_delta.get(j).get(0) - timestamp_delta_min;
+      int epsilon_v =ts_block_delta.get(j).get(1) - value_delta_min;
+      if (epsilon_r > max_interval) {
+        max_interval = epsilon_r;
+      }
+      if (epsilon_v > max_value) {
+        max_value = epsilon_v;
+      }
+      ArrayList<Integer> tmp = new ArrayList<>();
+      tmp.add(epsilon_r);
+      tmp.add(epsilon_v);
+      ts_block_delta.set(j, tmp);
+    }
+    for (ArrayList<Integer> segment_max : ts_block_delta_segment) {
+      length += getBitWith(segment_max.get(0) - timestamp_delta_min);
+      length += getBitWith(segment_max.get(1) - value_delta_min);
+    }
+
+    int max_bit_width_interval = getBitWith(max_interval);
+    int max_bit_width_value = getBitWith(max_value);
+
+     result.clear();
+
+    result.add(length);
+    result.add(max_bit_width_interval);
+    result.add(max_bit_width_value);
+
+    result.add(timestamp_delta_min);
+    result.add(value_delta_min);
+
+
+
+    return ts_block_delta;
+  }
+
+
+  public static int getBeta(
+          ArrayList<ArrayList<Integer>> ts_block,
+          int alpha,
+          ArrayList<Integer> min_index,
+          int block_size,
+          ArrayList<Integer> raw_length,
+          ArrayList<Float> theta,
+          int segment_size) {
+
+    int raw_abs_sum = raw_length.get(0);
+    ArrayList<ArrayList<Integer>> new_length_list =new ArrayList<>();
+
+    ArrayList<Integer> j_star_list = new ArrayList<>(); // beta list of min b 
phi alpha to j
+    int j_star = -1;
+    ArrayList<Integer> b = new ArrayList<>();
+    if (alpha == -1) {
+      return j_star;
+    }
+
+    if (alpha == 0) {
+      for (int j = 2; j < block_size; j++) {
+        // if j, alpha+1, alpha points are min residuals, need to recalculate 
min residuals
+        
if(min_index.contains(j)||min_index.contains(0)||min_index.contains(1)){
+          b = adjust0MinChange(ts_block, raw_length, j, theta, segment_size);
+        }else {
+          b = adjust0MinChangeNo(ts_block, raw_length, j, theta, segment_size);
+        }
+        if (b.get(0) < raw_abs_sum) {
+          raw_abs_sum = b.get(0);
+          j_star_list = new ArrayList<>();
+          new_length_list = new ArrayList<>();
+          j_star_list.add(j);
+          new_length_list.add(b);
+        } else if (b.get(0) == raw_abs_sum) {
+          j_star_list.add(j);
+          new_length_list.add(b);
+        }
+      }
+      if(min_index.contains(0)||min_index.contains(1)){
+        b = adjust0n1MinChange(ts_block, raw_length, theta, segment_size);
+      }else {
+        b = adjust0n1MinChangeNo(ts_block, raw_length, theta, segment_size);
+      }
+      if (b.get(0) < raw_abs_sum) {
+        raw_abs_sum = b.get(0);
+        j_star_list = new ArrayList<>();
+        new_length_list = new ArrayList<>();
+        j_star_list.add(block_size);
+        new_length_list.add(b);
+      } else if (b.get(0) == raw_abs_sum) {
+        j_star_list.add(block_size);
+        new_length_list.add(b);
+      }
+    } // alpha == n
+    else if (alpha == block_size - 1) {
+      for (int j = 1; j < block_size - 1; j++) {
+        if(min_index.contains(block_size - 1)||min_index.contains(j)){
+          b = adjustnMinChange(ts_block, raw_length, j, theta, segment_size);
+        }else {
+          b = adjustnMinChangeNo(ts_block, raw_length, j, theta, segment_size);
+        }
+        if (b.get(0) < raw_abs_sum) {
+          raw_abs_sum = b.get(0);
+          j_star_list = new ArrayList<>();
+          new_length_list = new ArrayList<>();
+          j_star_list.add(j);
+          new_length_list.add(b);
+        } else if (b.get(0) == raw_abs_sum) {
+          j_star_list.add(j);
+          new_length_list.add(b);
+        }
+      }
+      if(min_index.contains(block_size - 1)||min_index.contains(0)){
+        b = adjustn0MinChange(ts_block, raw_length, theta, segment_size);
+      }else {
+        b = adjustn0MinChangeNo(ts_block, raw_length, theta, segment_size);
+      }
+      if (b.get(0) < raw_abs_sum) {
+        raw_abs_sum = b.get(0);
+        j_star_list.clear();
+        j_star_list = new ArrayList<>();
+        new_length_list = new ArrayList<>();
+        j_star_list.add(0);
+        new_length_list.add(b);
+      } else if (b.get(0) == raw_abs_sum) {
+        j_star_list.add(0);
+        new_length_list.add(b);
+      }
+    } // alpha != 1 and alpha != n
+    else {
+      for (int j = 1; j < block_size; j++) {
+        if (alpha != j && (alpha + 1) != j) {
+          
if(min_index.contains(j)||min_index.contains(alpha)||min_index.contains(alpha+1)){
+            b = adjustAlphaToJMinChange(ts_block, raw_length, alpha, j, theta, 
segment_size);
+          }else {
+            b = adjustAlphaToJMinChangeNo(ts_block, raw_length, alpha, j, 
theta, segment_size);
+          }
+          if (b.get(0) < raw_abs_sum) {
+            raw_abs_sum = b.get(0);
+            j_star_list = new ArrayList<>();
+            new_length_list = new ArrayList<>();
+            j_star_list.add(j);
+            new_length_list.add(b);
+          } else if (b.get(0) == raw_abs_sum) {
+            j_star_list.add(j);
+            new_length_list.add(b);
+          }
+        }
+      }
+      
if(min_index.contains(0)||min_index.contains(alpha)||min_index.contains(alpha+1)){
+        b = adjustTo0MinChange(ts_block, raw_length, alpha, theta, 
segment_size);
+      }else{
+        b = adjustTo0MinChangeNo(ts_block, raw_length, alpha, 
theta,segment_size);
+      }
+      if (b.get(0) < raw_abs_sum) {
+        raw_abs_sum = b.get(0);
+        j_star_list = new ArrayList<>();
+        new_length_list = new ArrayList<>();
+        j_star_list.add(0);
+        new_length_list.add(b);
+      } else if (b.get(0) == raw_abs_sum) {
+        j_star_list.add(0);
+        new_length_list.add(b);
+      }
+      
if(min_index.contains(block_size-1)||min_index.contains(alpha)||min_index.contains(alpha+1)){
+        b = adjustTonMinChange(ts_block,raw_length, alpha, theta, 
segment_size);
+      }else {
+        b = adjustTonMinChangeNo(ts_block,raw_length, alpha, theta, 
segment_size);
+      }
+
+      if (b.get(0) < raw_abs_sum) {
+        raw_abs_sum = b.get(0);
+        j_star_list = new ArrayList<>();
+        new_length_list = new ArrayList<>();
+        j_star_list.add(block_size);
+        new_length_list.add(b);
+      } else if (b.get(0) == raw_abs_sum) {
+        j_star_list.add(block_size);
+        new_length_list.add(b);
+      }
+    }
+    if (j_star_list.size() != 0) {
+      j_star = getIstarClose(alpha, j_star_list, new_length_list, raw_length);
+    }
+    return j_star;
+  }
+
+  // adjust 0 to no n
+
+  private static ArrayList<Integer> adjust0MinChange(
+          ArrayList<ArrayList<Integer>> ts_block,ArrayList<Integer> 
raw_length,  int j, ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    assert j != block_size;
+
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+    int timestamp_delta_max = Integer.MIN_VALUE;
+    int value_delta_max = Integer.MIN_VALUE;
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+
+
+    for (int i = 2; i < block_size; i++) {
+      int timestamp_delta_i;
+      int value_delta_i;
+      if (i != j) {
+        timestamp_delta_i =
+                ts_block.get(i).get(0)
+                        - (int) (theta0_t + theta1_t * (float) ts_block.get(i 
- 1).get(0));
+        value_delta_i =
+                ts_block.get(i).get(1)
+                        - (int) (theta0_v + theta1_v * (float) ts_block.get(i 
- 1).get(1));
+      } else {
+        timestamp_delta_i =
+                ts_block.get(j).get(0)
+                        - (int) (theta0_t + theta1_t * (float) 
ts_block.get(0).get(0));
+        value_delta_i =
+                ts_block.get(j).get(1)
+                        - (int) (theta0_v + theta1_v * (float) 
ts_block.get(0).get(1));
+        ArrayList<Integer> tmp0 = new ArrayList<>();
+        tmp0.add(timestamp_delta_i);
+        tmp0.add(value_delta_i);
+        ts_block_delta.add(tmp0);
+        if (timestamp_delta_i > timestamp_delta_max) {
+          timestamp_delta_max = timestamp_delta_i;
+        }
+        if (timestamp_delta_i < timestamp_delta_min) {
+          timestamp_delta_min = timestamp_delta_i;
+        }
+        if (value_delta_i > value_delta_max) {
+          value_delta_max = value_delta_i;
+        }
+        if (value_delta_i < value_delta_min) {
+          value_delta_min = value_delta_i;
+        }
+        timestamp_delta_i =
+                ts_block.get(0).get(0)
+                        - (int) (theta0_t + theta1_t * (float) ts_block.get(j 
- 1).get(0));
+        value_delta_i =
+                ts_block.get(0).get(1)
+                        - (int) (theta0_v + theta1_v * (float) ts_block.get(j 
- 1).get(1));
+      }
+      ArrayList<Integer> tmp0 = new ArrayList<>();
+      tmp0.add(timestamp_delta_i);
+      tmp0.add(value_delta_i);
+      ts_block_delta.add(tmp0);
+      if (timestamp_delta_i > timestamp_delta_max) {
+        timestamp_delta_max = timestamp_delta_i;
+      }
+      if (timestamp_delta_i < timestamp_delta_min) {
+        timestamp_delta_min = timestamp_delta_i;
+      }
+      if (value_delta_i > value_delta_max) {
+        value_delta_max = value_delta_i;
+      }
+      if (value_delta_i < value_delta_min) {
+        value_delta_min = value_delta_i;
+      }
+
+    }
+    int length = 0;
+    for (ArrayList<Integer> segment_max : ts_block_delta) {
+      length += getBitWith(segment_max.get(0) - timestamp_delta_min);
+      length += getBitWith(segment_max.get(1) - value_delta_min);
+    }
+
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+  private static ArrayList<Integer> adjust0MinChangeNo(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> 
raw_length, int j, ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    assert j != block_size;
+
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = raw_length.get(3);
+    int value_delta_min = raw_length.get(4);
+
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    int length = raw_length.get(0);
+    int timestamp_delta_i;
+    int value_delta_i;
+    timestamp_delta_i =
+            ts_block.get(j + 1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(j-1).get(0));
+    value_delta_i =
+            ts_block.get(j + 1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(j-1).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(0).get(0));
+    value_delta_i =
+            ts_block.get(1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(0).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(0).get(0)
+                    - (int) (theta0_t + theta1_t * (float) ts_block.get(j - 
1).get(0));
+    value_delta_i =
+            ts_block.get(0).get(1)
+                    - (int) (theta0_v + theta1_v * (float) ts_block.get(j - 
1).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjust0MinChange( ts_block, raw_length,  j, theta,  segment_size);
+    }
+
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+    timestamp_delta_i =
+            ts_block.get(j + 1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(0).get(0));
+    value_delta_i =
+            ts_block.get(j + 1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(0).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjust0MinChange( ts_block, raw_length,  j, theta,  segment_size);
+    }
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+
+  // adjust 0 to n
+  private static ArrayList<Integer> adjust0n1MinChange(
+          ArrayList<ArrayList<Integer>> ts_block,ArrayList<Integer> 
raw_length,  ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+    int length = 0;
+    for (int i = 2; i < block_size; i++) {
+      int timestamp_delta_i;
+      int value_delta_i;
+      timestamp_delta_i =
+              ts_block.get(i).get(0) - (int) (theta0_t + theta1_t * (float) 
ts_block.get(i - 1).get(0));
+      value_delta_i =
+              ts_block.get(i).get(1) - (int) (theta0_v + theta1_v * (float) 
ts_block.get(i - 1).get(1));
+      ArrayList<Integer> tmp0 = new ArrayList<>();
+      tmp0.add(timestamp_delta_i);
+      tmp0.add(value_delta_i);
+      ts_block_delta.add(tmp0);
+      if (timestamp_delta_i < timestamp_delta_min) {
+        timestamp_delta_min = timestamp_delta_i;
+      }
+      if (value_delta_i < value_delta_min) {
+        value_delta_min = value_delta_i;
+      }
+    }
+    int timestamp_delta_i;
+    int value_delta_i;
+    timestamp_delta_i =
+            ts_block.get(0).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size - 1).get(0));
+    value_delta_i =
+            ts_block.get(0).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size - 1).get(1));
+    ArrayList<Integer> tmp0 = new ArrayList<>();
+    tmp0.add(timestamp_delta_i);
+    tmp0.add(value_delta_i);
+    ts_block_delta.add(tmp0);
+    if (timestamp_delta_i < timestamp_delta_min) {
+      timestamp_delta_min = timestamp_delta_i;
+    }
+    if (value_delta_i < value_delta_min) {
+      value_delta_min = value_delta_i;
+    }
+
+    for (ArrayList<Integer> segment_max : ts_block_delta) {
+      length += getBitWith(segment_max.get(0) - timestamp_delta_min);
+      length += getBitWith(segment_max.get(1) - value_delta_min);
+    }
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+  private static ArrayList<Integer> adjust0n1MinChangeNo(
+          ArrayList<ArrayList<Integer>> ts_block,ArrayList<Integer> 
raw_length,  ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = raw_length.get(3);
+    int value_delta_min = raw_length.get(4);
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+
+    int length = raw_length.get(0);
+    int timestamp_delta_i;
+    int value_delta_i;
+    timestamp_delta_i =
+            ts_block.get(1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(0).get(0));
+    value_delta_i =
+            ts_block.get(1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(0).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(0).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size - 1).get(0));
+    value_delta_i =
+            ts_block.get(0).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size - 1).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjust0n1MinChange( ts_block, raw_length,  theta,  segment_size);
+    }
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+
+
+  // adjust n to no 0
+   private static ArrayList<Integer> adjustnMinChange(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> 
raw_length,  int j, ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    assert j != 0;
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+
+    int length = 0;
+
+
+    for (int i = 1; i < block_size - 1; i++) {
+      int timestamp_delta_i;
+      int value_delta_i;
+      if (i != j) {
+        timestamp_delta_i =
+                ts_block.get(i).get(0)
+                        - (int) (theta0_t + theta1_t * (float) ts_block.get(i 
- 1).get(0));
+        value_delta_i =
+                ts_block.get(i).get(1)
+                        - (int) (theta0_v + theta1_v * (float) ts_block.get(i 
- 1).get(1));
+      } else {
+        timestamp_delta_i =
+                ts_block.get(j).get(0)
+                        - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size-1).get(0));
+        value_delta_i =
+                ts_block.get(j).get(1)
+                        - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size-1).get(1));
+        ArrayList<Integer> tmp0 = new ArrayList<>();
+        tmp0.add(timestamp_delta_i);
+        tmp0.add(value_delta_i);
+        ts_block_delta.add(tmp0);
+        if (timestamp_delta_i < timestamp_delta_min) {
+          timestamp_delta_min = timestamp_delta_i;
+        }
+        if (value_delta_i < value_delta_min) {
+          value_delta_min = value_delta_i;
+        }
+
+
+        timestamp_delta_i =
+                ts_block.get(block_size-1).get(0)
+                        - (int) (theta0_t + theta1_t * (float) ts_block.get(j 
- 1).get(0));
+        value_delta_i =
+                ts_block.get(block_size-1).get(1)
+                        - (int) (theta0_v + theta1_v * (float) ts_block.get(j 
- 1).get(1));
+      }
+      ArrayList<Integer> tmp0 = new ArrayList<>();
+      tmp0.add(timestamp_delta_i);
+      tmp0.add(value_delta_i);
+      ts_block_delta.add(tmp0);
+
+      if (timestamp_delta_i < timestamp_delta_min) {
+        timestamp_delta_min = timestamp_delta_i;
+      }
+      if (value_delta_i < value_delta_min) {
+        value_delta_min = value_delta_i;
+      }
+
+    }
+
+    for (ArrayList<Integer> segment_max : ts_block_delta) {
+      length += getBitWith(segment_max.get(0) - timestamp_delta_min);
+      length += getBitWith(segment_max.get(1) - value_delta_min);
+    }
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+  private static ArrayList<Integer> adjustnMinChangeNo(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> 
raw_length,  int j, ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    assert j != 0;
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    int length = raw_length.get(0);
+    int timestamp_delta_i;
+    int value_delta_i;
+    timestamp_delta_i =
+            ts_block.get(j).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(j-1).get(0));
+    value_delta_i =
+            ts_block.get(j).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(j-1).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(block_size-1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size-2).get(0));
+    value_delta_i =
+            ts_block.get(block_size-1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size-2).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+
+    timestamp_delta_i =
+            ts_block.get(j).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size - 1).get(0));
+    value_delta_i =
+            ts_block.get(j).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size - 1).get(1));
+
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustnMinChange( ts_block, raw_length, j,  theta,  segment_size);
+    }
+
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(block_size - 1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(j-1).get(0));
+    value_delta_i =
+            ts_block.get(block_size - 1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(j-1).get(1));
+
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustnMinChange( ts_block, raw_length, j,  theta,  segment_size);
+    }
+
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+    return b;
+  }
+  // adjust n to 0
+   // adjust n to 0
+  private static ArrayList<Integer> adjustn0MinChange(
+          ArrayList<ArrayList<Integer>> ts_block,ArrayList<Integer> 
raw_length,  ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+    int length = 0;
+
+    for (int i = 1; i < block_size - 1; i++) {
+      int timestamp_delta_i;
+      int value_delta_i;
+      timestamp_delta_i =
+              ts_block.get(i).get(0) - (int) (theta0_t + theta1_t * (float) 
ts_block.get(i - 1).get(0));
+      value_delta_i =
+              ts_block.get(i).get(1) - (int) (theta0_v + theta1_v * (float) 
ts_block.get(i - 1).get(1));
+      ArrayList<Integer> tmp0 = new ArrayList<>();
+      tmp0.add(timestamp_delta_i);
+      tmp0.add(value_delta_i);
+      ts_block_delta.add(tmp0);
+      if (timestamp_delta_i < timestamp_delta_min) {
+        timestamp_delta_min = timestamp_delta_i;
+      }
+      if (value_delta_i < value_delta_min) {
+        value_delta_min = value_delta_i;
+      }
+
+    }
+    int timestamp_delta_i;
+    int value_delta_i;
+    timestamp_delta_i =
+            ts_block.get(0).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size - 1).get(0));
+    value_delta_i =
+            ts_block.get(0).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size - 1).get(1));
+    ArrayList<Integer> tmp0 = new ArrayList<>();
+    tmp0.add(timestamp_delta_i);
+    tmp0.add(value_delta_i);
+    ts_block_delta.add(tmp0);
+
+    if (timestamp_delta_i < timestamp_delta_min) {
+      timestamp_delta_min = timestamp_delta_i;
+    }
+    if (value_delta_i < value_delta_min) {
+      value_delta_min = value_delta_i;
+    }
+    for (ArrayList<Integer> segment_max : ts_block_delta) {
+      length += getBitWith(segment_max.get(0) - timestamp_delta_min);
+      length += getBitWith(segment_max.get(1) - value_delta_min);
+    }
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+  // adjust n to 0
+  private static ArrayList<Integer> adjustn0MinChangeNo(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> 
raw_length,  ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = raw_length.get(3);
+    int value_delta_min = raw_length.get(4);
+    ArrayList<ArrayList<Integer>> ts_block_delta_segment = new ArrayList<>();
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    int length = raw_length.get(0);
+    int timestamp_delta_i;
+    int value_delta_i;
+    timestamp_delta_i =
+            ts_block.get(block_size - 1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size - 2).get(0));
+    value_delta_i =
+            ts_block.get(block_size - 1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size - 2).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+
+    timestamp_delta_i =
+            ts_block.get(0).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size - 1).get(0));
+    value_delta_i =
+            ts_block.get(0).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size - 1).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustn0MinChange( ts_block, raw_length, theta,  segment_size);
+    }
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+    return b;
+  }
+
+    private static ArrayList<Integer> adjustAlphaToJMinChange(
+          ArrayList<ArrayList<Integer>> ts_block,  ArrayList<Integer> 
raw_length,int alpha, int j, ArrayList<Float> theta, int segment_size) {
+
+    int block_size = ts_block.size();
+    assert alpha != block_size - 1;
+    assert alpha != 0;
+    assert j != 0;
+    assert j != block_size;
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+    int length = 0;
+    for (int i = 1; i < block_size; i++) {
+      int timestamp_delta_i;
+      int value_delta_i;
+      if (i == j) {
+        timestamp_delta_i =
+                ts_block.get(j).get(0)
+                        - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha).get(0));
+        value_delta_i =
+                ts_block.get(j).get(1)
+                        - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha).get(1));
+      } else if (i == alpha) {
+        timestamp_delta_i =
+                ts_block.get(alpha).get(0)
+                        - (int) (theta0_t + theta1_t * (float) ts_block.get(j 
- 1).get(0));
+        value_delta_i =
+                ts_block.get(alpha).get(1)
+                        - (int) (theta0_v + theta1_v * (float) ts_block.get(j 
- 1).get(1));
+      } else if (i == alpha + 1) {
+        timestamp_delta_i =
+                ts_block.get(alpha + 1).get(0)
+                        - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha - 1).get(0));
+        value_delta_i =
+                ts_block.get(alpha + 1).get(1)
+                        - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha - 1).get(1));
+      } else {
+        timestamp_delta_i =
+                ts_block.get(i).get(0)
+                        - (int) (theta0_t + theta1_t * (float) ts_block.get(i 
- 1).get(0));
+        value_delta_i =
+                ts_block.get(i).get(1)
+                        - (int) (theta0_v + theta1_v * (float) ts_block.get(i 
- 1).get(1));
+      }
+      ArrayList<Integer> tmp0 = new ArrayList<>();
+      tmp0.add(timestamp_delta_i);
+      tmp0.add(value_delta_i);
+      ts_block_delta.add(tmp0);
+      if (timestamp_delta_i < timestamp_delta_min) {
+        timestamp_delta_min = timestamp_delta_i;
+      }
+      if (value_delta_i < value_delta_min) {
+        value_delta_min = value_delta_i;
+      }
+
+    }
+
+    for (ArrayList<Integer> segment_max : ts_block_delta) {
+      length += getBitWith(segment_max.get(0) - timestamp_delta_min);
+      length += getBitWith(segment_max.get(1) - value_delta_min);
+    }
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+  private static ArrayList<Integer> adjustAlphaToJMinChangeNo(
+          ArrayList<ArrayList<Integer>> ts_block,  ArrayList<Integer> 
raw_length, int alpha, int j, ArrayList<Float> theta, int segment_size) {
+
+    int block_size = ts_block.size();
+    assert alpha != block_size - 1;
+    assert alpha != 0;
+    assert j != 0;
+    assert j != block_size;
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = raw_length.get(3);
+    int value_delta_min = raw_length.get(4);
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    int length = raw_length.get(0);
+    int timestamp_delta_i;
+    int value_delta_i;
+    timestamp_delta_i =
+            ts_block.get(alpha + 1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha).get(0));
+    value_delta_i =
+            ts_block.get(alpha + 1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(alpha).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha-1).get(0));
+    value_delta_i =
+            ts_block.get(alpha).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha-1).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(j).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(j-1).get(0));
+    value_delta_i =
+            ts_block.get(j).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(j-1).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+
+
+    timestamp_delta_i =
+            ts_block.get(alpha ).get(0)
+                    - (int) (theta0_t + theta1_t * (float) ts_block.get(j - 
1).get(0));
+    value_delta_i =
+            ts_block.get(alpha ).get(1)
+                    - (int) (theta0_v + theta1_v * (float) ts_block.get(j - 
1).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustAlphaToJMinChange( ts_block, raw_length, alpha, j, theta,  
segment_size);
+    }
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+    timestamp_delta_i =
+            ts_block.get(j).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha).get(0));
+    value_delta_i =
+            ts_block.get(j).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustAlphaToJMinChange( ts_block, raw_length, alpha, j, theta,  
segment_size);
+    }
+
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+    timestamp_delta_i =
+            ts_block.get(alpha).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(j-1).get(0));
+    value_delta_i =
+            ts_block.get(alpha).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(j-1).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustAlphaToJMinChange( ts_block, raw_length, alpha, j, theta,  
segment_size);
+    }
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+    return b;
+  }
+
+
+  private static ArrayList<Integer> adjustTo0MinChange(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> 
raw_length, int alpha, ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    assert alpha != block_size - 1;
+    assert alpha != 0;
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+
+    for (int i = 1; i < block_size; i++) {
+      int timestamp_delta_i;
+      int value_delta_i;
+      if (i == (alpha + 1)) {
+        timestamp_delta_i =
+                ts_block.get(alpha + 1).get(0)
+                        - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha - 1).get(0));
+        value_delta_i =
+                ts_block.get(alpha + 1).get(1)
+                        - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha - 1).get(1));
+      } else if (i == alpha) {
+        timestamp_delta_i =
+                ts_block.get(0).get(0)
+                        - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha).get(0));
+        value_delta_i =
+                ts_block.get(0).get(1)
+                        - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha).get(1));
+      } else {
+        timestamp_delta_i =
+                ts_block.get(i).get(0)
+                        - (int) (theta0_t + theta1_t * (float) ts_block.get(i 
- 1).get(0));
+        value_delta_i =
+                ts_block.get(i).get(1)
+                        - (int) (theta0_v + theta1_v * (float) ts_block.get(i 
- 1).get(1));
+      }
+      ArrayList<Integer> tmp= new ArrayList<>();
+      tmp.add(timestamp_delta_i);
+      tmp.add(value_delta_i);
+      ts_block_delta.add(tmp);
+
+      if (timestamp_delta_i < timestamp_delta_min) {
+        timestamp_delta_min = timestamp_delta_i;
+      }
+
+      if (value_delta_i < value_delta_min) {
+        value_delta_min = value_delta_i;
+      }
+
+//            if (timestamp_delta_i > max_interval_segment) {
+//                max_interval_segment = timestamp_delta_i;
+//                tmp_segment.set(0, max_interval_segment);
+//            }
+//            if (value_delta_i > max_value_segment) {
+//                max_value_segment = value_delta_i;
+//                tmp_segment.set(1, max_value_segment);
+//            }
+//            if (i % segment_size == 0) {
+//                ts_block_delta_segment.add(tmp_segment);
+//                tmp_segment = new ArrayList<>();
+//                max_interval_segment = Integer.MIN_VALUE;
+//                max_value_segment = Integer.MIN_VALUE;
+//                tmp_segment.add(max_interval_segment);
+//                tmp_segment.add(max_value_segment);
+//            }
+    }
+    int length = 0;
+    for (ArrayList<Integer> segment_max : ts_block_delta) {
+      length += getBitWith(segment_max.get(0) - timestamp_delta_min);
+      length += getBitWith(segment_max.get(1) - value_delta_min);
+    }
+//        raw_length.set(3,timestamp_delta_min);
+//        raw_length.set(4,value_delta_min);
+
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+  private static ArrayList<Integer> adjustTo0MinChangeNo(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> 
raw_length, int alpha, ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    assert alpha != block_size - 1;
+    assert alpha != 0;
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = raw_length.get(3);
+    int value_delta_min = raw_length.get(4);
+    ArrayList<ArrayList<Integer>> ts_block_delta_segment = new ArrayList<>();
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    int length = raw_length.get(0);
+    int timestamp_delta_i;
+    int value_delta_i;
+    timestamp_delta_i =
+            ts_block.get(alpha + 1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha).get(0));
+    value_delta_i =
+            ts_block.get(alpha + 1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(alpha).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha-1).get(0));
+    value_delta_i =
+            ts_block.get(alpha).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha-1).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+
+    timestamp_delta_i =
+            ts_block.get(alpha + 1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) ts_block.get(alpha 
- 1).get(0));
+    value_delta_i =
+            ts_block.get(alpha + 1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) ts_block.get(alpha 
- 1).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustTo0MinChange( ts_block, raw_length, alpha,  theta,  
segment_size);
+    }
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(0).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha).get(0));
+    value_delta_i =
+            ts_block.get(0).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustTo0MinChange( ts_block, raw_length, alpha,  theta,  
segment_size);
+    }
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+
+  private static ArrayList<Integer> adjustTonMinChange(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> 
raw_length, int alpha, ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    assert alpha != block_size - 1;
+    assert alpha != 0;
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+    int length = 0;
+
+    for (int i = 1; i < block_size; i++) {
+      int timestamp_delta_i;
+      int value_delta_i;
+      if (i == (alpha + 1)) {
+        timestamp_delta_i =
+                ts_block.get(alpha + 1).get(0)
+                        - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha - 1).get(0));
+        value_delta_i =
+                ts_block.get(alpha + 1).get(1)
+                        - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha - 1).get(1));
+      } else if (i == alpha) {
+        timestamp_delta_i =
+                ts_block.get(alpha).get(0)
+                        - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size - 1).get(0));
+        value_delta_i =
+                ts_block.get(alpha).get(1)
+                        - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size - 1).get(1));
+      } else {
+        timestamp_delta_i =
+                ts_block.get(i).get(0)
+                        - (int) (theta0_t + theta1_t * (float) ts_block.get(i 
- 1).get(0));
+        value_delta_i =
+                ts_block.get(i).get(1)
+                        - (int) (theta0_v + theta1_v * (float) ts_block.get(i 
- 1).get(1));
+      }
+      ArrayList<Integer> tmp0 = new ArrayList<>();
+      tmp0.add(timestamp_delta_i);
+      tmp0.add(value_delta_i);
+      ts_block_delta.add(tmp0);
+      if (timestamp_delta_i < timestamp_delta_min) {
+        timestamp_delta_min = timestamp_delta_i;
+      }
+      if (value_delta_i < value_delta_min) {
+        value_delta_min = value_delta_i;
+      }
+    }
+
+    for (ArrayList<Integer> segment_max : ts_block_delta) {
+      length += getBitWith(segment_max.get(0) - timestamp_delta_min);
+      length += getBitWith(segment_max.get(1) - value_delta_min);
+    }
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+
+  private static ArrayList<Integer> adjustTonMinChangeNo(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> 
raw_length, int alpha, ArrayList<Float> theta, int segment_size) {
+    int block_size = ts_block.size();
+    assert alpha != block_size - 1;
+    assert alpha != 0;
+    ArrayList<Integer> b = new ArrayList<>();
+    int timestamp_delta_min = raw_length.get(3);
+    int value_delta_min = raw_length.get(4);
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    int length = raw_length.get(0);
+
+    int timestamp_delta_i;
+    int value_delta_i;
+    timestamp_delta_i =
+            ts_block.get(alpha + 1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha).get(0));
+    value_delta_i =
+            ts_block.get(alpha + 1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(alpha).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(alpha-1).get(0));
+    value_delta_i =
+            ts_block.get(alpha).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(alpha-1).get(1));
+
+    length -= getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length -= getBitWith(value_delta_i-value_delta_min);
+
+    timestamp_delta_i =
+            ts_block.get(alpha + 1).get(0)
+                    - (int) (theta0_t + theta1_t * (float) ts_block.get(alpha 
- 1).get(0));
+    value_delta_i =
+            ts_block.get(alpha + 1).get(1)
+                    - (int) (theta0_v + theta1_v * (float) ts_block.get(alpha 
- 1).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustTonMinChange( ts_block, raw_length, alpha,  theta,  
segment_size);
+    }
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+    timestamp_delta_i =
+            ts_block.get(alpha).get(0)
+                    - (int) (theta0_t + theta1_t * (float) 
ts_block.get(block_size-1).get(0));
+    value_delta_i =
+            ts_block.get(alpha).get(1)
+                    - (int) (theta0_v + theta1_v * (float) 
ts_block.get(block_size-1).get(1));
+    if(timestamp_delta_i<timestamp_delta_min ||  value_delta_i < 
timestamp_delta_min){
+      return adjustTonMinChange( ts_block, raw_length, alpha,  theta,  
segment_size);
+    }
+    length += getBitWith(timestamp_delta_i-timestamp_delta_min);
+    length += getBitWith(value_delta_i-value_delta_min);
+
+    b.add(length);
+    b.add(timestamp_delta_min);
+    b.add(value_delta_min);
+
+    return b;
+  }
+
+
+  private static int getIstarClose(int alpha, ArrayList<Integer> 
j_star_list,ArrayList<ArrayList<Integer>> new_length_list,ArrayList<Integer> 
raw_length) {
+    int min_i = 0;
+    int min_dis = Integer.MAX_VALUE;
+    for (int i= 0;i< j_star_list.size();i++) {
+      if (abs(alpha - j_star_list.get(i)) < min_dis) {
+        min_i = j_star_list.get(i);
+        min_dis = abs(alpha - j_star_list.get(i));
+        raw_length.set(0, new_length_list.get(i).get(0));
+        raw_length.set(3, new_length_list.get(i).get(1));
+        raw_length.set(4, new_length_list.get(i).get(2));
+      }
+    }
+    if (min_dis == 0) {
+      System.out.println("get IstarClose error");
+      return 0;
+    }
+    return min_i;
+  }
+
+  public static ArrayList<Integer> getIStar(
+          ArrayList<ArrayList<Integer>> ts_block, ArrayList<Integer> 
min_index, int block_size, int index, ArrayList<Float> theta, int k) {
+
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+    int timestamp_delta_min_index = -1;
+    int value_delta_min_index = -1;
+    int alpha = 0;
+    ArrayList<Integer> alpha_list = new ArrayList<>();
+
+    float theta0_t = theta.get(0);
+    float theta1_t = theta.get(1);
+    float theta0_v = theta.get(2);
+    float theta1_v = theta.get(3);
+    ArrayList<ArrayList<Integer>> ts_block_delta = new ArrayList<>();
+
+    for (int j = 1; j < block_size; j++) {
+      int epsilon_v_j =
+              ts_block.get(j).get(1)
+                      - (int) (theta0_v + theta1_v * (float) ts_block.get(j - 
1).get(1));
+      int epsilon_r_j =
+              ts_block.get(j).get(0)
+                      - (int) (theta0_t + theta1_t * (float) ts_block.get(j - 
1).get(0));
+      ArrayList<Integer> tmp = new ArrayList<>();
+      tmp.add(j);
+      if (index == 0) {
+        tmp.add(epsilon_v_j);
+      }else if (index == 1) {
+        tmp.add(epsilon_r_j);
+      }
+      ts_block_delta.add(tmp);
+      if(epsilon_r_j < timestamp_delta_min){
+        timestamp_delta_min = epsilon_r_j;
+        timestamp_delta_min_index = j;
+      }
+      if(epsilon_v_j < value_delta_min){
+        value_delta_min = epsilon_v_j;
+        value_delta_min_index = j;
+      }
+    }
+    min_index.add(timestamp_delta_min_index);
+    min_index.add(value_delta_min_index);
+
+    quickSort(ts_block_delta, 1, 0, block_size - 2);
+    alpha_list.add(ts_block_delta.get(0).get(0));
+    for (int i = 0; i < k; i++) {
+      alpha_list.add(ts_block_delta.get(block_size - 2 - k).get(0));
+    }
+    return alpha_list;
+  }
+
+  public static int[] getIStar(
+          int[][] ts_block, ArrayList<Integer> min_index, int block_size, int 
index, float[] theta, int k) {
+
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+    int timestamp_delta_min_index = -1;
+    int value_delta_min_index = -1;
+    int alpha = 0;
+
+
+    float theta0_t = theta[0];
+    float theta1_t = theta[1];
+    float theta0_v = theta[2];
+    float theta1_v = theta[3];
+    int[] ts_block_delta = new int[block_size-1];
+
+    for (int j = 0; j < block_size-1; j++) {
+      int epsilon_v_j =
+              ts_block[j+1][1]
+                      - (int) (theta0_v + theta1_v * (float) ts_block[j][1]);
+      int epsilon_r_j =
+              ts_block[j+1][0]
+                      - (int) (theta0_t + theta1_t * (float) ts_block[j][0]);
+//      ArrayList<Integer> tmp = new ArrayList<>();
+//      tmp.add(j);
+      if (index == 0) {
+        ts_block_delta[j] = epsilon_v_j;
+
+//        tmp.add(epsilon_v_j);
+      }else if (index == 1) {
+        ts_block_delta[j] = epsilon_r_j;
+//        tmp.add(epsilon_r_j);
+      }
+//      ts_block_delta.add(tmp);
+      if(epsilon_r_j < timestamp_delta_min){
+        timestamp_delta_min = epsilon_r_j;
+        timestamp_delta_min_index = j;
+      }
+      if(epsilon_v_j < value_delta_min){
+        value_delta_min = epsilon_v_j;
+        value_delta_min_index = j;
+      }
+    }
+    min_index.add(timestamp_delta_min_index);
+    min_index.add(value_delta_min_index);
+
+    Arrays.sort(ts_block_delta);
+//    quickSort(ts_block_delta, 1, 0, block_size - 2);
+    int[] alpha_list = new int[k+1];
+//    ArrayList<Integer> alpha_list = new ArrayList<>();
+    alpha_list[0] = ts_block_delta[0];
+    for (int i = 0; i < k; i++) {
+      alpha_list[i+1] = ts_block_delta[block_size - 2 - k];
+    }
+    return alpha_list;
+  }
+  public static int[] getIStar(
+          int[][] ts_block,
+          ArrayList<Integer> min_index,
+          int block_size,
+          int[] raw_length,
+          float[] theta,
+          int k) {
+    int timestamp_delta_max = Integer.MIN_VALUE;
+    int value_delta_max = Integer.MIN_VALUE;
+    int timestamp_delta_min = Integer.MAX_VALUE;
+    int value_delta_min = Integer.MAX_VALUE;
+    int timestamp_delta_max_index = -1;
+    int value_delta_max_index = -1;
+    int timestamp_delta_min_index = -1;
+    int value_delta_min_index = -1;
+    int[] alpha_list = new int[2*k+2];
+
+    int[][] ts_block_delta_time = new int[block_size-1][2];
+    int[][] ts_block_delta_value = new int[block_size-1][2];
+
+//    ArrayList<ArrayList<Integer>> ts_block_delta_time = new ArrayList<>();
+//    ArrayList<ArrayList<Integer>> ts_block_delta_value = new ArrayList<>();
+
+    float theta0_t = theta[0];
+    float theta1_t = theta[1];
+    float theta0_v = theta[2];
+    float theta1_v = theta[3];
+
+
+    for (int j = 0; j < block_size-1; j++) {
+      int epsilon_r_j = ts_block[j+1][0] - (int) (theta0_t + theta1_t * 
(float) ts_block[j][0]);
+      int epsilon_v_j = ts_block[j+1][1] - (int) (theta0_v + theta1_v * 
(float) ts_block[j][1]);
+      ts_block_delta_time[j][0] = j;
+      ts_block_delta_time[j][1] = epsilon_r_j;
+      ts_block_delta_value[j][0] = j;
+      ts_block_delta_value[j][1] = epsilon_v_j;
+
+
+      if (epsilon_v_j > value_delta_max) {
+        value_delta_max = (int) epsilon_v_j;
+      }
+      if (epsilon_v_j < value_delta_min) {
+        value_delta_min = (int) epsilon_v_j;
+      }
+      if (epsilon_r_j > timestamp_delta_max) {
+        timestamp_delta_max = (int) epsilon_r_j;
+      }
+      if (epsilon_r_j < timestamp_delta_min) {
+        timestamp_delta_min = (int) epsilon_r_j;
+      }
+    }
+    Arrays.sort(ts_block_delta_time, (a, b) -> {
+      if(a[1]==b[1])
+        return Integer.compare(a[0], b[0]);
+      return Integer.compare(a[1], b[1]);
+    });
+
+    min_index.add(ts_block_delta_time[0][0]);
+    alpha_list[0]= ts_block_delta_time[0][0];
+    for (int i = 0; i < k; i++) {
+      alpha_list[i+1]=ts_block_delta_time[block_size - 2 - k][0];
+    }
+
+    Arrays.sort(ts_block_delta_value, (a, b) -> {
+      if(a[1]==b[1])
+        return Integer.compare(a[0], b[0]);
+      return Integer.compare(a[1], b[1]);
+    });
+
+    int pos_alpha_list = k+1;
+//    quickSort(ts_block_delta_value, 1, 0, block_size - 2);
+    min_index.add(ts_block_delta_value[0][0]);
+    if (!containsValue(alpha_list,ts_block_delta_value[0][0])){
+      alpha_list[pos_alpha_list] = ts_block_delta_value[0][0];
+      pos_alpha_list ++;
+    }
+
+    for (int i = 0; i < k; i++) {
+      if (!containsValue(alpha_list,ts_block_delta_value[block_size - 2 - 
k][0])){
+        alpha_list[pos_alpha_list] = ts_block_delta_value[block_size - 2 - 
k][0];
+        pos_alpha_list ++;
+      }
+    }
+
+
+    return alpha_list;
+  }
+
+//  public static ArrayList<Integer> getIStar(
+//          ArrayList<ArrayList<Integer>> ts_block,
+//          ArrayList<Integer> min_index,
+//          int block_size,
+//          ArrayList<Integer> raw_length,
+//          ArrayList<Float> theta,
+//          int k) {
+//    int timestamp_delta_max = Integer.MIN_VALUE;
+//    int value_delta_max = Integer.MIN_VALUE;
+//    int timestamp_delta_min = Integer.MAX_VALUE;
+//    int value_delta_min = Integer.MAX_VALUE;
+//    int timestamp_delta_max_index = -1;
+//    int value_delta_max_index = -1;
+//    int timestamp_delta_min_index = -1;
+//    int value_delta_min_index = -1;
+//    ArrayList<Integer> alpha_list = new ArrayList<>();
+//
+//    ArrayList<ArrayList<Integer>> ts_block_delta_time = new ArrayList<>();
+//    ArrayList<ArrayList<Integer>> ts_block_delta_value = new ArrayList<>();
+//
+//    float theta0_t = theta.get(0);
+//    float theta1_t = theta.get(1);
+//    float theta0_v = theta.get(2);
+//    float theta1_v = theta.get(3);
+//
+//
+//    for (int j = 1; j < block_size; j++) {
+//      int epsilon_r_j =
+//              ts_block.get(j).get(0) - (int) (theta0_t + theta1_t * (float) 
ts_block.get(j - 1).get(0));
+//      int epsilon_v_j =
+//              ts_block.get(j).get(1) - (int) (theta0_v + theta1_v * (float) 
ts_block.get(j - 1).get(1));
+//      ArrayList<Integer> tmp = new ArrayList<>();
+//      tmp.add(j);
+//      tmp.add(epsilon_r_j);
+//      ts_block_delta_time.add(tmp);
+//
+//      tmp = new ArrayList<>();
+//      tmp.add(j);
+//      tmp.add(epsilon_v_j);
+//      ts_block_delta_value.add(tmp);
+//
+//
+//      if (epsilon_v_j > value_delta_max) {
+//        value_delta_max = (int) epsilon_v_j;
+//        value_delta_max_index = j;
+//      }
+//      if (epsilon_v_j < value_delta_min) {
+//        value_delta_min = (int) epsilon_v_j;
+//        value_delta_min_index = j;
+//      }
+//      if (epsilon_r_j > timestamp_delta_max) {
+//        timestamp_delta_max = (int) epsilon_r_j;
+//        timestamp_delta_max_index = j;
+//      }
+//      if (epsilon_r_j < timestamp_delta_min) {
+//        timestamp_delta_min = (int) epsilon_r_j;
+//        timestamp_delta_min_index = j;
+//      }
+//    }
+//    quickSort(ts_block_delta_time, 1, 0, block_size - 2);
+//    min_index.add(ts_block_delta_time.get(0).get(0));
+//    alpha_list.add(ts_block_delta_time.get(0).get(0));
+//    for (int i = 0; i < k; i++) {
+//      alpha_list.add(ts_block_delta_time.get(block_size - 2 - k).get(0));
+//    }
+//
+//    quickSort(ts_block_delta_value, 1, 0, block_size - 2);
+//    min_index.add(ts_block_delta_value.get(0).get(0));
+//    if (!alpha_list.contains(ts_block_delta_value.get(0).get(0)))
+//      alpha_list.add(ts_block_delta_value.get(0).get(0));
+//    for (int i = 0; i < k; i++) {
+//      if (!alpha_list.contains(ts_block_delta_value.get(block_size - 2 - 
k).get(0)))
+//        alpha_list.add(ts_block_delta_value.get(block_size - 2 - k).get(0));
+//    }
+//
+//
+//    return alpha_list;
+//  }
+
+  public static ArrayList<Byte> encode2Bytes(
+          ArrayList<ArrayList<Integer>> ts_block,
+          ArrayList<Integer> raw_length,
+          ArrayList<Float> theta,
+          ArrayList<Integer> result2) {
+    ArrayList<Byte> encoded_result = new ArrayList<>();
+
+
+
+    // encode interval0 and value0
+    byte[] interval0_byte = int2Bytes(ts_block.get(0).get(0));
+    for (byte b : interval0_byte) encoded_result.add(b);
+    byte[] value0_byte = int2Bytes(ts_block.get(0).get(1));
+    for (byte b : value0_byte) encoded_result.add(b);
+
+    // encode theta
+    byte[] theta0_r_byte = float2bytes(theta.get(0) + raw_length.get(3));
+    for (byte b : theta0_r_byte) encoded_result.add(b);
+    byte[] theta1_r_byte = float2bytes(theta.get(1));
+    for (byte b : theta1_r_byte) encoded_result.add(b);
+    byte[] theta0_v_byte = float2bytes(theta.get(2) + raw_length.get(4));
+    for (byte b : theta0_v_byte) encoded_result.add(b);
+    byte[] theta1_v_byte = float2bytes(theta.get(3));
+    for (byte b : theta1_v_byte) encoded_result.add(b);
+
+    // encode interval
+    byte[] max_bit_width_interval_byte = int2Bytes(raw_length.get(1));
+    for (byte b : max_bit_width_interval_byte) encoded_result.add(b);
+    byte[] timestamp_bytes = bitPacking(ts_block, 0, raw_length.get(1));
+    for (byte b : timestamp_bytes) encoded_result.add(b);
+
+    // encode value
+    byte[] max_bit_width_value_byte = int2Bytes(raw_length.get(2));
+    for (byte b : max_bit_width_value_byte) encoded_result.add(b);
+    byte[] value_bytes = bitPacking(ts_block, 1, raw_length.get(2));
+    for (byte b : value_bytes) encoded_result.add(b);
+
+    byte[] td_common_byte = int2Bytes(result2.get(0));
+    for (byte b : td_common_byte) encoded_result.add(b);
+
+    return encoded_result;
+  }
+
+  public static ArrayList<Byte> encodeRLEBitWidth2Bytes(
+          ArrayList<ArrayList<Integer>> bit_width_segments) {
+    ArrayList<Byte> encoded_result = new ArrayList<>();
+
+    ArrayList<ArrayList<Integer>> run_length_time = new ArrayList<>();
+    ArrayList<ArrayList<Integer>> run_length_value = new ArrayList<>();
+
+    int count_of_time = 0;
+    int count_of_value = 0;
+    int pre_time = bit_width_segments.get(0).get(0);
+    int pre_value = bit_width_segments.get(0).get(1);
+    int size = bit_width_segments.size();
+    for (int i = 1; i < size; i++) {
+      int cur_time = bit_width_segments.get(i).get(0);
+      int cur_value = bit_width_segments.get(i).get(1);
+      if (cur_time != pre_time) {
+        ArrayList<Integer> tmp = new ArrayList<>();
+        tmp.add(count_of_time);
+        tmp.add(pre_time);
+        run_length_time.add(tmp);
+        pre_time = cur_time;
+        count_of_time = 0;
+      } else {
+        count_of_time++;
+        if (count_of_time == 256) {
+          ArrayList<Integer> tmp = new ArrayList<>();
+          tmp.add(count_of_time);
+          tmp.add(pre_time);
+          run_length_time.add(tmp);
+          count_of_time = 0;
+        }
+      }
+
+      if (cur_value != pre_value) {
+        ArrayList<Integer> tmp = new ArrayList<>();
+        tmp.add(count_of_value);
+        tmp.add(pre_value);
+        run_length_value.add(tmp);
+        pre_value = cur_value;
+        count_of_value = 0;
+      } else {
+        count_of_value++;
+        if (count_of_value == 256) {
+          ArrayList<Integer> tmp = new ArrayList<>();
+          tmp.add(count_of_value);
+          tmp.add(pre_value);
+          run_length_value.add(tmp);
+          count_of_value = 0;
+        }
+      }
+
+    }
+    if (count_of_time != 0) {
+      ArrayList<Integer> tmp = new ArrayList<>();
+      tmp.add(count_of_time);
+      tmp.add(pre_time);
+      run_length_time.add(tmp);
+    }
+    if (count_of_value != 0) {
+      ArrayList<Integer> tmp = new ArrayList<>();
+      tmp.add(count_of_value);
+      tmp.add(pre_value);
+      run_length_value.add(tmp);
+    }
+
+    for (ArrayList<Integer> bit_width_time : run_length_time) {
+      byte[] timestamp_bytes = bitWidth2Bytes(bit_width_time.get(0));
+      for (byte b : timestamp_bytes) encoded_result.add(b);
+      byte[] value_bytes = bitWidth2Bytes(bit_width_time.get(1));
+      for (byte b : value_bytes) encoded_result.add(b);
+    }
+    for (ArrayList<Integer> bit_width_value : run_length_value) {
+      byte[] timestamp_bytes = bitWidth2Bytes(bit_width_value.get(0));
+      for (byte b : timestamp_bytes) encoded_result.add(b);
+      byte[] value_bytes = bitWidth2Bytes(bit_width_value.get(1));
+      for (byte b : value_bytes) encoded_result.add(b);
+    }
+    return encoded_result;
+  }
+
+  public static int encodeRLEBitWidth2Bytes(
+          int[][] bit_width_segments) {
+    int encoded_result = 0;
+
+//    ArrayList<ArrayList<Integer>> run_length_time = new ArrayList<>();
+//    ArrayList<ArrayList<Integer>> run_length_value = new ArrayList<>();
+
+    int count_of_time = 0;
+    int count_of_value = 0;
+    int pre_time = bit_width_segments[0][0];
+    int pre_value = bit_width_segments[0][1];
+    int size = bit_width_segments.length;
+    int[][] run_length_time = new int[size][2];
+    int[][] run_length_value = new int[size][2];
+
+    int pos_time = 0;
+    int pos_value = 0;
+
+    for (int i = 1; i < size; i++) {
+      int cur_time = bit_width_segments[i][0];
+      int cur_value = bit_width_segments[i][1];
+      if (cur_time != pre_time) {
+        run_length_time[pos_time][0] = count_of_time;
+        run_length_time[pos_time][1] = pre_time;
+        pos_time ++;
+        pre_time = cur_time;
+        count_of_time = 0;
+      } else {
+        count_of_time++;
+        if (count_of_time == 256) {
+          run_length_time[pos_time][0] = count_of_time;
+          run_length_time[pos_time][1] = pre_time;
+          pos_time ++;
+          count_of_time = 0;
+        }
+      }
+
+      if (cur_value != pre_value) {
+        run_length_time[pos_value][0] = count_of_value;
+        run_length_time[pos_value][1] = pre_value;
+        pos_value ++;
+
+        pre_value = cur_value;
+        count_of_value = 0;
+      } else {
+        count_of_value++;
+        if (count_of_value == 256) {
+          run_length_time[pos_value][0] = count_of_value;
+          run_length_time[pos_value][1] = pre_value;
+          pos_value ++;
+          count_of_value = 0;
+        }
+      }
+
+    }
+    if (count_of_time != 0) {
+      run_length_time[pos_time][0] = count_of_time;
+      run_length_time[pos_time][1] = pre_time;
+      pos_time ++;
+    }
+    if (count_of_value != 0) {
+      run_length_time[pos_value][0] = count_of_value;
+      run_length_time[pos_value][1] = pre_value;
+      pos_value ++;
+    }
+
+    encoded_result += (pos_time * 2);
+    encoded_result += (pos_value * 2);
+
+    return encoded_result;
+  }
+
+  public static int[][] segmentBitPacking(int[][] ts_block_delta, int 
block_size, int segment_size) {
+
+    int segment_n = (block_size - 1) / segment_size;
+    int[][] bit_width_segments = new int[segment_n][2];
+    for (int segment_i = 0; segment_i < segment_n; segment_i++) {
+      int bit_width_time = Integer.MIN_VALUE;
+      int bit_width_value = Integer.MIN_VALUE;
+
+      for (int data_i = segment_i * segment_size + 1; data_i < (segment_i + 1) 
* segment_size + 1; data_i++) {
+        int cur_bit_width_time = getBitWith(ts_block_delta[data_i][0]);
+        int cur_bit_width_value = getBitWith(ts_block_delta[data_i][1]);
+        if (cur_bit_width_time > bit_width_time) {
+          bit_width_time = cur_bit_width_time;
+        }
+        if (cur_bit_width_value > bit_width_value) {
+          bit_width_value = cur_bit_width_value;
+        }
+      }
+      bit_width_segments[segment_i][0] = bit_width_time;
+      bit_width_segments[segment_i][1] = bit_width_value;
+    }
+    return bit_width_segments;
+  }
+  public static ArrayList<ArrayList<Integer>> 
segmentBitPacking(ArrayList<ArrayList<Integer>> ts_block_delta, int block_size, 
int segment_size) {
+    ArrayList<ArrayList<Integer>> bit_width_segments = new ArrayList<>();
+    int segment_n = (block_size - 1) / segment_size;
+    for (int segment_i = 0; segment_i < segment_n; segment_i++) {
+      int bit_width_time = Integer.MIN_VALUE;
+      int bit_width_value = Integer.MIN_VALUE;
+
+      for (int data_i = segment_i * segment_size + 1; data_i < (segment_i + 1) 
* segment_size + 1; data_i++) {
+        int cur_bit_width_time = getBitWith(ts_block_delta.get(data_i).get(0));
+        int cur_bit_width_value = 
getBitWith(ts_block_delta.get(data_i).get(1));
+        if (cur_bit_width_time > bit_width_time) {
+          bit_width_time = cur_bit_width_time;
+        }
+        if (cur_bit_width_value > bit_width_value) {
+          bit_width_value = cur_bit_width_value;
+        }
+      }
+      ArrayList<Integer> bit_width = new ArrayList<>();
+      bit_width.add(bit_width_time);
+      bit_width.add(bit_width_value);
+      bit_width_segments.add(bit_width);
+    }
+
+    return bit_width_segments;
+  }
+
+  public static void moveAlphaToBeta(ArrayList<ArrayList<Integer>> ts_block, 
int alpha, int beta) {
+    ArrayList<Integer> tmp_tv = ts_block.get(alpha);
+    if (beta < alpha) {
+      for (int u = alpha - 1; u >= beta; u--) {
+        ArrayList<Integer> tmp_tv_cur = new ArrayList<>();
+        tmp_tv_cur.add(ts_block.get(u).get(0));
+        tmp_tv_cur.add(ts_block.get(u).get(1));
+        ts_block.set(u + 1, tmp_tv_cur);
+      }
+    } else {
+      for (int u = alpha + 1; u < beta; u++) {
+        ArrayList<Integer> tmp_tv_cur = new ArrayList<>();
+        tmp_tv_cur.add(ts_block.get(u).get(0));
+        tmp_tv_cur.add(ts_block.get(u).get(1));
+        ts_block.set(u - 1, tmp_tv_cur);
+      }
+      beta--;
+    }
+    ts_block.set(beta, tmp_tv);
+  }
+
+  private static int BOSBlockEncoderPartition(int[][] data, int i, int 
block_size,int segment_size,int k, int encode_pos , byte[] cur_byte) {
+
+
+//    ArrayList<ArrayList<Integer>> ts_block = new ArrayList<>();
+//    ArrayList<ArrayList<Integer>> ts_block_reorder = new ArrayList<>();
+//    ArrayList<ArrayList<Integer>> ts_block_partition = new ArrayList<>();
+    int min_time = data[i * block_size][0];
+    int[][] ts_block = new int[block_size][2];
+    int[][] ts_block_reorder = new int[block_size][2];
+    int[][] ts_block_partition = new int[block_size][2];
+    for (int j = 0; j < block_size; j++) {
+      data[j + i * block_size][0]-=min_time;
+      ts_block[j][0] = data[j + i * block_size][0];
+      ts_block[j][1] = data[j + i * block_size][1];
+      ts_block_reorder[j][0] = data[j + i * block_size][0];
+      ts_block_reorder[j][1] = data[j + i * block_size][1];
+    }
+
+
+
+    // raw-order
+    int[] raw_length = new int[5]; // 
length,max_bit_width_interval,max_bit_width_value,max_bit_width_deviation
+    float[] theta = new float[4];
+    int[][] ts_block_delta = getEncodeBitsRegression(ts_block, block_size, 
raw_length, theta, segment_size);
+    int[][] bit_width_segments_partition = segmentBitPacking(ts_block_delta, 
block_size, segment_size);
+    raw_length[0] = numberOfEncodeSegment2Bytes(ts_block_delta, 
bit_width_segments_partition, raw_length, segment_size, theta);
+
+    Arrays.sort(ts_block, (a, b) -> {
+      if(a[0]==b[0])
+        return Integer.compare(a[1], b[1]);
+      return Integer.compare(a[0], b[0]);
+    });
+//    quickSort(ts_block, 0, 0, block_size - 1);
+    int[] time_length = new int[5];// 
length,max_bit_width_interval,max_bit_width_value,max_bit_width_deviation
+    float[] theta_time = new float[4];
+    int[][] ts_block_delta_time = getEncodeBitsRegression(ts_block, 
block_size, time_length, theta_time, segment_size);
+    int[][] bit_width_segments_time = segmentBitPacking(ts_block_delta_time, 
block_size, segment_size);
+    time_length[0] = numberOfEncodeSegment2Bytes(ts_block_delta_time, 
bit_width_segments_time, time_length, segment_size, theta_time);
+
+
+    Arrays.sort(ts_block, (a, b) -> {
+      if(a[1]==b[1])
+        return Integer.compare(a[0], b[0]);
+      return Integer.compare(a[1], b[1]);
+    });
+    // value-order
+//    quickSort(ts_block, 1, 0, block_size - 1);
+
+    int[] reorder_length = new int[5];
+    float[] theta_reorder = new float[4];
+    int[][] ts_block_delta_reorder = getEncodeBitsRegression(ts_block, 
block_size, reorder_length, theta_reorder, segment_size);
+    int[][] bit_width_segments_value = 
segmentBitPacking(ts_block_delta_reorder, block_size, segment_size);
+    reorder_length[0] = numberOfEncodeSegment2Bytes(ts_block_delta_reorder, 
bit_width_segments_value, reorder_length, segment_size, theta_reorder);
+
+
+    int[] alpha_list;
+
+    int choose = min3(time_length[0], raw_length[0], reorder_length[0]);
+    ArrayList<Integer> min_index = new ArrayList<>();
+
+    if (choose == 0) {
+      raw_length = time_length;
+      Arrays.sort(ts_block, (a, b) -> {
+        if(a[0]==b[0])
+          return Integer.compare(a[1], b[1]);
+        return Integer.compare(a[0], b[0]);
+      });
+      theta = theta_time;
+      ts_block_delta = ts_block_delta_time;
+      alpha_list = getIStar(ts_block,min_index, block_size, 0, theta, k);
+    } else if (choose == 1) {
+      ts_block = ts_block_reorder;
+      alpha_list = getIStar(ts_block,min_index, block_size, 0, theta, k);
+    } else {
+      raw_length = reorder_length;
+      theta = theta_reorder;
+      ts_block_delta = ts_block_delta_reorder;
+      alpha_list = getIStar(ts_block,min_index, block_size, 1, theta, k);
+    }
+    int[] beta_list = new int[alpha_list.length];
+    int[][] new_length_list = new int[alpha_list.length][5];
+
+
+//    ArrayList<ArrayList<Integer>> new_length_list = new ArrayList<>();
+
+
+    for (int j = 0; j< alpha_list.length;j++) {
+      int alpha = alpha_list[j];
+      int[] new_length = raw_length.clone();
+      beta_list[j] = getBeta(ts_block, alpha, min_index,block_size, 
new_length, theta, segment_size, j, new_length_list);
+//      new_length_list.add(new_length);
+    }
+    ArrayList<Integer> isMoveable = isMovable(alpha_list, beta_list);
+    int adjust_count = 0;
+    while (isMoveable.size() != 0) {
+      if (adjust_count < block_size / 2 && adjust_count <= 20) {
+        adjust_count++;
+      } else {
+        break;
+      }
+      ArrayList<ArrayList<Integer>> all_length = new ArrayList<>();
+
+      for (int isMoveable_i : isMoveable) {
+        ArrayList<Integer> tmp = new ArrayList<>();
+        tmp.add(isMoveable_i);
+        tmp.add(new_length_list.get(isMoveable_i).get(0));
+        all_length.add(tmp);
+
+      }
+      quickSort(all_length, 1, 0, all_length.size() - 1);
+      if (all_length.get(0).get(1) <= raw_length.get(0)) {
+        ArrayList<ArrayList<Integer>> new_ts_block = 
(ArrayList<ArrayList<Integer>>) ts_block.clone();
+        moveAlphaToBeta(new_ts_block, 
alpha_list.get(all_length.get(0).get(0)), 
beta_list.get(all_length.get(0).get(0)));
+        ArrayList<Integer> new_length = new ArrayList<>();
+        ts_block_delta = getEncodeBitsRegression(new_ts_block, block_size, 
new_length, theta, segment_size);
+        ArrayList<ArrayList<Integer>> bit_width_segments= 
segmentBitPacking(ts_block_delta, block_size, segment_size);
+        new_length.set(0, encodeSegment2Bytes(ts_block_delta, 
bit_width_segments, new_length, segment_size, theta, result2).size());
+
+        if(new_length.get(0) <= raw_length.get(0)){
+          raw_length = new_length;
+          ts_block  = (ArrayList<ArrayList<Integer>>) new_ts_block.clone();
+        }else {
+          break;
+        }
+      } else {
+        break;
+      }
+      alpha_list = getIStar(ts_block, min_index,block_size, raw_length, theta, 
k);
+
+      int alpha_size = alpha_list.size();
+      for (int alpha_i = alpha_size - 1; alpha_i >= 0; alpha_i--) {
+        if (beta_list.contains(alpha_list.get(alpha_i))) {
+          alpha_list.remove(alpha_i);
+        }
+      }
+      beta_list = new ArrayList<>();
+
+      for (int alpha : alpha_list) {
+        ArrayList<Integer> new_length = (ArrayList<Integer>) 
raw_length.clone();
+        beta_list.add(getBeta(ts_block,alpha, min_index,  block_size, 
raw_length, theta, segment_size));
+        new_length_list.add(new_length);
+      }
+      isMoveable = isMovable(alpha_list, beta_list);
+    }
+    ts_block_delta = getEncodeBitsRegressionNoTrain(ts_block, block_size, 
raw_length, theta, segment_size);
+    ArrayList<ArrayList<Integer>> bit_width_segments = new ArrayList<>();
+    int segment_n = (block_size - 1) / segment_size;
+    for (int segment_i = 0; segment_i < segment_n; segment_i++) {
+      int bit_width_time = Integer.MIN_VALUE;
+      int bit_width_value = Integer.MIN_VALUE;
+
+      for (int data_i = segment_i * segment_size + 1; data_i < (segment_i + 1) 
* segment_size + 1; data_i++) {
+        int cur_bit_width_time = getBitWith(ts_block_delta.get(data_i).get(0));
+        int cur_bit_width_value = 
getBitWith(ts_block_delta.get(data_i).get(1));
+        if (cur_bit_width_time > bit_width_time) {
+          bit_width_time = cur_bit_width_time;
+        }
+        if (cur_bit_width_value > bit_width_value) {
+          bit_width_value = cur_bit_width_value;
+        }
+      }
+      ArrayList<Integer> bit_width = new ArrayList<>();
+      bit_width.add(bit_width_time);
+      bit_width.add(bit_width_value);
+      bit_width_segments.add(bit_width);
+    }
+
+
+    ArrayList<Byte> cur_encoded_result = encodeSegment2Bytes(ts_block_delta, 
bit_width_segments, raw_length, segment_size, theta, result2);
+
+    return encode_pos;
+  }
+
+  public static int ReorderingRegressionEncoder(
+          int[][] data, int block_size, int[] third_value, int segment_size, 
int k,  byte[] encoded_result) {
+    block_size++;
+//    ArrayList<Byte> encoded_result = new ArrayList<Byte>();
+    int length_all = data.length;
+    int encode_pos = 0;
+    int2Bytes(length_all,encode_pos,encoded_result);
+    encode_pos += 4;
+
+    int block_num = length_all / block_size;
+    int2Bytes(block_size,encode_pos,encoded_result);
+    encode_pos+= 4;
+
+    // ----------------------- compare the whole time series order by time, 
value and partition ---------------------------
+    int length_time = 0;
+    int length_value = 0;
+    int length_partition = 0;
+    ArrayList<ArrayList<Integer>> data_value = (ArrayList<ArrayList<Integer>>) 
data.clone();
+    quickSort(data_value, 1, 0, length_all - 1);
+
+    ArrayList<ArrayList<Integer>> data_partition = new ArrayList<>();
+
+    for (ArrayList<Integer> datum : data) {
+      if (datum.get(1) > third_value[third_value.length - 1]) {
+        data_partition.add(datum);
+      }
+    }
+    for (int third_i = third_value.length - 1; third_i > 0; third_i--) {
+      for (ArrayList<Integer> datum : data) {
+        if (datum.get(1) <= third_value[third_i] && datum.get(1) > 
third_value[third_i - 1]) {
+          data_partition.add(datum);
+        }
+      }
+    }
+    for (ArrayList<Integer> datum : data) {
+      if (datum.get(1) <= third_value[0]) {
+        data_partition.add(datum);
+      }
+    }
+    for (int i = 0; i < block_num; i++) {
+      ArrayList<ArrayList<Integer>> ts_block_time = new ArrayList<>();
+      ArrayList<ArrayList<Integer>> ts_block_value = new ArrayList<>();
+      ArrayList<ArrayList<Integer>> ts_block_partition = new ArrayList<>();
+
+      for (int j = 0; j < block_size; j++) {
+        ts_block_time.add(data.get(j + i * block_size));
+        ts_block_value.add(data_value.get(j + i * block_size));
+        ts_block_partition.add(data_partition.get(j + i * block_size));
+      }
+      ArrayList<Integer> result1 = new ArrayList<>();
+      splitTimeStamp3(ts_block_time, result1);
+      ArrayList<Integer> raw_length = new ArrayList<>();
+      ArrayList<Float> theta = new ArrayList<>();
+      ArrayList<ArrayList<Integer>> ts_block_delta = 
getEncodeBitsRegression(ts_block_time, block_size, raw_length, theta, 
segment_size);
+      ArrayList<ArrayList<Integer>> bit_width_segments = 
segmentBitPacking(ts_block_delta, block_size, segment_size);
+      length_time += encodeSegment2Bytes(ts_block_delta, bit_width_segments, 
raw_length, segment_size, theta, result1).size();
+
+
+      ArrayList<Integer> result2 = new ArrayList<>();
+      splitTimeStamp3(ts_block_value, result2);
+      ArrayList<Integer> raw_length_value = new ArrayList<>();
+      ArrayList<Float> theta_value = new ArrayList<>();
+      ArrayList<ArrayList<Integer>> ts_block_delta_value = 
getEncodeBitsRegression(ts_block_value, block_size, raw_length_value, 
theta_value, segment_size);
+      ArrayList<ArrayList<Integer>> bit_width_segments_value = 
segmentBitPacking(ts_block_delta_value, block_size, segment_size);
+      length_value += encodeSegment2Bytes(ts_block_delta_value, 
bit_width_segments_value, raw_length_value, segment_size, theta_value, 
result2).size();
+
+      ArrayList<Integer> result3 = new ArrayList<>();
+      splitTimeStamp3(ts_block_partition, result3);
+      ArrayList<Integer> raw_length_partition = new ArrayList<>();
+      ArrayList<Float> theta_partition = new ArrayList<>();
+      ArrayList<ArrayList<Integer>> ts_block_delta_partition = 
getEncodeBitsRegression(ts_block_partition, block_size, raw_length_partition, 
theta_partition, segment_size);
+      ArrayList<ArrayList<Integer>> bit_width_segments_partition = 
segmentBitPacking(ts_block_delta_partition, block_size, segment_size);
+      length_partition += encodeSegment2Bytes(ts_block_delta_partition, 
bit_width_segments_partition, raw_length_partition, segment_size, 
theta_partition, result3).size();
+
+    }
+    int remaining_length = length_all - block_num * block_size;
+
+
+    if (length_partition < length_time && length_partition < length_value) { 
// partition performs better
+      data = data_partition;
+
+
+      for (int i = 0; i < block_num; i++) {
+        encode_pos =  BOSBlockEncoderPartition(data, i, block_size, 
segment_size,k, encode_pos,encoded_result);
+
+      }
+    } else {
+      if (length_value < length_time) { // order by value performs better
+        System.out.println("type2");
+        data = data_value;
+      } else {
+        System.out.println("type1");
+      }
+      for (int i = 0; i < block_num; i++) {
+        ArrayList<ArrayList<Integer>> ts_block = new ArrayList<>();
+        ArrayList<ArrayList<Integer>> ts_block_reorder = new ArrayList<>();
+        ArrayList<ArrayList<Integer>> ts_block_partition = new ArrayList<>();
+        int min_time = data.get(i * block_size).get(0);
+        for (int j = 0; j < block_size; j++) {
+          data.get(j + i * block_size).set(0,data.get(j + i * 
block_size).get(0)-min_time);
+          ts_block.add(data.get(j + i * block_size));
+          ts_block_reorder.add(data.get(j + i * block_size));
+        }
+
+        ArrayList<Integer> result2 = new ArrayList<>();
+        //      result2.add(1);
+        splitTimeStamp3(ts_block, result2);
+        splitTimeStamp3(ts_block_reorder, result2);
+        quickSort(ts_block, 0, 0, block_size - 1);
+        ArrayList<Integer> raw_length = new ArrayList<>(); // 
length,max_bit_width_interval,max_bit_width_value,max_bit_width_deviation
+        ArrayList<Float> theta = new ArrayList<>();
+        ArrayList<ArrayList<Integer>> ts_block_delta = 
getEncodeBitsRegression(ts_block, block_size, raw_length, theta, segment_size);
+        ArrayList<ArrayList<Integer>> bit_width_segments_time = 
segmentBitPacking(ts_block_delta, block_size, segment_size);
+        raw_length.set(0, encodeSegment2Bytes(ts_block_delta, 
bit_width_segments_time, raw_length, segment_size, theta, result2).size());
+
+        // value-order
+        quickSort(ts_block, 1, 0, block_size - 1);
+
+        ArrayList<Integer> reorder_length = new ArrayList<>();
+        ArrayList<Float> theta_reorder = new ArrayList<>();
+        ArrayList<ArrayList<Integer>> ts_block_delta_reorder = 
getEncodeBitsRegression(ts_block, block_size, reorder_length, theta_reorder, 
segment_size);
+        ArrayList<ArrayList<Integer>> bit_width_segments_value = 
segmentBitPacking(ts_block_delta_reorder, block_size, segment_size);
+        reorder_length.set(0, encodeSegment2Bytes(ts_block_delta_reorder, 
bit_width_segments_value, reorder_length, segment_size, theta_reorder, 
result2).size());
+
+        for (ArrayList<Integer> datum : ts_block) {
+          if (datum.get(1) > third_value[third_value.length - 1]) {
+            ts_block_partition.add(datum);
+          }
+        }
+        for (int third_i = third_value.length - 1; third_i > 0; third_i--) {
+          for (ArrayList<Integer> datum : ts_block) {
+            if (datum.get(1) <= third_value[third_i] && datum.get(1) > 
third_value[third_i - 1]) {
+              ts_block_partition.add(datum);
+            }
+          }
+        }
+        for (ArrayList<Integer> datum : ts_block) {
+          if (datum.get(1) <= third_value[0]) {
+            ts_block_partition.add(datum);
+          }
+        }
+        ArrayList<Integer> partition_length = new ArrayList<>();
+        ArrayList<Float> theta_partition = new ArrayList<>();
+        ArrayList<ArrayList<Integer>> ts_block_delta_partition = 
getEncodeBitsRegression(ts_block_partition, block_size, partition_length, 
theta_partition, segment_size);
+        ArrayList<ArrayList<Integer>> bit_width_segments_partition = 
segmentBitPacking(ts_block_delta_partition, block_size, segment_size);
+        partition_length.set(0, encodeSegment2Bytes(ts_block_delta_partition, 
bit_width_segments_partition, partition_length, segment_size, theta_partition, 
result2).size());
+
+
+        int choose = min3(partition_length.get(0), reorder_length.get(0), 
raw_length.get(0));
+        ArrayList<Integer> alpha_list;
+        ArrayList<Integer> min_index = new ArrayList<>();
+        if (choose == 0) {
+          raw_length = partition_length;
+          ts_block = ts_block_partition;
+          ts_block_delta = ts_block_delta_partition;
+          theta = theta_partition;
+          alpha_list = getIStar(ts_block, min_index,block_size, 0, theta, k);
+        } else if (choose == 1) {
+          raw_length = reorder_length;
+          quickSort(ts_block, 1, 0, block_size - 1);
+          ts_block_delta = ts_block_delta_reorder;
+          theta = theta_reorder;
+          alpha_list = getIStar(ts_block,min_index, block_size, 1, theta, k);
+        } else {
+                    quickSort(ts_block, 0, 0, block_size - 1);
+          alpha_list = getIStar(ts_block,min_index, block_size, 0, theta, k);
+        }
+
+        ArrayList<Integer> beta_list= new ArrayList<>();
+        ArrayList<ArrayList<Integer>> new_length_list = new ArrayList<>();
+
+        for (int alpha : alpha_list) {
+          ArrayList<Integer> new_length = (ArrayList<Integer>) 
raw_length.clone();
+          beta_list.add(getBeta(ts_block, alpha, min_index,block_size, 
new_length, theta, segment_size));
+          new_length_list.add(new_length);
+        }
+        ArrayList<Integer> isMoveable = isMovable(alpha_list, beta_list);
+        int adjust_count = 0;
+        while (isMoveable.size() != 0) {
+          if (adjust_count < block_size / 2 && adjust_count <= 20) {
+            adjust_count++;
+          } else {
+            break;
+          }
+          ArrayList<ArrayList<Integer>> all_length = new ArrayList<>();
+
+          for (int isMoveable_i : isMoveable) {
+            ArrayList<Integer> tmp = new ArrayList<>();
+            tmp.add(isMoveable_i);
+            tmp.add(new_length_list.get(isMoveable_i).get(0));
+            all_length.add(tmp);
+
+          }
+          quickSort(all_length, 1, 0, all_length.size() - 1);
+          if (all_length.get(0).get(1) <= raw_length.get(0)) {
+            ArrayList<ArrayList<Integer>> new_ts_block = 
(ArrayList<ArrayList<Integer>>) ts_block.clone();
+            moveAlphaToBeta(new_ts_block, 
alpha_list.get(all_length.get(0).get(0)), 
beta_list.get(all_length.get(0).get(0)));
+            ArrayList<Integer> new_length = new ArrayList<>();
+            ts_block_delta = getEncodeBitsRegression(new_ts_block, block_size, 
new_length, theta, segment_size);
+            ArrayList<ArrayList<Integer>> bit_width_segments= 
segmentBitPacking(ts_block_delta, block_size, segment_size);
+            new_length.set(0, encodeSegment2Bytes(ts_block_delta, 
bit_width_segments, new_length, segment_size, theta, result2).size());
+
+            if(new_length.get(0) <= raw_length.get(0)){
+              raw_length = new_length;
+              ts_block  = (ArrayList<ArrayList<Integer>>) new_ts_block.clone();
+            }else {
+              break;
+            }
+          } else {
+            break;
+          }
+          alpha_list = getIStar(ts_block,min_index, block_size, raw_length, 
theta, k);
+          int alpha_size = alpha_list.size();
+          for (int alpha_i = alpha_size - 1; alpha_i >= 0; alpha_i--) {
+            if (beta_list.contains(alpha_list.get(alpha_i))) {
+              alpha_list.remove(alpha_i);
+            }
+          }
+          beta_list = new ArrayList<>();
+          for (int alpha : alpha_list) {
+            ArrayList<Integer> new_length = (ArrayList<Integer>) 
raw_length.clone();
+            beta_list.add(getBeta(ts_block, alpha, min_index,block_size, 
new_length, theta, segment_size));
+            new_length_list.add(new_length);
+          }
+          isMoveable = isMovable(alpha_list, beta_list);
+        }
+        ts_block_delta = getEncodeBitsRegressionNoTrain(ts_block, block_size, 
raw_length, theta, segment_size);
+        ArrayList<ArrayList<Integer>> bit_width_segments = new ArrayList<>();
+        int segment_n = (block_size - 1) / segment_size;
+        for (int segment_i = 0; segment_i < segment_n; segment_i++) {
+          int bit_width_time = Integer.MIN_VALUE;
+          int bit_width_value = Integer.MIN_VALUE;
+
+          for (int data_i = segment_i * segment_size + 1; data_i < (segment_i 
+ 1) * segment_size + 1; data_i++) {
+            int cur_bit_width_time = 
getBitWith(ts_block_delta.get(data_i).get(0));
+            int cur_bit_width_value = 
getBitWith(ts_block_delta.get(data_i).get(1));
+            if (cur_bit_width_time > bit_width_time) {
+              bit_width_time = cur_bit_width_time;
+            }
+            if (cur_bit_width_value > bit_width_value) {
+              bit_width_value = cur_bit_width_value;
+            }
+          }
+          ArrayList<Integer> bit_width = new ArrayList<>();
+          bit_width.add(bit_width_time);
+          bit_width.add(bit_width_value);
+          bit_width_segments.add(bit_width);
+        }
+
+        ArrayList<Byte> cur_encoded_result = 
encodeSegment2Bytes(ts_block_delta, bit_width_segments, raw_length, 
segment_size, theta, result2);
+        encoded_result.addAll(cur_encoded_result);
+
+      }
+    }
+
+
+    remaining_length = length_all - block_num * block_size;
+    if (remaining_length == 1) {
+      byte[] timestamp_end_bytes = int2Bytes(data.get(data.size() - 1).get(0));
+      for (byte b : timestamp_end_bytes) encoded_result.add(b);
+      byte[] value_end_bytes = int2Bytes(data.get(data.size() - 1).get(1));
+      for (byte b : value_end_bytes) encoded_result.add(b);
+    }
+    if (remaining_length != 0 && remaining_length != 1) {
+      ArrayList<ArrayList<Integer>> ts_block = new ArrayList<>();
+      ArrayList<ArrayList<Integer>> ts_block_reorder = new ArrayList<>();
+
+      int min_time = data.get(block_num * block_size).get(0);
+      for (int j = block_num * block_size; j < length_all; j++) {
+        data.get(j).set(0,data.get(j).get(0) - min_time);
+        ts_block.add(data.get(j));
+        ts_block_reorder.add(data.get(j));
+      }
+      ArrayList<Integer> result2 = new ArrayList<>();
+      splitTimeStamp3(ts_block, result2);
+
+      quickSort(ts_block, 0, 0, remaining_length - 1);
+
+      // time-order
+      ArrayList<Integer> raw_length =
+              new ArrayList<>(); // 
length,max_bit_width_interval,max_bit_width_value,max_bit_width_deviation
+      ArrayList<Integer> i_star_ready = new ArrayList<>();
+      ArrayList<Float> theta = new ArrayList<>();
+      ArrayList<ArrayList<Integer>> ts_block_delta =
+              getEncodeBitsRegression(ts_block, remaining_length, raw_length, 
theta, segment_size);
+
+      // value-order
+      quickSort(ts_block, 1, 0, remaining_length - 1);
+      ArrayList<Integer> reorder_length = new ArrayList<>();
+      ArrayList<Integer> i_star_ready_reorder = new ArrayList<>();
+      ArrayList<Float> theta_reorder = new ArrayList<>();
+      ArrayList<ArrayList<Integer>> ts_block_delta_reorder =
+              getEncodeBitsRegression(
+                      ts_block, remaining_length, reorder_length, 
theta_reorder, segment_size);
+
+      if (raw_length.get(0) <= reorder_length.get(0)) {
+        quickSort(ts_block, 0, 0, remaining_length - 1);
+      } else {
+        raw_length = reorder_length;
+        theta = theta_reorder;
+        quickSort(ts_block, 1, 0, remaining_length - 1);
+      }
+      ts_block_delta =
+              getEncodeBitsRegression(ts_block, remaining_length, raw_length, 
theta, segment_size);
+      int supple_length;
+      if (remaining_length % 8 == 0) {
+        supple_length = 1;
+      } else if (remaining_length % 8 == 1) {
+        supple_length = 0;
+      } else {
+        supple_length = 9 - remaining_length % 8;
+      }
+      for (int s = 0; s < supple_length; s++) {
+        ArrayList<Integer> tmp = new ArrayList<>();
+        tmp.add(0);
+        tmp.add(0);
+        ts_block_delta.add(tmp);
+      }
+      ArrayList<Byte> cur_encoded_result = encode2Bytes(ts_block_delta, 
raw_length, theta, result2);
+
+      encoded_result.addAll(cur_encoded_result);
+    }
+    return encoded_result;
+  }
+
+  private static ArrayList<Integer> isMovable(ArrayList<Integer> alpha_list, 
ArrayList<Integer> beta_list) {
+    ArrayList<Integer> isMoveable = new ArrayList<>();
+    for (int i = 0; i < alpha_list.size(); i++) {
+      if (alpha_list.get(i) != -1 && beta_list.get(i) != -1) {
+        isMoveable.add(i);
+      }
+    }
+    return isMoveable;
+  }
+
+  private static int numberOfEncodeSegment2Bytes(int[][] 
delta_segments,int[][]  bit_width_segments, int[] raw_length, int segment_size, 
float[] theta) {
+    ArrayList<Byte> encoded_result = new ArrayList<>();
+    int block_size = delta_segments.length;
+    int segment_n = block_size / segment_size;
+    int result = 0;
+    result += 8; // encode interval0 and value0
+    result += 16; // encode theta
+    result += encodeRLEBitWidth2Bytes(bit_width_segments);
+//    // encode interval0 and value0
+//    byte[] interval0_byte = int2Bytes(delta_segments.get(0).get(0));
+//    for (byte b : interval0_byte) encoded_result.add(b);
+//    byte[] value0_byte = int2Bytes(delta_segments.get(0).get(1));
+//    for (byte b : value0_byte) encoded_result.add(b);
+//
+//    // encode theta
+//    byte[] theta0_r_byte = float2bytes(theta.get(0) + raw_length.get(3));
+//    for (byte b : theta0_r_byte) encoded_result.add(b);
+//    byte[] theta1_r_byte = float2bytes(theta.get(1));
+//    for (byte b : theta1_r_byte) encoded_result.add(b);
+//    byte[] theta0_v_byte = float2bytes(theta.get(2) + raw_length.get(4));
+//    for (byte b : theta0_v_byte) encoded_result.add(b);
+//    byte[] theta1_v_byte = float2bytes(theta.get(3));
+//    for (byte b : theta1_v_byte) encoded_result.add(b);
+//    encoded_result.addAll(encodeRLEBitWidth2Bytes(bit_width_segments));
+    for (int segment_i = 0; segment_i < segment_n; segment_i++) {
+      int bit_width_time = bit_width_segments[segment_i][0];
+      int bit_width_value = bit_width_segments[segment_i][1];
+      result += (segment_size*bit_width_time/8);
+      result += (segment_size*bit_width_value/8);
+    }
+
+//    byte[] td_common_byte = int2Bytes(result2.get(0));
+//    for (byte b : td_common_byte) encoded_result.add(b);
+
+    return result;
+  }
+  private static ArrayList<Byte> 
encodeSegment2Bytes(ArrayList<ArrayList<Integer>> delta_segments, 
ArrayList<ArrayList<Integer>> bit_width_segments, ArrayList<Integer> 
raw_length, int segment_size, ArrayList<Float> theta) {
+    ArrayList<Byte> encoded_result = new ArrayList<>();
+    int block_size = delta_segments.size();
+    int segment_n = block_size / segment_size;
+
+    // encode interval0 and value0
+    byte[] interval0_byte = int2Bytes(delta_segments.get(0).get(0));
+    for (byte b : interval0_byte) encoded_result.add(b);
+    byte[] value0_byte = int2Bytes(delta_segments.get(0).get(1));
+    for (byte b : value0_byte) encoded_result.add(b);
+
+    // encode theta
+    byte[] theta0_r_byte = float2bytes(theta.get(0) + raw_length.get(3));
+    for (byte b : theta0_r_byte) encoded_result.add(b);
+    byte[] theta1_r_byte = float2bytes(theta.get(1));
+    for (byte b : theta1_r_byte) encoded_result.add(b);
+    byte[] theta0_v_byte = float2bytes(theta.get(2) + raw_length.get(4));
+    for (byte b : theta0_v_byte) encoded_result.add(b);
+    byte[] theta1_v_byte = float2bytes(theta.get(3));
+    for (byte b : theta1_v_byte) encoded_result.add(b);
+    encoded_result.addAll(encodeRLEBitWidth2Bytes(bit_width_segments));
+    for (int segment_i = 0; segment_i < segment_n; segment_i++) {
+      int bit_width_time = bit_width_segments.get(segment_i).get(0);
+      int bit_width_value = bit_width_segments.get(segment_i).get(1);
+      byte[] timestamp_bytes = bitPacking(delta_segments, 0, segment_i * 
segment_size + 1, segment_size, bit_width_time);
+      for (byte b : timestamp_bytes) encoded_result.add(b);
+      byte[] value_bytes = bitPacking(delta_segments, 1, segment_i * 
segment_size + 1, segment_size, bit_width_value);
+      for (byte b : value_bytes) encoded_result.add(b);
+    }
+
+//    byte[] td_common_byte = int2Bytes(result2.get(0));
+//    for (byte b : td_common_byte) encoded_result.add(b);
+
+    return encoded_result;
+  }
+
+  public static ArrayList<ArrayList<Integer>> 
ReorderingRegressionDecoder(ArrayList<Byte> encoded) {
+    ArrayList<ArrayList<Integer>> data = new ArrayList<>();
+    int decode_pos = 0;
+    int length_all = bytes2Integer(encoded, decode_pos, 4);
+    decode_pos += 4;
+    int block_size = bytes2Integer(encoded, decode_pos, 4);
+    decode_pos += 4;
+
+    int block_num = length_all / block_size;
+    int remain_length = length_all - block_num * block_size;
+    int zero_number;
+    if (remain_length % 8 == 0) {
+      zero_number = 1;
+    } else if (remain_length % 8 == 1) {
+      zero_number = 0;
+    } else {
+      zero_number = 9 - remain_length % 8;
+    }
+
+    for (int k = 0; k < block_num; k++) {
+      ArrayList<Integer> time_list = new ArrayList<>();
+      ArrayList<Integer> value_list = new ArrayList<>();
+
+      ArrayList<ArrayList<Integer>> ts_block = new ArrayList<>();
+
+      int time0 = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+      int value0 = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+
+      float theta0_r = bytes2float(encoded, decode_pos);
+      decode_pos += 4;
+      float theta1_r = bytes2float(encoded, decode_pos);
+      decode_pos += 4;
+      float theta0_v = bytes2float(encoded, decode_pos);
+      decode_pos += 4;
+      float theta1_v = bytes2float(encoded, decode_pos);
+      decode_pos += 4;
+
+
+      // get bit_width_segments
+      ArrayList<Integer> bit_width_segments_time = new ArrayList<>();
+      ArrayList<Integer> bit_width_segments_value = new ArrayList<>();
+      int sum_time_bit_width = 0;
+      int sum_value_bit_width = 0;
+      int segment_n = (block_size - 1) / 8;
+      while (sum_time_bit_width != segment_n) {
+        int max_bit_width_time_nums = bytes2BitWidth(encoded, decode_pos, 1);
+        decode_pos += 1;
+        int max_bit_width_time = bytes2BitWidth(encoded, decode_pos, 1);
+        decode_pos += 1;
+        sum_time_bit_width += max_bit_width_time_nums;
+        for (int i = 0; i < max_bit_width_time_nums; i++) {
+          bit_width_segments_time.add(max_bit_width_time);
+        }
+      }
+      while (sum_value_bit_width != segment_n) {
+        int max_bit_width_value_nums = bytes2BitWidth(encoded, decode_pos, 1);
+        decode_pos += 1;
+        int max_bit_width_value = bytes2BitWidth(encoded, decode_pos, 1);
+        decode_pos += 1;
+        sum_value_bit_width += max_bit_width_value_nums;
+        for (int i = 0; i < max_bit_width_value_nums; i++) {
+          bit_width_segments_value.add(max_bit_width_value);
+        }
+      }
+
+
+      for (int i = 0; i < segment_n; i++) {
+        int max_bit_width_time = bit_width_segments_time.get(i);
+        ArrayList<Integer> tmp_time_list = decodebitPacking(encoded, 
decode_pos, max_bit_width_time, 0, 9);
+        decode_pos += max_bit_width_time * 8;
+        time_list.addAll(tmp_time_list);
+        int max_bit_width_value = bit_width_segments_value.get(i);
+        ArrayList<Integer> tmp_value_list = decodebitPacking(encoded, 
decode_pos, max_bit_width_value, 0, 9);
+        decode_pos += max_bit_width_value * 8;
+        value_list.addAll(tmp_value_list);
+      }
+
+
+      int td_common = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+
+      int ti_pre = time0;
+      int vi_pre = value0;
+      for (int i = 0; i < block_size - 1; i++) {
+        int ti = (int) ((double) theta0_r + (double) theta1_r * (double) 
ti_pre) + time_list.get(i);
+        time_list.set(i, ti);
+        ti_pre = ti;
+
+        int vi =
+                (int) ((double) theta0_v + (double) theta1_v * (double) 
vi_pre) + value_list.get(i);
+        value_list.set(i, vi);
+        vi_pre = vi;
+      }
+
+      ArrayList<Integer> ts_block_tmp0 = new ArrayList<>();
+      ts_block_tmp0.add(time0);
+      ts_block_tmp0.add(value0);
+      ts_block.add(ts_block_tmp0);
+      for (int i = 0; i < block_size - 1; i++) {
+        int ti = (time_list.get(i) - time0) * td_common + time0;
+        ArrayList<Integer> ts_block_tmp = new ArrayList<>();
+        ts_block_tmp.add(ti);
+        ts_block_tmp.add(value_list.get(i));
+        ts_block.add(ts_block_tmp);
+      }
+      quickSort(ts_block, 0, 0, block_size - 1);
+      data.addAll(ts_block);
+    }
+
+    if (remain_length == 1) {
+      int timestamp_end = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+      int value_end = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+      ArrayList<Integer> ts_block_end = new ArrayList<>();
+      ts_block_end.add(timestamp_end);
+      ts_block_end.add(value_end);
+      data.add(ts_block_end);
+    }
+    if (remain_length != 0 && remain_length != 1) {
+      ArrayList<Integer> time_list = new ArrayList<>();
+      ArrayList<Integer> value_list = new ArrayList<>();
+
+      ArrayList<ArrayList<Integer>> ts_block = new ArrayList<>();
+
+      int time0 = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+      int value0 = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+
+      float theta0_r = bytes2float(encoded, decode_pos);
+      decode_pos += 4;
+      float theta1_r = bytes2float(encoded, decode_pos);
+      decode_pos += 4;
+      float theta0_v = bytes2float(encoded, decode_pos);
+      decode_pos += 4;
+      float theta1_v = bytes2float(encoded, decode_pos);
+      decode_pos += 4;
+
+      int max_bit_width_time = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+      time_list =
+              decodebitPacking(encoded, decode_pos, max_bit_width_time, 0, 
remain_length + zero_number);
+      decode_pos += max_bit_width_time * (remain_length + zero_number - 1) / 8;
+
+      int max_bit_width_value = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+      value_list =
+              decodebitPacking(
+                      encoded, decode_pos, max_bit_width_value, 0, 
remain_length + zero_number);
+      decode_pos += max_bit_width_value * (remain_length + zero_number - 1) / 
8;
+
+      int td_common = bytes2Integer(encoded, decode_pos, 4);
+      decode_pos += 4;
+
+      int ti_pre = time0;
+      int vi_pre = value0;
+      for (int i = 0; i < remain_length - 1; i++) {
+        int ti = (int) ((double) theta0_r + (double) theta1_r * (double) 
ti_pre) + time_list.get(i);
+        time_list.set(i, ti);
+        ti_pre = ti;
+        int vi =
+                (int) ((double) theta0_v + (double) theta1_v * (double) 
vi_pre) + value_list.get(i);
+        value_list.set(i, vi);
+        vi_pre = vi;
+      }
+
+      ArrayList<Integer> ts_block_tmp0 = new ArrayList<>();
+      ts_block_tmp0.add(time0);
+      ts_block_tmp0.add(value0);
+      ts_block.add(ts_block_tmp0);
+      for (int i = 0; i < remain_length - 1; i++) {
+        int ti = (time_list.get(i) - time0) * td_common + time0;
+        ArrayList<Integer> ts_block_tmp = new ArrayList<>();
+        ts_block_tmp.add(ti);
+        ts_block_tmp.add(value_list.get(i));
+        ts_block.add(ts_block_tmp);
+      }
+
+      quickSort(ts_block, 0, 0, remain_length - 1);
+      for (int i = 0; i < remain_length; i++) {
+        data.add(ts_block.get(i));
+      }
+    }
+    return data;
+  }
+
+
+  public static void main(@org.jetbrains.annotations.NotNull String[] args) 
throws IOException {
+//        String parent_dir = "C:/Users/xiaoj/Desktop/test";
+    String parent_dir = 
"/Users/xiaojinzhao/Documents/GitHub/iotdb/iotdb-core/tsfile/src/test/resources/";
+    String output_parent_dir = 
"/Users/xiaojinzhao/Documents/GitHub/encoding-reorder/compression_ratio";
+
+
+    String input_parent_dir = parent_dir + "trans_data/";
+    ArrayList<String> input_path_list = new ArrayList<>();
+    ArrayList<String> output_path_list = new ArrayList<>();
+    ArrayList<String> dataset_name = new ArrayList<>();
+    ArrayList<Integer> dataset_block_size = new ArrayList<>();
+    ArrayList<Integer> dataset_mid = new ArrayList<>();
+    ArrayList<int[]> dataset_third = new ArrayList<>();
+    ArrayList<Integer> dataset_k = new ArrayList<>();
+        dataset_name.add("CS-Sensors");
+    dataset_name.add("Metro-Traffic");
+    dataset_name.add("USGS-Earthquakes");
+    dataset_name.add("YZ-Electricity");
+    dataset_name.add("GW-Magnetic");
+    dataset_name.add("TY-Fuel");
+    dataset_name.add("Cyber-Vehicle");
+    dataset_name.add("Vehicle-Charge");
+    dataset_name.add("Nifty-Stocks");
+    dataset_name.add("TH-Climate");
+    dataset_name.add("TY-Transport");
+    dataset_name.add("EPM-Education");
+
+    int[] dataset_0 = {547,2816};
+    int[] dataset_1 = {1719,3731};
+    int[] dataset_2 = {-48,-11,6,25,52};
+    int[] dataset_3 = {8681,13584};
+    int[] dataset_4 = {79,184,274};
+    int[] dataset_5 = {17,68};
+    int[] dataset_6 = {677};
+    int[] dataset_7 = {1047,1725};
+    int[] dataset_8 = {227,499,614,1013};
+    int[] dataset_9 = {474,678};
+    int[] dataset_10 = {4,30,38,49,58};
+    int[] dataset_11 = {5182,8206};
+
+    dataset_third.add(dataset_0);
+    dataset_third.add(dataset_1);
+    dataset_third.add(dataset_2);
+    dataset_third.add(dataset_3);
+    dataset_third.add(dataset_4);
+    dataset_third.add(dataset_5);
+    dataset_third.add(dataset_6);
+    dataset_third.add(dataset_7);
+    dataset_third.add(dataset_8);
+    dataset_third.add(dataset_9);
+    dataset_third.add(dataset_10);
+    dataset_third.add(dataset_11);
+
+    for (int i = 0; i < dataset_name.size(); i++) {
+      input_path_list.add(input_parent_dir + dataset_name.get(i));
+      dataset_k.add(1);
+    }
+
+    output_path_list.add(output_parent_dir + "/CS-Sensors_ratio.csv"); // 0
+    dataset_block_size.add(1024);
+
+    output_path_list.add(output_parent_dir + "/Metro-Traffic_ratio.csv");// 1
+    dataset_block_size.add(512);
+    output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 
2
+    dataset_block_size.add(512);
+    output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+    dataset_block_size.add(256);
+    output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+    dataset_block_size.add(128);
+    output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+    dataset_block_size.add(64);
+    output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+    dataset_block_size.add(128);
+    output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+    dataset_block_size.add(512);
+    output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+    dataset_block_size.add(256);
+    output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+    dataset_block_size.add(512);
+    output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+    dataset_block_size.add(512);
+    output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+    dataset_block_size.add(512);
+
+//    for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+    for (int file_i = 9; file_i < 10; file_i++) {
+      String inputPath = input_path_list.get(file_i);
+      String Output = output_path_list.get(file_i);
+
+      int repeatTime = 1; // set repeat time
+
+      File file = new File(inputPath);
+      File[] tempList = file.listFiles();
+
+      CsvWriter writer = new CsvWriter(Output, ',', StandardCharsets.UTF_8);
+
+      String[] head = {
+        "Input Direction",
+        "Encoding Algorithm",
+        "Encoding Time",
+        "Decoding Time",
+        "Points",
+        "Compressed Size",
+        "Compression Ratio"
+      };
+      writer.writeRecord(head); // write header to output file
+
+      assert tempList != null;
+
+      for (File f : tempList) {
+        System.out.println(f);
+        InputStream inputStream = Files.newInputStream(f.toPath());
+        CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+        ArrayList<ArrayList<Integer>> data = new ArrayList<>();
+
+        ArrayList<ArrayList<Integer>> data_decoded = new ArrayList<>();
+
+        // add a column to "data"
+        loader.readHeaders();
+        data.clear();
+        while (loader.readRecord()) {
+          ArrayList<Integer> tmp = new ArrayList<>();
+          tmp.add(Integer.valueOf(loader.getValues()[0]));
+          tmp.add(Integer.valueOf(loader.getValues()[1]));
+           data.add(tmp);
+        }
+        inputStream.close();
+        ArrayList<Integer> result2 = new ArrayList<>();
+        splitTimeStamp3(data, result2);
+
+        int[][] data2_arr = new int[data.size()][2];
+        for(int i = 0;i<data.size();i++){
+          data2_arr[i][0] = data.get(i).get(0);
+          data2_arr[i][1] = data.get(i).get(1);
+        }
+        System.out.println(data2_arr[0][0]);
+        byte[] encoded_result = new byte[data2_arr.length*8];
+        long encodeTime = 0;
+        long decodeTime = 0;
+        double ratio = 0;
+        double compressed_size = 0;
+        int repeatTime2 = 1;
+          long s = System.nanoTime();
+          ArrayList<Byte> buffer = new ArrayList<>();
+          int length = 0;
+          for (int repeat = 0; repeat < repeatTime2; repeat++)
+            length = ReorderingRegressionEncoder(data2_arr, 
dataset_block_size.get(file_i), dataset_third.get(file_i), 8, 
dataset_k.get(file_i), encoded_result);
+          long e = System.nanoTime();
+          encodeTime += ((e - s) / repeatTime2);
+          compressed_size += length;
+          double ratioTmp = (double) buffer.size() / (double) (data.size() * 
Integer.BYTES * 2);
+          ratio += ratioTmp;
+          s = System.nanoTime();
+          e = System.nanoTime();
+          decodeTime += ((e - s) / repeatTime2);
+
+
+        String[] record = {
+          f.toString(),
+          "REGER",
+          String.valueOf(encodeTime),
+          String.valueOf(decodeTime),
+          String.valueOf(data.size()),
+          String.valueOf(compressed_size),
+          String.valueOf(ratio)
+        };
+        writer.writeRecord(record);
+
+      }
+      writer.close();
+    }
+  }
+}

Reply via email to